feat: Add SMTP settings and collapsible email configuration UI

- Add SMTP fields to TicketEmailSettings model (host, port, TLS/SSL, credentials, from email/name)
- Update serializers with SMTP fields and is_smtp_configured flag
- Add TicketEmailTestSmtpView for testing SMTP connections
- Update frontend API types and hooks for SMTP settings
- Add collapsible IMAP and SMTP configuration sections with "Configured" badges
- Fix TypeScript errors in mockData.ts (missing required fields, type mismatches)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
poduck
2025-11-29 18:28:29 -05:00
parent 0c7d76e264
commit cfc1b36ada
94 changed files with 13419 additions and 1121 deletions

View File

@@ -11,6 +11,7 @@ export const CURRENT_BUSINESS: Business = {
status: 'Active',
joinedAt: new Date('2023-01-15'),
resourcesCanReschedule: false,
paymentsEnabled: true,
requirePaymentMethodToBook: true,
cancellationWindowHours: 24,
lateCancellationFeePercent: 50,
@@ -89,22 +90,22 @@ const staffUserTech: User = { id: 'u_staff_tech', name: 'Jen IT', email: 'jen@te
export const RESOURCES: Resource[] = [
{ id: 'r1', name: 'Bay 1 (Lift)', type: 'ROOM' },
{ id: 'r2', name: 'Bay 2 (Lift)', type: 'ROOM' },
{ id: 'r3', name: 'Mike (Senior Mech)', type: 'STAFF', userId: staffUserAcme.id },
{ id: 'r4', name: 'Stacy Staff (Diag Tech)', type: 'STAFF', userId: STAFF_USER.id },
{ id: 'r5', name: 'Alignment Machine', type: 'EQUIPMENT' },
{ id: 'r6', name: 'Service Bay 3', type: 'ROOM', userId: RESOURCE_USER.id },
{ id: 'r1', name: 'Bay 1 (Lift)', type: 'ROOM', maxConcurrentEvents: 1 },
{ id: 'r2', name: 'Bay 2 (Lift)', type: 'ROOM', maxConcurrentEvents: 1 },
{ id: 'r3', name: 'Mike (Senior Mech)', type: 'STAFF', userId: String(staffUserAcme.id), maxConcurrentEvents: 1 },
{ id: 'r4', name: 'Stacy Staff (Diag Tech)', type: 'STAFF', userId: String(STAFF_USER.id), maxConcurrentEvents: 1 },
{ id: 'r5', name: 'Alignment Machine', type: 'EQUIPMENT', maxConcurrentEvents: 1 },
{ id: 'r6', name: 'Service Bay 3', type: 'ROOM', userId: String(RESOURCE_USER.id), maxConcurrentEvents: 1 },
];
export const SERVICES: Service[] = [
{ id: 's1', name: 'Full Synthetic Oil Change', durationMinutes: 60, price: 89.99, description: 'Premium oil and filter change.' },
{ id: 's2', name: 'Brake Pad Replacement', durationMinutes: 120, price: 245.00, description: 'Front and rear brake pad replacement.' },
{ id: 's3', name: 'Engine Diagnostics', durationMinutes: 90, price: 120.00, description: 'Full computer diagnostics of engine.' },
{ id: 's4', name: 'Tire Rotation', durationMinutes: 45, price: 40.00, description: 'Rotate and balance all four tires.' },
{ id: 's5', name: '4-Wheel Alignment', durationMinutes: 60, price: 95.50, description: 'Precision laser alignment.' },
{ id: 's6', name: 'Tire Patch', durationMinutes: 30, price: 25.00, description: 'Repair minor tire punctures.' },
{ id: 's7', name: 'Vehicle Inspection', durationMinutes: 60, price: 75.00, description: 'Comprehensive multi-point vehicle inspection.' },
{ id: 's1', name: 'Full Synthetic Oil Change', durationMinutes: 60, price: 89.99, description: 'Premium oil and filter change.', displayOrder: 1 },
{ id: 's2', name: 'Brake Pad Replacement', durationMinutes: 120, price: 245.00, description: 'Front and rear brake pad replacement.', displayOrder: 2 },
{ id: 's3', name: 'Engine Diagnostics', durationMinutes: 90, price: 120.00, description: 'Full computer diagnostics of engine.', displayOrder: 3 },
{ id: 's4', name: 'Tire Rotation', durationMinutes: 45, price: 40.00, description: 'Rotate and balance all four tires.', displayOrder: 4 },
{ id: 's5', name: '4-Wheel Alignment', durationMinutes: 60, price: 95.50, description: 'Precision laser alignment.', displayOrder: 5 },
{ id: 's6', name: 'Tire Patch', durationMinutes: 30, price: 25.00, description: 'Repair minor tire punctures.', displayOrder: 6 },
{ id: 's7', name: 'Vehicle Inspection', durationMinutes: 60, price: 75.00, description: 'Comprehensive multi-point vehicle inspection.', displayOrder: 7 },
];
const dayOffset = (days: number) => {
@@ -169,7 +170,7 @@ const customerUserCharlie: User = { id: 'u_cust_charlie', name: 'Charlie Day', e
export const CUSTOMERS: Customer[] = [
{
id: 'c1',
userId: CUSTOMER_USER.id,
userId: String(CUSTOMER_USER.id),
name: 'Alice Smith',
email: 'alice@example.com',
phone: '(555) 123-4567',
@@ -188,7 +189,7 @@ export const CUSTOMERS: Customer[] = [
},
{
id: 'c2',
userId: customerUserBob.id,
userId: String(customerUserBob.id),
name: 'Bob Jones',
email: 'bob.j@example.com',
phone: '(555) 987-6543',
@@ -203,7 +204,7 @@ export const CUSTOMERS: Customer[] = [
},
{
id: 'c3',
userId: customerUserCharlie.id,
userId: String(customerUserCharlie.id),
name: 'Charlie Day',
email: 'charlie@paddys.com',
phone: '(555) 444-3333',
@@ -296,10 +297,10 @@ export const ALL_BUSINESSES: Business[] = [
];
export const SUPPORT_TICKETS: Ticket[] = [
{ id: 't101', subject: 'Cannot connect custom domain', businessName: 'Prestige Worldwide', priority: 'High', status: 'Open', createdAt: new Date('2023-10-26T09:00:00') },
{ id: 't102', subject: 'Question about invoice #4022', businessName: 'Acme Auto Repair', priority: 'Low', status: 'In Progress', createdAt: new Date('2023-10-25T14:30:00') },
{ id: 't103', subject: 'Feature request: Group bookings', businessName: 'Tech Solutions', priority: 'Medium', status: 'Open', createdAt: new Date('2023-10-26T11:15:00') },
{ id: 't104', subject: 'Login issues for staff member', businessName: 'Mom & Pop Shop', priority: 'High', status: 'Resolved', createdAt: new Date('2023-10-24T16:45:00') },
{ id: 't101', subject: 'Cannot connect custom domain', description: 'Having issues connecting my custom domain.', ticketType: 'PLATFORM', priority: 'HIGH', status: 'OPEN', category: 'TECHNICAL', creator: 'u_owner_prestige', creatorEmail: 'brennan@prestige.com', creatorFullName: 'Brennan Huff', createdAt: '2023-10-26T09:00:00Z', updatedAt: '2023-10-26T09:00:00Z' },
{ id: 't102', subject: 'Question about invoice #4022', description: 'Need clarification on invoice charges.', ticketType: 'PLATFORM', priority: 'LOW', status: 'IN_PROGRESS', category: 'BILLING', creator: 'u1', creatorEmail: 'john@acme-auto.com', creatorFullName: 'John Owner', createdAt: '2023-10-25T14:30:00Z', updatedAt: '2023-10-25T14:30:00Z' },
{ id: 't103', subject: 'Feature request: Group bookings', description: 'Would like to request group booking feature.', ticketType: 'PLATFORM', priority: 'MEDIUM', status: 'OPEN', category: 'FEATURE_REQUEST', creator: 'u_owner_techsol', creatorEmail: 'owner@techsol.com', creatorFullName: 'Tech Solutions Owner', createdAt: '2023-10-26T11:15:00Z', updatedAt: '2023-10-26T11:15:00Z' },
{ id: 't104', subject: 'Login issues for staff member', description: 'Staff member cannot login.', ticketType: 'PLATFORM', priority: 'HIGH', status: 'RESOLVED', category: 'ACCOUNT', creator: 'u_owner_mompop', creatorEmail: 'owner@mompop.com', creatorFullName: 'Mom and Pop Owner', createdAt: '2023-10-24T16:45:00Z', updatedAt: '2023-10-24T16:45:00Z', resolvedAt: '2023-10-25T10:00:00Z' },
];
export const ALL_USERS: User[] = [