sync: Auto-sync from Mikes-MacBook-Air.local at 2026-03-09 08:14:13

Synced files:
- Session logs updated
- Latest context and credentials
- Command/directive updates

Machine: Mikes-MacBook-Air.local
Timestamp: 2026-03-09 08:14:13

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-03-09 08:14:13 -07:00
parent f81872784b
commit a1a19f8c00
59 changed files with 14435 additions and 1 deletions

View File

@@ -0,0 +1,612 @@
import { useState, useCallback, useMemo } from 'react';
import type {
QuoteData,
QuoteResult,
QuoteBreakdown,
CompanyInfo,
GPSSelection,
SupportSelection,
VoIPSelection,
WebHostingSelection,
EmailSelection,
ContactInfo,
GPSTierId,
SupportPlanId,
BlockTimeId,
VoIPTierId,
WebHostingTierId,
EmailTierId,
EmailProvider,
Industry,
ContactPreference,
} from '@/types/quote';
import {
gpsTiers,
equipmentMonitoring,
supportPlans,
blockTimeOptions,
voipTiers,
voipHardware,
webHostingTiers,
emailTiers,
} from '@/lib/pricing-data';
/**
* Initial state values
*/
const initialCompanyInfo: CompanyInfo = {
name: '',
endpointCount: 10,
industry: '',
notes: '',
};
const initialGPSSelection: GPSSelection = {
tierId: 'pro',
endpointCount: 10,
includeEquipment: false,
equipmentDeviceCount: 0,
};
const initialSupportSelection: SupportSelection = {
planId: 'standard',
useBlockTime: false,
blockTimeId: null,
};
const initialVoIPSelection: VoIPSelection = {
enabled: false,
tierId: 'voip-standard',
userCount: 0,
hardware: [],
};
const initialWebHostingSelection: WebHostingSelection = {
enabled: false,
tierId: 'hosting-business',
};
const initialEmailSelection: EmailSelection = {
enabled: false,
provider: 'm365',
tierId: 'm365-standard',
mailboxCount: 0,
};
const initialContactInfo: ContactInfo = {
name: '',
email: '',
phone: '',
companyName: '',
currentITSituation: '',
contactPreference: 'email',
agreedToTerms: false,
};
/**
* Hook return type
*/
export interface UseQuoteReturn {
quoteData: QuoteData;
quoteResult: QuoteResult | null;
// Company updates
updateCompany: (data: Partial<CompanyInfo>) => void;
setEndpointCount: (count: number) => void;
setIndustry: (industry: Industry | '') => void;
// GPS updates
updateGPS: (data: Partial<GPSSelection>) => void;
setGPSTier: (tierId: GPSTierId) => void;
setEquipmentEnabled: (enabled: boolean) => void;
setEquipmentCount: (count: number) => void;
// Support updates
updateSupport: (data: Partial<SupportSelection>) => void;
setSupportPlan: (planId: SupportPlanId) => void;
setBlockTimeEnabled: (enabled: boolean) => void;
setBlockTime: (blockTimeId: BlockTimeId) => void;
// VoIP updates
updateVoIP: (data: Partial<VoIPSelection>) => void;
setVoIPEnabled: (enabled: boolean) => void;
setVoIPTier: (tierId: VoIPTierId) => void;
setVoIPUserCount: (count: number) => void;
addHardware: (hardwareId: string, quantity: number, isRental: boolean) => void;
removeHardware: (hardwareId: string) => void;
updateHardwareQuantity: (hardwareId: string, quantity: number) => void;
// Web Hosting updates
updateWebHosting: (data: Partial<WebHostingSelection>) => void;
setWebHostingEnabled: (enabled: boolean) => void;
setWebHostingTier: (tierId: WebHostingTierId) => void;
// Email updates
updateEmail: (data: Partial<EmailSelection>) => void;
setEmailEnabled: (enabled: boolean) => void;
setEmailProvider: (provider: EmailProvider) => void;
setEmailTier: (tierId: EmailTierId) => void;
setMailboxCount: (count: number) => void;
// Contact updates
updateContact: (data: Partial<ContactInfo>) => void;
setContactPreference: (preference: ContactPreference) => void;
setAgreedToTerms: (agreed: boolean) => void;
// Calculations
calculateQuote: () => QuoteResult;
getGPSMonthly: () => number;
getSupportMonthly: () => number;
getVoIPMonthly: () => number;
getWebHostingMonthly: () => number;
getEmailMonthly: () => number;
getVoIPOneTime: () => number;
// Reset
resetQuote: () => void;
}
/**
* Quote calculation and state management hook
*/
export function useQuote(): UseQuoteReturn {
const [company, setCompany] = useState<CompanyInfo>(initialCompanyInfo);
const [gps, setGPS] = useState<GPSSelection>(initialGPSSelection);
const [support, setSupport] = useState<SupportSelection>(initialSupportSelection);
const [voip, setVoIP] = useState<VoIPSelection>(initialVoIPSelection);
const [webHosting, setWebHosting] = useState<WebHostingSelection>(initialWebHostingSelection);
const [email, setEmail] = useState<EmailSelection>(initialEmailSelection);
const [contact, setContact] = useState<ContactInfo>(initialContactInfo);
const [quoteResult, setQuoteResult] = useState<QuoteResult | null>(null);
// Combined quote data
const quoteData: QuoteData = useMemo(
() => ({
company,
gps,
support,
voip,
webHosting,
email,
contact,
}),
[company, gps, support, voip, webHosting, email, contact]
);
// ============================================================================
// Company Updates
// ============================================================================
const updateCompany = useCallback((data: Partial<CompanyInfo>) => {
setCompany((prev) => {
const updated = { ...prev, ...data };
// Sync endpoint count with GPS selection
if (data.endpointCount !== undefined) {
setGPS((gpsState) => ({ ...gpsState, endpointCount: data.endpointCount as number }));
}
return updated;
});
}, []);
const setEndpointCount = useCallback((count: number) => {
const validCount = Math.max(1, count);
setCompany((prev) => ({ ...prev, endpointCount: validCount }));
setGPS((prev) => ({ ...prev, endpointCount: validCount }));
}, []);
const setIndustry = useCallback((industry: Industry | '') => {
setCompany((prev) => ({ ...prev, industry }));
}, []);
// ============================================================================
// GPS Updates
// ============================================================================
const updateGPS = useCallback((data: Partial<GPSSelection>) => {
setGPS((prev) => ({ ...prev, ...data }));
}, []);
const setGPSTier = useCallback((tierId: GPSTierId) => {
setGPS((prev) => ({ ...prev, tierId }));
}, []);
const setEquipmentEnabled = useCallback((enabled: boolean) => {
setGPS((prev) => ({
...prev,
includeEquipment: enabled,
equipmentDeviceCount: enabled ? Math.max(prev.equipmentDeviceCount, 1) : 0,
}));
}, []);
const setEquipmentCount = useCallback((count: number) => {
setGPS((prev) => ({ ...prev, equipmentDeviceCount: Math.max(0, count) }));
}, []);
// ============================================================================
// Support Updates
// ============================================================================
const updateSupport = useCallback((data: Partial<SupportSelection>) => {
setSupport((prev) => ({ ...prev, ...data }));
}, []);
const setSupportPlan = useCallback((planId: SupportPlanId) => {
setSupport((prev) => ({ ...prev, planId }));
}, []);
const setBlockTimeEnabled = useCallback((enabled: boolean) => {
setSupport((prev) => ({
...prev,
useBlockTime: enabled,
blockTimeId: enabled ? (prev.blockTimeId || 'block-10') : null,
}));
}, []);
const setBlockTime = useCallback((blockTimeId: BlockTimeId) => {
setSupport((prev) => ({ ...prev, blockTimeId, useBlockTime: true }));
}, []);
// ============================================================================
// VoIP Updates
// ============================================================================
const updateVoIP = useCallback((data: Partial<VoIPSelection>) => {
setVoIP((prev) => ({ ...prev, ...data }));
}, []);
const setVoIPEnabled = useCallback((enabled: boolean) => {
setVoIP((prev) => ({
...prev,
enabled,
userCount: enabled ? Math.max(prev.userCount, 1) : 0,
}));
}, []);
const setVoIPTier = useCallback((tierId: VoIPTierId) => {
setVoIP((prev) => ({ ...prev, tierId }));
}, []);
const setVoIPUserCount = useCallback((count: number) => {
setVoIP((prev) => ({ ...prev, userCount: Math.max(0, count) }));
}, []);
const addHardware = useCallback((hardwareId: string, quantity: number, isRental: boolean) => {
setVoIP((prev) => {
const existing = prev.hardware.find((h) => h.hardwareId === hardwareId);
if (existing) {
return {
...prev,
hardware: prev.hardware.map((h) =>
h.hardwareId === hardwareId ? { ...h, quantity, isRental } : h
),
};
}
return {
...prev,
hardware: [...prev.hardware, { hardwareId, quantity, isRental }],
};
});
}, []);
const removeHardware = useCallback((hardwareId: string) => {
setVoIP((prev) => ({
...prev,
hardware: prev.hardware.filter((h) => h.hardwareId !== hardwareId),
}));
}, []);
const updateHardwareQuantity = useCallback((hardwareId: string, quantity: number) => {
setVoIP((prev) => ({
...prev,
hardware: prev.hardware.map((h) =>
h.hardwareId === hardwareId ? { ...h, quantity: Math.max(0, quantity) } : h
),
}));
}, []);
// ============================================================================
// Web Hosting Updates
// ============================================================================
const updateWebHosting = useCallback((data: Partial<WebHostingSelection>) => {
setWebHosting((prev) => ({ ...prev, ...data }));
}, []);
const setWebHostingEnabled = useCallback((enabled: boolean) => {
setWebHosting((prev) => ({ ...prev, enabled }));
}, []);
const setWebHostingTier = useCallback((tierId: WebHostingTierId) => {
setWebHosting((prev) => ({ ...prev, tierId }));
}, []);
// ============================================================================
// Email Updates
// ============================================================================
const updateEmail = useCallback((data: Partial<EmailSelection>) => {
setEmail((prev) => ({ ...prev, ...data }));
}, []);
const setEmailEnabled = useCallback((enabled: boolean) => {
setEmail((prev) => ({
...prev,
enabled,
mailboxCount: enabled ? Math.max(prev.mailboxCount, 1) : 0,
}));
}, []);
const setEmailProvider = useCallback((provider: EmailProvider) => {
setEmail((prev) => {
// Set default tier for provider
const defaultTier = provider === 'm365' ? 'm365-standard' : 'whm-standard';
return { ...prev, provider, tierId: defaultTier as EmailTierId };
});
}, []);
const setEmailTier = useCallback((tierId: EmailTierId) => {
setEmail((prev) => ({ ...prev, tierId }));
}, []);
const setMailboxCount = useCallback((count: number) => {
setEmail((prev) => ({ ...prev, mailboxCount: Math.max(0, count) }));
}, []);
// ============================================================================
// Contact Updates
// ============================================================================
const updateContact = useCallback((data: Partial<ContactInfo>) => {
setContact((prev) => ({ ...prev, ...data }));
}, []);
const setContactPreference = useCallback((preference: ContactPreference) => {
setContact((prev) => ({ ...prev, contactPreference: preference }));
}, []);
const setAgreedToTerms = useCallback((agreed: boolean) => {
setContact((prev) => ({ ...prev, agreedToTerms: agreed }));
}, []);
// ============================================================================
// Calculation Functions
// ============================================================================
const getGPSMonthly = useCallback((): number => {
const tier = gpsTiers.find((t) => t.id === gps.tierId);
if (!tier) return 0;
let total = tier.pricePerEndpoint * gps.endpointCount;
if (gps.includeEquipment && gps.equipmentDeviceCount > 0) {
const additionalDevices = Math.max(0, gps.equipmentDeviceCount - equipmentMonitoring.baseDevices);
total += equipmentMonitoring.basePrice + (additionalDevices * equipmentMonitoring.additionalDevicePrice);
}
return total;
}, [gps]);
const getSupportMonthly = useCallback((): number => {
const plan = supportPlans.find((p) => p.id === support.planId);
if (!plan) return 0;
let total = plan.monthlyPrice;
if (support.useBlockTime && support.blockTimeId) {
const blockTime = blockTimeOptions.find((b) => b.id === support.blockTimeId);
if (blockTime) {
total += blockTime.price;
}
}
return total;
}, [support]);
const getVoIPMonthly = useCallback((): number => {
if (!voip.enabled) return 0;
const tier = voipTiers.find((t) => t.id === voip.tierId);
if (!tier) return 0;
let total = tier.pricePerUser * voip.userCount;
// Add rental hardware costs
voip.hardware.forEach((hw) => {
if (hw.isRental) {
const hardware = voipHardware.find((h) => h.id === hw.hardwareId);
if (hardware) {
total += hardware.monthlyRental * hw.quantity;
}
}
});
return total;
}, [voip]);
const getVoIPOneTime = useCallback((): number => {
if (!voip.enabled) return 0;
let total = 0;
// Add purchased hardware costs
voip.hardware.forEach((hw) => {
if (!hw.isRental) {
const hardware = voipHardware.find((h) => h.id === hw.hardwareId);
if (hardware) {
total += hardware.oneTimePrice * hw.quantity;
}
}
});
return total;
}, [voip]);
const getWebHostingMonthly = useCallback((): number => {
if (!webHosting.enabled) return 0;
const tier = webHostingTiers.find((t) => t.id === webHosting.tierId);
return tier ? tier.monthlyPrice : 0;
}, [webHosting]);
const getEmailMonthly = useCallback((): number => {
if (!email.enabled) return 0;
const tier = emailTiers.find((t) => t.id === email.tierId);
return tier ? tier.pricePerMailbox * email.mailboxCount : 0;
}, [email]);
const calculateQuote = useCallback((): QuoteResult => {
const gpsMonthly = getGPSMonthly();
const supportMonthly = getSupportMonthly();
const voipMonthly = getVoIPMonthly();
const voipOneTime = getVoIPOneTime();
const webHostingMonthly = getWebHostingMonthly();
const emailMonthly = getEmailMonthly();
// Calculate GPS breakdown
const gpsTier = gpsTiers.find((t) => t.id === gps.tierId);
const gpsMonitoring = gpsTier ? gpsTier.pricePerEndpoint * gps.endpointCount : 0;
let gpsEquipment = 0;
if (gps.includeEquipment && gps.equipmentDeviceCount > 0) {
const additionalDevices = Math.max(0, gps.equipmentDeviceCount - equipmentMonitoring.baseDevices);
gpsEquipment = equipmentMonitoring.basePrice + (additionalDevices * equipmentMonitoring.additionalDevicePrice);
}
// Calculate support breakdown
const supportPlan = supportPlans.find((p) => p.id === support.planId);
const supportPlanCost = supportPlan ? supportPlan.monthlyPrice : 0;
let supportBlockTime = 0;
if (support.useBlockTime && support.blockTimeId) {
const blockTime = blockTimeOptions.find((b) => b.id === support.blockTimeId);
if (blockTime) {
supportBlockTime = blockTime.price;
}
}
// Calculate VoIP breakdown
const voipTier = voipTiers.find((t) => t.id === voip.tierId);
const voipService = voip.enabled && voipTier ? voipTier.pricePerUser * voip.userCount : 0;
let voipHardwareMonthly = 0;
if (voip.enabled) {
voip.hardware.forEach((hw) => {
if (hw.isRental) {
const hardware = voipHardware.find((h) => h.id === hw.hardwareId);
if (hardware) {
voipHardwareMonthly += hardware.monthlyRental * hw.quantity;
}
}
});
}
const breakdown: QuoteBreakdown = {
gps: {
monitoring: gpsMonitoring,
equipment: gpsEquipment,
total: gpsMonthly,
},
support: {
plan: supportPlanCost,
blockTime: supportBlockTime,
total: supportMonthly,
},
voip: {
service: voipService,
hardware: voipHardwareMonthly,
total: voipMonthly,
},
webHosting: webHostingMonthly,
email: emailMonthly,
};
const monthlyTotal = gpsMonthly + supportMonthly + voipMonthly + webHostingMonthly + emailMonthly;
const result: QuoteResult = {
monthlyTotal,
oneTimeTotal: voipOneTime,
breakdown,
gpsMonthly,
supportMonthly,
voipMonthly,
webHostingMonthly,
emailMonthly,
};
setQuoteResult(result);
return result;
}, [gps, support, voip, webHosting, email, getGPSMonthly, getSupportMonthly, getVoIPMonthly, getVoIPOneTime, getWebHostingMonthly, getEmailMonthly]);
// ============================================================================
// Reset
// ============================================================================
const resetQuote = useCallback(() => {
setCompany(initialCompanyInfo);
setGPS(initialGPSSelection);
setSupport(initialSupportSelection);
setVoIP(initialVoIPSelection);
setWebHosting(initialWebHostingSelection);
setEmail(initialEmailSelection);
setContact(initialContactInfo);
setQuoteResult(null);
}, []);
return {
quoteData,
quoteResult,
// Company updates
updateCompany,
setEndpointCount,
setIndustry,
// GPS updates
updateGPS,
setGPSTier,
setEquipmentEnabled,
setEquipmentCount,
// Support updates
updateSupport,
setSupportPlan,
setBlockTimeEnabled,
setBlockTime,
// VoIP updates
updateVoIP,
setVoIPEnabled,
setVoIPTier,
setVoIPUserCount,
addHardware,
removeHardware,
updateHardwareQuantity,
// Web Hosting updates
updateWebHosting,
setWebHostingEnabled,
setWebHostingTier,
// Email updates
updateEmail,
setEmailEnabled,
setEmailProvider,
setEmailTier,
setMailboxCount,
// Contact updates
updateContact,
setContactPreference,
setAgreedToTerms,
// Calculations
calculateQuote,
getGPSMonthly,
getSupportMonthly,
getVoIPMonthly,
getWebHostingMonthly,
getEmailMonthly,
getVoIPOneTime,
// Reset
resetQuote,
};
}