# Resource Types & Logo Upload - Implementation Summary

## ✅ Completed

### Backend Models

1. **ResourceType Model** (`smoothschedule/schedule/models.py`)
   - Custom resource type definitions (e.g., "Hair Stylist", "Massage Room")
   - Category field: STAFF (requires staff assignment) or OTHER
   - `is_default` flag to prevent deletion of core types
   - Validation to prevent deletion when in use
   - Database migration created and applied ✅

2. **Resource Model Updates** (`smoothschedule/schedule/models.py`)
   - Added `resource_type` ForeignKey to ResourceType model
   - Kept legacy `type` field for backwards compatibility
   - Migration created and applied ✅

3. **Tenant Model Updates** (`smoothschedule/core/models.py`)
   - Added `logo` ImageField for business logo upload
   - Added `logo_display_mode` field with choices:
     - `logo-only`: Show only logo in sidebar
     - `text-only`: Show only business name (default)
     - `logo-and-text`: Show both logo and name
   - Added `primary_color` and `secondary_color` fields
   - Database migration created and applied ✅

### Frontend Updates

1. **TypeScript Types** (`frontend/src/types.ts`)
   - Added `ResourceTypeDefinition` interface
   - Added `ResourceTypeCategory` type
   - Added `logoDisplayMode` to Business interface
   - Updated Resource interface with `typeId` field

2. **React Hooks** (`frontend/src/hooks/useResourceTypes.ts`)
   - `useResourceTypes()` - Fetch resource types
   - `useCreateResourceType()` - Create new type
   - `useUpdateResourceType()` - Update existing type
   - `useDeleteResourceType()` - Delete type (with validation)
   - Includes placeholder data for default types

3. **Sidebar Component** (`frontend/src/components/Sidebar.tsx`)
   - Updated to display logo based on `logoDisplayMode`
   - Shows logo image when mode is `logo-only` or `logo-and-text`
   - Hides business name text when mode is `logo-only`
   - Maintains fallback to initials when no logo

4. **Resource Modal** (`frontend/src/pages/Resources.tsx`)
   - Resource type dropdown now works (no longer disabled)
   - Staff autocomplete fully functional with keyboard navigation
   - Debounced search to reduce API calls
   - All three default types available (Staff, Room, Equipment)

## ⏳ Next Steps

### 1. Data Migration for Default Types
Create a data migration to populate default ResourceType records for existing tenants:

```bash
cd /home/poduck/Desktop/smoothschedule2/smoothschedule
docker compose -f docker-compose.local.yml exec django python manage.py makemigrations schedule --empty --name create_default_resource_types
```

Then edit the migration to add:
```python
def create_default_types(apps, schema_editor):
    ResourceType = apps.get_model('schedule', 'ResourceType')

    # Create default types
    ResourceType.objects.get_or_create(
        name='Staff',
        defaults={
            'category': 'STAFF',
            'is_default': True,
            'icon_name': 'user'
        }
    )
    ResourceType.objects.get_or_create(
        name='Room',
        defaults={
            'category': 'OTHER',
            'is_default': True,
            'icon_name': 'home'
        }
    )
    ResourceType.objects.get_or_create(
        name='Equipment',
        defaults={
            'category': 'OTHER',
            'is_default': True,
            'icon_name': 'wrench'
        }
    )
```

### 2. API Serializers & Views
Create Django REST Framework serializers and viewsets:

**File**: `smoothschedule/schedule/serializers.py`
```python
class ResourceTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = ResourceType
        fields = ['id', 'name', 'category', 'is_default', 'icon_name', 'created_at']
        read_only_fields = ['id', 'created_at']

    def validate_delete(self, instance):
        if instance.is_default:
            raise serializers.ValidationError("Cannot delete default resource types.")
        if instance.resources.exists():
            raise serializers.ValidationError(f"Cannot delete - in use by {instance.resources.count()} resources.")
```

**File**: `smoothschedule/schedule/views.py`
```python
class ResourceTypeViewSet(viewsets.ModelViewSet):
    queryset = ResourceType.objects.all()
    serializer_class = ResourceTypeSerializer
    permission_classes = [IsAuthenticated]

    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        self.serializer_class().validate_delete(instance)
        return super().destroy(request, *args, **kwargs)
```

**File**: `smoothschedule/schedule/urls.py`
```python
router.register(r'resource-types', ResourceTypeViewSet, basename='resourcetype')
```

### 3. Logo Upload API
Add logo upload endpoint to tenant/business API:

**File**: `smoothschedule/core/api_views.py` (or similar)
```python
class TenantLogoUploadView(APIView):
    permission_classes = [IsAuthenticated]
    parser_classes = [MultiPartParser, FormParser]

    def post(self, request):
        tenant = request.tenant  # From django-tenants middleware
        logo_file = request.FILES.get('logo')

        if not logo_file:
            return Response({'error': 'No logo file provided'}, status=400)

        # Validate file size (5MB max)
        if logo_file.size > 5 * 1024 * 1024:
            return Response({'error': 'Logo file too large (max 5MB)'}, status=400)

        # Validate file type
        if not logo_file.content_type.startswith('image/'):
            return Response({'error': 'File must be an image'}, status=400)

        tenant.logo = logo_file
        tenant.save()

        return Response({
            'logoUrl': tenant.logo.url,
            'message': 'Logo uploaded successfully'
        })

    def delete(self, request):
        tenant = request.tenant
        tenant.logo.delete()
        tenant.logo = None
        tenant.save()
        return Response({'message': 'Logo removed successfully'})
```

### 4. Settings Page UI Components
Add to `frontend/src/pages/Settings.tsx`:

#### A. Resource Types Tab
```tsx
{activeTab === 'resources' && (
  <div className="space-y-6">
    <div>
      <h3 className="text-lg font-semibold">Resource Types</h3>
      <p className="text-gray-600">Customize how you categorize your bookable resources.</p>
    </div>

    <ResourceTypesManager />
  </div>
)}
```

#### B. Logo Upload in Branding Section
```tsx
<div className="space-y-4">
  <h4 className="font-semibold">Business Logo</h4>

  {/* Preview */}
  {business.logoUrl ? (
    <div className="relative inline-block">
      <img src={business.logoUrl} alt="Logo" className="w-32 h-32 object-contain border rounded" />
      <button
        onClick={handleRemoveLogo}
        className="absolute -top-2 -right-2 bg-red-500 text-white rounded-full p-1"
      >
        <X size={16} />
      </button>
    </div>
  ) : (
    <div className="w-32 h-32 border-2 border-dashed rounded flex items-center justify-center text-gray-400">
      <Image size={32} />
    </div>
  )}

  {/* Upload */}
  <input
    type="file"
    id="logo-upload"
    className="hidden"
    accept="image/*"
    onChange={handleLogoUpload}
  />
  <label htmlFor="logo-upload" className="btn-secondary">
    <Upload size={16} />
    Upload Logo
  </label>

  {/* Display Mode */}
  <div>
    <label className="block font-medium mb-2">Logo Display Mode</label>
    <select
      value={business.logoDisplayMode}
      onChange={(e) => handleUpdateBusiness({ logoDisplayMode: e.target.value })}
      className="form-select"
    >
      <option value="text-only">Text Only</option>
      <option value="logo-only">Logo Only</option>
      <option value="logo-and-text">Logo and Text</option>
    </select>
  </div>

  {/* Preview with menu background */}
  <div>
    <label className="block font-medium mb-2">Preview in Sidebar</label>
    <div
      className="w-64 p-4 rounded-lg"
      style={{ backgroundColor: business.primaryColor }}
    >
      <div className="flex items-center gap-3">
        {business.logoUrl && (business.logoDisplayMode === 'logo-only' || business.logoDisplayMode === 'logo-and-text') ? (
          <img src={business.logoUrl} alt="Logo" className="w-10 h-10 object-contain" />
        ) : (
          <div className="w-10 h-10 bg-white rounded-lg flex items-center justify-center text-brand-600 font-bold">
            {business.name.substring(0, 2).toUpperCase()}
          </div>
        )}
        {business.logoDisplayMode !== 'logo-only' && (
          <div>
            <h1 className="font-bold text-white truncate">{business.name}</h1>
            <p className="text-xs text-white/60 truncate">{business.subdomain}.smoothschedule.com</p>
          </div>
        )}
      </div>
    </div>
  </div>
</div>
```

### 5. Update Resources Page
Modify `frontend/src/pages/Resources.tsx` to use custom resource types:

```tsx
const { data: resourceTypes = [] } = useResourceTypes();

// In the modal:
<select value={selectedTypeId} onChange={handleTypeChange}>
  {resourceTypes.map(type => (
    <option key={type.id} value={type.id}>
      {type.name}
    </option>
  ))}
</select>

{/* Show staff selector if selected type is STAFF category */}
{selectedType?.category === 'STAFF' && (
  <StaffAutocomplete />
)}
```

## Testing Checklist

- [ ] Create a custom resource type (e.g., "Massage Therapist")
- [ ] Delete a custom type (should work if not in use)
- [ ] Try to delete a default type (should fail)
- [ ] Try to delete a type in use (should fail)
- [ ] Upload a business logo
- [ ] Change logo display mode and verify sidebar updates
- [ ] Remove logo
- [ ] Create a resource using custom type
- [ ] Verify staff assignment required for STAFF category types

## Files Modified/Created

### Backend
- ✅ `smoothschedule/schedule/models.py` - Added ResourceType model, updated Resource
- ✅ `smoothschedule/core/models.py` - Added logo fields to Tenant
- ✅ `smoothschedule/schedule/migrations/0007_*.py` - ResourceType migration
- ✅ `smoothschedule/core/migrations/0003_*.py` - Tenant logo migration
- ⏳ `smoothschedule/schedule/serializers.py` - Need ResourceTypeSerializer
- ⏳ `smoothschedule/schedule/views.py` - Need ResourceTypeViewSet
- ⏳ `smoothschedule/schedule/urls.py` - Need router registration
- ⏳ `smoothschedule/core/api_views.py` - Need logo upload endpoint

### Frontend
- ✅ `frontend/src/types.ts` - Added ResourceType interfaces
- ✅ `frontend/src/hooks/useResourceTypes.ts` - CRUD hooks
- ✅ `frontend/src/components/Sidebar.tsx` - Logo display logic
- ✅ `frontend/src/pages/Resources.tsx` - Fixed dropdown, autocomplete
- ⏳ `frontend/src/pages/Settings.tsx` - Need resource types tab & logo upload UI
- ⏳ `frontend/src/components/ResourceTypesManager.tsx` - Need new component

## Database Schema

### ResourceType Table
```sql
CREATE TABLE schedule_resourcetype (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    category VARCHAR(10) NOT NULL DEFAULT 'OTHER',
    is_default BOOLEAN NOT NULL DEFAULT FALSE,
    icon_name VARCHAR(50),
    created_at TIMESTAMP NOT NULL,
    updated_at TIMESTAMP NOT NULL
);
```

### Tenant Table Updates
```sql
ALTER TABLE core_tenant ADD COLUMN logo VARCHAR(100);
ALTER TABLE core_tenant ADD COLUMN logo_display_mode VARCHAR(20) DEFAULT 'text-only';
ALTER TABLE core_tenant ADD COLUMN primary_color VARCHAR(7) DEFAULT '#2563eb';
ALTER TABLE core_tenant ADD COLUMN secondary_color VARCHAR(7) DEFAULT '#0ea5e9';
```

### Resource Table Updates
```sql
ALTER TABLE schedule_resource ADD COLUMN resource_type_id INTEGER REFERENCES schedule_resourcetype(id) ON DELETE PROTECT;
```

## Notes

- Logo files stored in `MEDIA_ROOT/tenant_logos/`
- Max file size: 5MB
- Supported formats: PNG, JPG, SVG
- Recommended dimensions: 500x500px (square) or 500x200px (wide)
- Default resource types are created via data migration
- Legacy `Resource.type` field kept for backwards compatibility
