# Custom Resource Types & Logo Upload - Implementation Plan ## Overview Allow businesses to create custom resource types (e.g., "Stylist", "Massage Therapist", "Treatment Room") instead of hardcoded types. Also add logo upload to business branding. ## Features ### 1. Custom Resource Types - **Default Types**: Always include one "Staff" type (cannot be deleted) - **Custom Names**: Users can name types whatever they want (e.g., "Hair Stylist", "Nail Technician", "Massage Room") - **Categories**: Each type has a category: - `STAFF`: Requires staff member assignment - `OTHER`: No staff assignment needed - **Management**: Add, edit, delete custom types in Business Settings ### 2. Logo Upload - Upload business logo in branding section - Support PNG, JPG, SVG - Preview before saving - Used in customer-facing pages ## Database Changes ### Backend Models ```python # smoothschedule/schedule/models.py class ResourceType(models.Model): """Custom resource type definitions per business""" business = models.ForeignKey('tenants.Business', on_delete=models.CASCADE, related_name='resource_types') name = models.CharField(max_length=100) # "Stylist", "Treatment Room", etc. category = models.CharField(max_length=10, choices=[ ('STAFF', 'Staff'), ('OTHER', 'Other'), ]) is_default = models.BooleanField(default=False) # Cannot be deleted icon_name = models.CharField(max_length=50, null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) class Meta: unique_together = ['business', 'name'] ordering = ['name'] def __str__(self): return f"{self.business.name} - {self.name}" class Resource(models.Model): """Update existing Resource model""" # ... existing fields ... # NEW FIELD - references custom resource type resource_type = models.ForeignKey( ResourceType, on_delete=models.PROTECT, # Cannot delete type if resources use it related_name='resources', null=True, # For migration blank=True ) # DEPRECATED - keep for backwards compatibility during migration type = models.CharField( max_length=20, choices=[('STAFF', 'Staff'), ('ROOM', 'Room'), ('EQUIPMENT', 'Equipment')], default='STAFF' ) # smoothschedule/tenants/models.py class Business(models.Model): # ... existing fields ... # NEW FIELD - logo upload logo = models.ImageField(upload_to='business_logos/', null=True, blank=True) ``` ### Migration Strategy 1. Create `ResourceType` model 2. For each business, create default resource types: - "Staff" (category=STAFF, is_default=True) - "Room" (category=OTHER, is_default=True) - "Equipment" (category=OTHER, is_default=True) 3. Migrate existing resources to use default types based on their `type` field 4. Eventually deprecate `Resource.type` field ## API Endpoints ### Resource Types ``` GET /api/resource-types/ # List business resource types POST /api/resource-types/ # Create new type PATCH /api/resource-types/{id}/ # Update type DELETE /api/resource-types/{id}/ # Delete type (if not in use & not default) ``` ### Logo Upload ``` POST /api/business/logo/ # Upload logo DELETE /api/business/logo/ # Remove logo ``` ## Frontend Implementation ### 1. Business Settings - Resource Types Tab ```tsx // Add new tab to Settings.tsx ``` ### ResourceTypesManager Component ```tsx interface ResourceTypesManagerProps {} const ResourceTypesManager: React.FC = () => { const { data: types = [] } = useResourceTypes(); const createMutation = useCreateResourceType(); const updateMutation = useUpdateResourceType(); const deleteMutation = useDeleteResourceType(); return (

Resource Types

Customize how you categorize your bookable resources.

{/* List of types */} {types.map(type => ( ))} {/* Add new type button */} {/* Create/Edit Modal */}
); }; ``` ### 2. Logo Upload in Branding Section ```tsx // In Settings.tsx, Branding section

Business Logo

{/* Logo preview */} {business.logoUrl && (
Business logo
)} {/* Upload button */}
``` ### 3. Update Resources.tsx to use custom types ```tsx // Resources.tsx const Resources: React.FC = () => { const { data: resourceTypes = [] } = useResourceTypes(); return ( {/* Show staff selector if selected type is STAFF category */} {selectedType?.category === 'STAFF' && ( )} ); }; ``` ## Implementation Steps ### Phase 1: Backend Foundation 1. ✅ Create TypeScript types (DONE) 2. ⏳ Create Django models (`ResourceType`, add `Business.logo`) 3. ⏳ Create migrations with default data 4. ⏳ Create serializers 5. ⏳ Create API views and URLs 6. ⏳ Add file upload handling for logos ### Phase 2: Frontend Hooks & Types 1. ✅ Create `useResourceTypes` hook (DONE) 2. ⏳ Create logo upload utilities 3. ⏳ Update `Resource` type to include `typeId` ### Phase 3: UI Components 1. ⏳ Add "Resource Types" tab to Settings 2. ⏳ Create ResourceTypesManager component 3. ⏳ Create ResourceTypeModal component 4. ⏳ Add logo upload to Branding section 5. ⏳ Update Resources page to use custom types ### Phase 4: Migration & Testing 1. ⏳ Test creating/editing/deleting types 2. ⏳ Test logo upload/removal 3. ⏳ Ensure backwards compatibility 4. ⏳ Test resource creation with custom types ## User Experience ### Creating a Custom Resource Type 1. Navigate to Business Settings → Resource Types 2. Click "+ Add Resource Type" 3. Enter name (e.g., "Massage Therapist") 4. Select category: Staff or Other 5. Click Save 6. New type appears in list and is available when creating resources ### Uploading a Logo 1. Navigate to Business Settings → General → Branding 2. Click "Upload Logo" 3. Select image file (PNG, JPG, or SVG) 4. Preview appears 5. Click "Save Changes" 6. Logo appears in header and customer-facing pages ## Benefits 1. **Flexibility**: Businesses can name types to match their industry 2. **Clarity**: "Massage Therapist" is clearer than "Staff" for a spa 3. **Scalability**: Add new types as business grows 4. **Branding**: Logo upload improves professional appearance 5. **User-Friendly**: Simple UI for non-technical users ## Notes - Default "Staff" type cannot be deleted (ensures at least one staff type exists) - Cannot delete types that are in use by existing resources - Logo file size limit: 5MB - Logo recommended dimensions: 500x500px (square) or 500x200px (wide)