from django import forms from .models import Seller, CardListing, PackListing, Game, Bounty, BountyOffer from users.models import Profile class SellerThemeForm(forms.ModelForm): class Meta: model = Profile fields = ['theme_preference'] widgets = { 'theme_preference': forms.Select(attrs={'class': 'form-select'}) } class SellerRegistrationForm(forms.ModelForm): street = forms.CharField(max_length=200, widget=forms.TextInput(attrs={'placeholder': 'Street Address'})) city = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'placeholder': 'City'})) state = forms.CharField(max_length=100, widget=forms.TextInput(attrs={'placeholder': 'State'})) zip_code = forms.CharField(max_length=20, widget=forms.TextInput(attrs={'placeholder': 'Zip Code'})) class Meta: model = Seller fields = ['store_name', 'description', 'contact_email', 'contact_phone'] widgets = { 'description': forms.Textarea(attrs={'rows': 4}), } def save(self, commit=True): seller = super().save(commit=False) # Create address # We need the user to link the address to? The Seller model has user. # But here seller.user might not be set yet if it's done in the view. # However, save(commit=True) usually saves. # We'll create the Address instance but we need the user. # We can't easily get the user here unless we pass it or it's already on seller. # In the view `seller_register`, we do `form.instance.user = request.user` before saving? # Let's check `seller_register` view. # If we can't create Address yet, we might need to handle it in the view. # BUT, standard ModelForm save() returns the instance. # Let's attach the address data to the instance temporarily? # Or better: Override save to creating the Address. # We will assume seller.user is set by the view before save is called, # or we just create the address without user first (but user is required in Address model). # Actually, Address.user is required. # So we MUST have the user. return seller class SellerEditForm(forms.ModelForm): street = forms.CharField(max_length=200, required=False) city = forms.CharField(max_length=100, required=False) state = forms.CharField(max_length=100, required=False) zip_code = forms.CharField(max_length=20, required=False) tax_id = forms.CharField(required=False, widget=forms.TextInput(attrs={'type': 'password'}), help_text="SSN, ITIN, or EIN (Stored securely)") payout_details = forms.CharField(required=False, widget=forms.Textarea(attrs={'rows': 3}), help_text="Bank account or other payout details (Stored securely)") class Meta: model = Seller fields = ['store_name', 'description', 'contact_email', 'contact_phone', 'store_image', 'hero_image', 'minimum_order_amount', 'shipping_cost', 'tax_id', 'payout_details'] widgets = { 'description': forms.Textarea(attrs={'rows': 4}), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.instance and self.instance.pk: self.fields['tax_id'].initial = self.instance.tax_id self.fields['payout_details'].initial = self.instance.payout_details # Populate address fields if self.instance.store_address: self.fields['street'].initial = self.instance.store_address.street self.fields['city'].initial = self.instance.store_address.city self.fields['state'].initial = self.instance.store_address.state self.fields['zip_code'].initial = self.instance.store_address.zip_code def save(self, commit=True): seller = super().save(commit=False) seller.tax_id = self.cleaned_data.get('tax_id') seller.payout_details = self.cleaned_data.get('payout_details') # Handle Address # We need to update existing or create new. street = self.cleaned_data.get('street') city = self.cleaned_data.get('city') state = self.cleaned_data.get('state') zip_code = self.cleaned_data.get('zip_code') if street and city and state and zip_code: from users.models import Address if seller.store_address: seller.store_address.street = street seller.store_address.city = city seller.store_address.state = state seller.store_address.zip_code = zip_code if commit: seller.store_address.save() else: # Create new address. Requires user. # seller.user should exist. address = Address( user=seller.user, name=seller.store_name, # Use store name for address name street=street, city=city, state=state, zip_code=zip_code, address_type='shipping' # Default ) if commit: address.save() seller.store_address = address if commit: seller.save() return seller class CardListingForm(forms.ModelForm): class Meta: model = CardListing fields = ['condition', 'price', 'quantity', 'status', 'image'] # TODO: Add search widget for card selection or filter by game/set class PackListingForm(forms.ModelForm): class Meta: model = PackListing fields = ['game', 'name', 'listing_type', 'price', 'quantity', 'image_url'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Helper to indicate quantity logic self.fields['quantity'].help_text = "For Virtual packs, this is automatically updated based on inventory." class AddCardListingForm(forms.Form): card_name = forms.CharField(max_length=200, label="Card Name", help_text="Enter the card name.") game = forms.ModelChoiceField(queryset=Game.objects.all(), empty_label="Select Game") set_name = forms.CharField(max_length=200, label="Set Name", help_text="Enter the set name (e.g., 'Alpha', 'Base Set').") collector_number = forms.CharField(max_length=20, required=False, label="Card Number", help_text="The number on the bottom of the card (e.g. '197'). Useful for variants.") condition = forms.ChoiceField(choices=CardListing.CONDITION_CHOICES) price = forms.DecimalField(max_digits=10, decimal_places=2) quantity = forms.IntegerField(min_value=1, initial=1) image = forms.ImageField(required=False, label="Card Image") class BountyForm(forms.ModelForm): card_name = forms.CharField(max_length=200, label="Card Name", help_text="Search for a card...", required=False) card_id = forms.CharField(widget=forms.HiddenInput(), required=False) class Meta: model = Bounty fields = ['title', 'description', 'target_price', 'quantity_wanted'] widgets = { 'description': forms.Textarea(attrs={'rows': 3}), } def clean(self): cleaned_data = super().clean() card_id = cleaned_data.get('card_id') title = cleaned_data.get('title') card_name = cleaned_data.get('card_name') if not card_id and not title and not card_name: raise forms.ValidationError("You must either select a Card or provide a Title.") return cleaned_data class BountyOfferForm(forms.ModelForm): class Meta: model = BountyOffer fields = ['price', 'description'] widgets = { 'description': forms.Textarea(attrs={'rows': 3}), } class MultipleFileInput(forms.ClearableFileInput): allow_multiple_selected = True class BulkListingForm(forms.Form): csv_file = forms.FileField(label="Upload CSV", help_text="Upload the filled-out template CSV.") images = forms.FileField(widget=MultipleFileInput(attrs={'multiple': True}), required=False, label="Upload Images", help_text="Select all images referenced in your CSV.") class CheckoutForm(forms.Form): shipping_address = forms.ModelChoiceField(queryset=None, empty_label="Select Shipping Address", widget=forms.Select(attrs={'class': 'form-select'})) payment_method = forms.ModelChoiceField(queryset=None, empty_label="Select Payment Method", widget=forms.Select(attrs={'class': 'form-select'})) def __init__(self, *args, **kwargs): user = kwargs.pop('user', None) super().__init__(*args, **kwargs) if user: from users.models import Address, PaymentMethod self.fields['shipping_address'].queryset = Address.objects.filter(user=user, address_type='shipping') self.fields['payment_method'].queryset = PaymentMethod.objects.filter(user=user)