@aws505/sheetsite 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/README.md +105 -0
  2. package/dist/components/index.js +1696 -0
  3. package/dist/components/index.js.map +1 -0
  4. package/dist/components/index.mjs +1630 -0
  5. package/dist/components/index.mjs.map +1 -0
  6. package/dist/config/index.js +1840 -0
  7. package/dist/config/index.js.map +1 -0
  8. package/dist/config/index.mjs +1793 -0
  9. package/dist/config/index.mjs.map +1 -0
  10. package/dist/data/index.js +1296 -0
  11. package/dist/data/index.js.map +1 -0
  12. package/dist/data/index.mjs +1220 -0
  13. package/dist/data/index.mjs.map +1 -0
  14. package/dist/index.js +5433 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/index.mjs +5285 -0
  17. package/dist/index.mjs.map +1 -0
  18. package/dist/seo/index.js +187 -0
  19. package/dist/seo/index.js.map +1 -0
  20. package/dist/seo/index.mjs +155 -0
  21. package/dist/seo/index.mjs.map +1 -0
  22. package/dist/theme/index.js +552 -0
  23. package/dist/theme/index.js.map +1 -0
  24. package/dist/theme/index.mjs +526 -0
  25. package/dist/theme/index.mjs.map +1 -0
  26. package/package.json +96 -0
  27. package/src/components/index.ts +41 -0
  28. package/src/components/layout/Footer.tsx +234 -0
  29. package/src/components/layout/Header.tsx +134 -0
  30. package/src/components/sections/FAQ.tsx +178 -0
  31. package/src/components/sections/Gallery.tsx +107 -0
  32. package/src/components/sections/Hero.tsx +202 -0
  33. package/src/components/sections/Hours.tsx +225 -0
  34. package/src/components/sections/Services.tsx +216 -0
  35. package/src/components/sections/Testimonials.tsx +184 -0
  36. package/src/components/ui/Button.tsx +158 -0
  37. package/src/components/ui/Card.tsx +162 -0
  38. package/src/components/ui/Icons.tsx +508 -0
  39. package/src/config/index.ts +207 -0
  40. package/src/config/presets/generic.ts +153 -0
  41. package/src/config/presets/home-kitchen.ts +154 -0
  42. package/src/config/presets/index.ts +708 -0
  43. package/src/config/presets/professional.ts +165 -0
  44. package/src/config/presets/repair.ts +160 -0
  45. package/src/config/presets/restaurant.ts +162 -0
  46. package/src/config/presets/salon.ts +178 -0
  47. package/src/config/presets/tailor.ts +159 -0
  48. package/src/config/types.ts +314 -0
  49. package/src/data/csv-parser.ts +154 -0
  50. package/src/data/defaults.ts +202 -0
  51. package/src/data/google-drive.ts +148 -0
  52. package/src/data/index.ts +535 -0
  53. package/src/data/sheets.ts +709 -0
  54. package/src/data/types.ts +379 -0
  55. package/src/seo/index.ts +272 -0
  56. package/src/theme/colors.ts +351 -0
  57. package/src/theme/index.ts +249 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/data/index.ts","../../src/data/types.ts","../../src/data/csv-parser.ts","../../src/data/google-drive.ts","../../src/data/sheets.ts","../../src/data/defaults.ts"],"sourcesContent":["/**\n * SheetSite Data Module\n *\n * Provides all data-related functionality:\n * - Google Sheets integration (public CSV and private API modes)\n * - Type definitions for site data\n * - CSV parsing utilities\n * - Google Drive URL utilities\n * - Default data and fallbacks\n */\n\n// Types\nexport * from './types';\n\n// Google Sheets integration\nexport {\n fetchSheetData,\n fetchPublicSheetData,\n fetchPrivateSheetData,\n fetchInlineData,\n mergeSiteData,\n type FetchOptions,\n} from './sheets';\n\n// CSV parsing\nexport {\n parseCSV,\n normalizeHeader,\n mapRows,\n parseBoolean,\n parseNumber,\n parseInteger,\n parseSortOrder,\n type ParsedRow,\n} from './csv-parser';\n\n// Google Drive utilities\nexport {\n normalizeGoogleDriveUrl,\n getGoogleDriveThumbnail,\n isGoogleDriveUrl,\n extractGoogleDriveFileId,\n processImageUrls,\n processImageUrlsInArray,\n} from './google-drive';\n\n// Defaults\nexport {\n DEFAULT_SITE_DATA,\n createDefaultSiteData,\n industryDefaults,\n} from './defaults';\n\n// =============================================================================\n// CONVENIENCE FUNCTIONS\n// =============================================================================\n\nimport type { SheetConfig, SiteData, PartialSiteData } from './types';\nimport { fetchSheetData, mergeSiteData } from './sheets';\nimport { DEFAULT_SITE_DATA, createDefaultSiteData, industryDefaults } from './defaults';\n\n/**\n * In-memory cache for site data.\n */\nlet cachedSiteData: SiteData | null = null;\nlet cacheTimestamp: number = 0;\nconst CACHE_DURATION = 5 * 60 * 1000; // 5 minutes\n\n/**\n * Clear the in-memory cache.\n * Call this when you need to force a refresh.\n */\nexport function clearSiteDataCache(): void {\n cachedSiteData = null;\n cacheTimestamp = 0;\n}\n\n/**\n * Get site data with caching.\n * This is the primary function for fetching site data in your application.\n *\n * @param config - Sheet configuration (public CSV or private API)\n * @param defaults - Default data to merge with (optional)\n * @returns Complete site data\n */\nexport async function getSiteData(\n config: SheetConfig | undefined,\n defaults: SiteData = DEFAULT_SITE_DATA\n): Promise<SiteData> {\n // Check cache\n const now = Date.now();\n if (cachedSiteData && now - cacheTimestamp < CACHE_DURATION) {\n return cachedSiteData;\n }\n\n // If no config, return defaults\n if (!config) {\n return defaults;\n }\n\n try {\n const partialData = await fetchSheetData(config);\n const siteData = mergeSiteData(partialData, defaults);\n\n // Update cache\n cachedSiteData = siteData;\n cacheTimestamp = now;\n\n return siteData;\n } catch (error) {\n console.error('Error fetching site data:', error);\n return defaults;\n }\n}\n\n/**\n * Get site data with a custom default based on business type.\n *\n * @param config - Sheet configuration\n * @param businessName - Name of the business\n * @returns Complete site data\n */\nexport async function getSiteDataWithName(\n config: SheetConfig | undefined,\n businessName: string\n): Promise<SiteData> {\n const defaults = createDefaultSiteData(businessName);\n return getSiteData(config, defaults);\n}\n\n/**\n * Create a sheet configuration from environment variables.\n * This is a convenience function for common setup patterns.\n *\n * Expected environment variables for public CSV mode:\n * - SHEET_MODE=public_csv\n * - SHEET_CSV_URL_BUSINESS\n * - SHEET_CSV_URL_HOURS (optional)\n * - SHEET_CSV_URL_SERVICES (optional)\n * - SHEET_CSV_URL_GALLERY (optional)\n * - SHEET_CSV_URL_TESTIMONIALS (optional)\n * - SHEET_CSV_URL_FAQ (optional)\n * - SHEET_CSV_URL_TEAM (optional)\n * - SHEET_CSV_URL_MENU (optional)\n * - SHEET_CSV_URL_PRODUCTS (optional)\n * - SHEET_CSV_URL_ANNOUNCEMENTS (optional)\n *\n * Expected environment variables for private API mode:\n * - SHEET_MODE=private_api\n * - SHEET_ID\n * - GOOGLE_SERVICE_ACCOUNT_EMAIL\n * - GOOGLE_PRIVATE_KEY\n *\n * For inline mode, use createInlineConfig() instead.\n */\nexport function createSheetConfigFromEnv(): SheetConfig | undefined {\n const mode = process.env.SHEET_MODE;\n\n if (mode === 'public_csv') {\n const businessUrl = process.env.SHEET_CSV_URL_BUSINESS;\n if (!businessUrl) {\n console.warn('SHEET_CSV_URL_BUSINESS not set, using defaults');\n return undefined;\n }\n\n return {\n mode: 'public_csv',\n tabs: {\n business: businessUrl,\n hours: process.env.SHEET_CSV_URL_HOURS,\n services: process.env.SHEET_CSV_URL_SERVICES,\n gallery: process.env.SHEET_CSV_URL_GALLERY,\n testimonials: process.env.SHEET_CSV_URL_TESTIMONIALS,\n faq: process.env.SHEET_CSV_URL_FAQ,\n team: process.env.SHEET_CSV_URL_TEAM,\n menu: process.env.SHEET_CSV_URL_MENU,\n products: process.env.SHEET_CSV_URL_PRODUCTS,\n announcements: process.env.SHEET_CSV_URL_ANNOUNCEMENTS,\n },\n };\n }\n\n if (mode === 'private_api') {\n const sheetId = process.env.SHEET_ID;\n const clientEmail = process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL;\n const privateKey = process.env.GOOGLE_PRIVATE_KEY;\n\n if (!sheetId || !clientEmail || !privateKey) {\n console.warn('Missing required environment variables for private API mode');\n return undefined;\n }\n\n return {\n mode: 'private_api',\n sheetId,\n clientEmail,\n privateKey,\n };\n }\n\n // No valid mode configured\n return undefined;\n}\n\n// =============================================================================\n// INLINE DATA UTILITIES\n// =============================================================================\n\nimport type { InlineDataConfig, BusinessInfo, HoursEntry, DayOfWeek } from './types';\n\n/**\n * Create an inline configuration for direct data injection.\n * This bypasses Google Sheets entirely and uses provided data directly.\n *\n * Ideal for:\n * - Automated site generation from CSV/JSON leads\n * - Rapid prototyping and demos\n * - Testing without network dependencies\n *\n * @example\n * ```ts\n * const config = createInlineConfig({\n * business: {\n * name: \"John's Tailor Shop\",\n * tagline: \"Expert Alterations\",\n * phone: \"555-123-4567\",\n * city: \"San Diego\",\n * state: \"CA\"\n * },\n * hours: [\n * { day: 'monday', open: '9:00 AM', close: '5:00 PM', closed: false }\n * ]\n * });\n *\n * const siteData = await getSiteData(config, industryDefaults.tailor());\n * ```\n */\nexport function createInlineConfig(data: PartialSiteData): InlineDataConfig {\n return {\n mode: 'inline',\n data,\n };\n}\n\n/**\n * Input format for lead data from scraped sources (e.g., Google Maps).\n * Designed to match common CSV export formats.\n */\nexport interface LeadData {\n // Required\n name: string;\n\n // Contact (at least phone recommended)\n phone?: string;\n phoneAlt?: string;\n email?: string;\n\n // Address - can be single field or split\n address?: string; // Full address string (will attempt to parse)\n addressLine1?: string;\n addressLine2?: string;\n city?: string;\n state?: string;\n zip?: string;\n country?: string;\n\n // Business info\n tagline?: string;\n description?: string;\n category?: string; // e.g., \"Tailor\", \"Restaurant\" - used for preset selection\n googleMapsUrl?: string;\n\n // Hours - can be structured or simple\n hours?: HoursEntry[] | SimpleHours;\n\n // Images\n heroImageUrl?: string;\n logoUrl?: string;\n galleryUrls?: string[];\n\n // Social proof\n rating?: number; // e.g., 4.5\n reviewCount?: number;\n testimonialQuote?: string;\n testimonialAuthor?: string;\n\n // Social links\n yelp?: string;\n instagram?: string;\n facebook?: string;\n twitter?: string;\n website?: string;\n\n // Additional\n yearEstablished?: number;\n priceRange?: '$' | '$$' | '$$$' | '$$$$';\n timezone?: string;\n}\n\n/**\n * Simple hours format for common patterns.\n */\nexport interface SimpleHours {\n weekdays?: { open: string; close: string };\n saturday?: { open: string; close: string } | 'closed';\n sunday?: { open: string; close: string } | 'closed';\n}\n\n/**\n * Convert simple hours format to HoursEntry array.\n */\nfunction parseSimpleHours(hours: SimpleHours): HoursEntry[] {\n const entries: HoursEntry[] = [];\n const weekdays: DayOfWeek[] = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'];\n\n if (hours.weekdays) {\n for (const day of weekdays) {\n entries.push({\n day,\n open: hours.weekdays.open,\n close: hours.weekdays.close,\n closed: false,\n });\n }\n }\n\n if (hours.saturday) {\n entries.push(\n hours.saturday === 'closed'\n ? { day: 'saturday', closed: true }\n : { day: 'saturday', open: hours.saturday.open, close: hours.saturday.close, closed: false }\n );\n }\n\n if (hours.sunday) {\n entries.push(\n hours.sunday === 'closed'\n ? { day: 'sunday', closed: true }\n : { day: 'sunday', open: hours.sunday.open, close: hours.sunday.close, closed: false }\n );\n }\n\n return entries;\n}\n\n/**\n * Parse a full address string into components.\n * Handles common US address formats.\n */\nfunction parseAddressString(\n address: string\n): Pick<BusinessInfo, 'addressLine1' | 'city' | 'state' | 'zip'> {\n // Try to match: \"123 Main St, City, ST 12345\" or similar\n const parts = address.split(',').map((s) => s.trim());\n\n if (parts.length >= 3) {\n // Likely: Street, City, State ZIP\n const lastPart = parts[parts.length - 1];\n const stateZipMatch = lastPart.match(/^([A-Z]{2})\\s*(\\d{5}(?:-\\d{4})?)$/);\n\n if (stateZipMatch) {\n return {\n addressLine1: parts.slice(0, -2).join(', '),\n city: parts[parts.length - 2],\n state: stateZipMatch[1],\n zip: stateZipMatch[2],\n };\n }\n }\n\n if (parts.length === 2) {\n // Likely: Street, City ST ZIP\n const cityStateZipMatch = parts[1].match(/^(.+?)\\s+([A-Z]{2})\\s*(\\d{5}(?:-\\d{4})?)$/);\n if (cityStateZipMatch) {\n return {\n addressLine1: parts[0],\n city: cityStateZipMatch[1],\n state: cityStateZipMatch[2],\n zip: cityStateZipMatch[3],\n };\n }\n }\n\n // Fallback: just use as address line 1\n return { addressLine1: address };\n}\n\n/**\n * Create PartialSiteData from lead data (e.g., scraped from Google Maps).\n *\n * This is the primary function for converting CSV/JSON lead data into\n * a format suitable for SheetSite. It handles common data formats and\n * performs sensible normalization.\n *\n * @example\n * ```ts\n * const lead = {\n * name: \"John's Tailor Shop\",\n * phone: \"555-123-4567\",\n * address: \"123 Main St, San Diego, CA 92101\",\n * category: \"Tailor\",\n * rating: 4.8,\n * reviewCount: 67,\n * hours: {\n * weekdays: { open: '9:00 AM', close: '5:00 PM' },\n * saturday: { open: '10:00 AM', close: '3:00 PM' },\n * sunday: 'closed'\n * }\n * };\n *\n * const siteData = createSiteDataFromLead(lead);\n * const config = createInlineConfig(siteData);\n * ```\n */\nexport function createSiteDataFromLead(lead: LeadData): PartialSiteData {\n // Parse address if provided as single string\n const addressParts =\n lead.address && !lead.addressLine1 ? parseAddressString(lead.address) : {};\n\n // Build business info\n const business: Partial<BusinessInfo> = {\n name: lead.name,\n tagline: lead.tagline,\n description: lead.description,\n phone: lead.phone,\n phoneAlt: lead.phoneAlt,\n email: lead.email,\n addressLine1: lead.addressLine1 || addressParts.addressLine1,\n addressLine2: lead.addressLine2,\n city: lead.city || addressParts.city,\n state: lead.state || addressParts.state,\n zip: lead.zip || addressParts.zip,\n country: lead.country || 'USA',\n googleMapsUrl: lead.googleMapsUrl,\n timezone: lead.timezone || 'America/Los_Angeles',\n heroImageUrl: lead.heroImageUrl,\n logoUrl: lead.logoUrl,\n socialYelp: lead.yelp,\n socialInstagram: lead.instagram,\n socialFacebook: lead.facebook,\n socialTwitter: lead.twitter,\n yearEstablished: lead.yearEstablished,\n priceRange: lead.priceRange,\n };\n\n // Parse hours\n let hours: HoursEntry[] | undefined;\n if (lead.hours) {\n if (Array.isArray(lead.hours)) {\n hours = lead.hours;\n } else {\n hours = parseSimpleHours(lead.hours);\n }\n }\n\n // Build gallery from URLs\n const gallery = lead.galleryUrls?.map((url, i) => ({\n id: `gallery-${i}`,\n imageUrl: url,\n alt: `${lead.name} - Image ${i + 1}`,\n featured: false,\n sortOrder: i,\n }));\n\n // Build testimonial from rating/review data\n const testimonials =\n lead.testimonialQuote && lead.testimonialAuthor\n ? [\n {\n id: 'testimonial-1',\n quote: lead.testimonialQuote,\n name: lead.testimonialAuthor,\n rating: lead.rating,\n source: 'Google',\n featured: false,\n sortOrder: 0,\n },\n ]\n : lead.rating\n ? [\n {\n id: 'testimonial-1',\n quote: `Rated ${lead.rating}/5 on Google${lead.reviewCount ? ` based on ${lead.reviewCount} reviews` : ''}`,\n name: 'Google Reviews',\n rating: Math.round(lead.rating),\n source: 'Google',\n featured: false,\n sortOrder: 0,\n },\n ]\n : undefined;\n\n return {\n business,\n hours,\n gallery,\n testimonials,\n };\n}\n\n/**\n * Create a complete site configuration from lead data in one step.\n *\n * Combines createSiteDataFromLead with defaults for the specified business type.\n *\n * @param lead - Lead data from scraping\n * @param businessType - Business type for defaults (e.g., 'tailor', 'restaurant')\n * @returns Complete site data ready for rendering\n *\n * @example\n * ```ts\n * const lead = { name: \"Maria's Alterations\", phone: \"555-1234\", category: \"tailor\" };\n * const siteData = await createSiteFromLead(lead, 'tailor');\n * ```\n */\nexport async function createSiteFromLead(\n lead: LeadData,\n businessType?: string\n): Promise<SiteData> {\n const partialData = createSiteDataFromLead(lead);\n const config = createInlineConfig(partialData);\n\n // Get industry-specific defaults if available\n const type = businessType || lead.category?.toLowerCase().replace(/\\s+/g, '-');\n let defaults = DEFAULT_SITE_DATA;\n\n if (type) {\n const typeKey = type as keyof typeof industryDefaults;\n if (typeKey in industryDefaults) {\n defaults = industryDefaults[typeKey]();\n }\n }\n\n return getSiteData(config, defaults);\n}\n","/**\n * SheetSite Data Types\n *\n * These types define the structure of data fetched from Google Sheets.\n * All data flows through these types, providing type safety across the entire site.\n */\n\nimport { z } from 'zod';\n\n// =============================================================================\n// BUSINESS INFO\n// =============================================================================\n\nexport const BusinessInfoSchema = z.object({\n name: z.string().min(1),\n tagline: z.string().optional(),\n description: z.string().optional(),\n aboutShort: z.string().optional(),\n aboutLong: z.string().optional(),\n\n // Contact\n phone: z.string().optional(),\n phoneAlt: z.string().optional(),\n email: z.string().email().optional().or(z.literal('')),\n\n // Address\n addressLine1: z.string().optional(),\n addressLine2: z.string().optional(),\n city: z.string().optional(),\n state: z.string().optional(),\n zip: z.string().optional(),\n country: z.string().default('USA'),\n\n // Location\n googleMapsUrl: z.string().url().optional().or(z.literal('')),\n mapsEmbedUrl: z.string().url().optional().or(z.literal('')),\n timezone: z.string().default('America/Los_Angeles'),\n\n // Images\n logoUrl: z.string().optional(),\n heroImageUrl: z.string().optional(),\n ogImageUrl: z.string().optional(),\n\n // Social\n socialYelp: z.string().url().optional().or(z.literal('')),\n socialInstagram: z.string().url().optional().or(z.literal('')),\n socialFacebook: z.string().url().optional().or(z.literal('')),\n socialTwitter: z.string().url().optional().or(z.literal('')),\n socialLinkedIn: z.string().url().optional().or(z.literal('')),\n socialYoutube: z.string().url().optional().or(z.literal('')),\n socialTiktok: z.string().url().optional().or(z.literal('')),\n\n // CTAs\n primaryCtaText: z.string().optional(),\n primaryCtaUrl: z.string().optional(),\n secondaryCtaText: z.string().optional(),\n secondaryCtaUrl: z.string().optional(),\n bookingUrl: z.string().url().optional().or(z.literal('')),\n\n // Banner\n bannerEnabled: z.boolean().default(false),\n bannerText: z.string().optional(),\n bannerUrl: z.string().optional(),\n\n // Business metadata\n priceRange: z.enum(['$', '$$', '$$$', '$$$$']).optional(),\n yearEstablished: z.number().optional(),\n licenseNumber: z.string().optional(),\n});\n\nexport type BusinessInfo = z.infer<typeof BusinessInfoSchema>;\n\n// =============================================================================\n// HOURS\n// =============================================================================\n\nexport const DayOfWeek = z.enum(['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']);\nexport type DayOfWeek = z.infer<typeof DayOfWeek>;\n\nexport const HoursEntrySchema = z.object({\n day: DayOfWeek,\n open: z.string().optional(), // e.g., \"9:00 AM\"\n close: z.string().optional(), // e.g., \"5:00 PM\"\n closed: z.boolean().default(false),\n});\n\nexport type HoursEntry = z.infer<typeof HoursEntrySchema>;\n\nexport const HoursSchema = z.array(HoursEntrySchema);\nexport type Hours = z.infer<typeof HoursSchema>;\n\n// =============================================================================\n// SERVICES\n// =============================================================================\n\nexport const ServiceSchema = z.object({\n id: z.string().optional(),\n title: z.string().min(1),\n description: z.string().optional(),\n priceNote: z.string().optional(), // e.g., \"Starting at $15\" or \"Call for quote\"\n price: z.number().optional(), // Exact price if applicable\n duration: z.string().optional(), // e.g., \"30 min\"\n icon: z.string().optional(), // Icon identifier\n imageUrl: z.string().optional(),\n featured: z.boolean().default(false),\n sortOrder: z.number().default(0),\n category: z.string().optional(),\n});\n\nexport type Service = z.infer<typeof ServiceSchema>;\n\nexport const ServicesSchema = z.array(ServiceSchema);\nexport type Services = z.infer<typeof ServicesSchema>;\n\n// =============================================================================\n// GALLERY\n// =============================================================================\n\nexport const GalleryItemSchema = z.object({\n id: z.string().optional(),\n imageUrl: z.string().min(1),\n alt: z.string().optional(),\n caption: z.string().optional(),\n featured: z.boolean().default(false),\n sortOrder: z.number().default(0),\n category: z.string().optional(),\n});\n\nexport type GalleryItem = z.infer<typeof GalleryItemSchema>;\n\nexport const GallerySchema = z.array(GalleryItemSchema);\nexport type Gallery = z.infer<typeof GallerySchema>;\n\n// =============================================================================\n// TESTIMONIALS / REVIEWS\n// =============================================================================\n\nexport const TestimonialSchema = z.object({\n id: z.string().optional(),\n quote: z.string().min(1),\n name: z.string().min(1),\n context: z.string().optional(), // e.g., \"Wedding alterations\"\n rating: z.number().min(1).max(5).optional(),\n source: z.string().optional(), // e.g., \"Google\", \"Yelp\"\n date: z.string().optional(),\n imageUrl: z.string().optional(), // Reviewer photo\n featured: z.boolean().default(false),\n sortOrder: z.number().default(0),\n});\n\nexport type Testimonial = z.infer<typeof TestimonialSchema>;\n\nexport const TestimonialsSchema = z.array(TestimonialSchema);\nexport type Testimonials = z.infer<typeof TestimonialsSchema>;\n\n// =============================================================================\n// FAQ\n// =============================================================================\n\nexport const FAQItemSchema = z.object({\n id: z.string().optional(),\n question: z.string().min(1),\n answer: z.string().min(1),\n category: z.string().optional(),\n sortOrder: z.number().default(0),\n});\n\nexport type FAQItem = z.infer<typeof FAQItemSchema>;\n\nexport const FAQSchema = z.array(FAQItemSchema);\nexport type FAQ = z.infer<typeof FAQSchema>;\n\n// =============================================================================\n// TEAM MEMBERS (for businesses that want to showcase staff)\n// =============================================================================\n\nexport const TeamMemberSchema = z.object({\n id: z.string().optional(),\n name: z.string().min(1),\n role: z.string().optional(),\n bio: z.string().optional(),\n imageUrl: z.string().optional(),\n email: z.string().email().optional().or(z.literal('')),\n phone: z.string().optional(),\n sortOrder: z.number().default(0),\n});\n\nexport type TeamMember = z.infer<typeof TeamMemberSchema>;\n\nexport const TeamSchema = z.array(TeamMemberSchema);\nexport type Team = z.infer<typeof TeamSchema>;\n\n// =============================================================================\n// MENU ITEMS (for restaurants, cafes, food businesses)\n// =============================================================================\n\nexport const MenuItemSchema = z.object({\n id: z.string().optional(),\n name: z.string().min(1),\n description: z.string().optional(),\n price: z.number().optional(),\n priceNote: z.string().optional(),\n category: z.string().optional(),\n imageUrl: z.string().optional(),\n dietary: z.array(z.string()).optional(), // e.g., [\"vegetarian\", \"gluten-free\"]\n featured: z.boolean().default(false),\n available: z.boolean().default(true),\n sortOrder: z.number().default(0),\n});\n\nexport type MenuItem = z.infer<typeof MenuItemSchema>;\n\nexport const MenuSchema = z.array(MenuItemSchema);\nexport type Menu = z.infer<typeof MenuSchema>;\n\n// =============================================================================\n// PRODUCTS (for craft sellers, retail)\n// =============================================================================\n\nexport const ProductSchema = z.object({\n id: z.string().optional(),\n name: z.string().min(1),\n description: z.string().optional(),\n price: z.number().optional(),\n priceNote: z.string().optional(),\n category: z.string().optional(),\n imageUrl: z.string().optional(),\n images: z.array(z.string()).optional(),\n inStock: z.boolean().default(true),\n featured: z.boolean().default(false),\n sortOrder: z.number().default(0),\n sku: z.string().optional(),\n purchaseUrl: z.string().url().optional().or(z.literal('')),\n});\n\nexport type Product = z.infer<typeof ProductSchema>;\n\nexport const ProductsSchema = z.array(ProductSchema);\nexport type Products = z.infer<typeof ProductsSchema>;\n\n// =============================================================================\n// ANNOUNCEMENTS / SPECIALS\n// =============================================================================\n\nexport const AnnouncementSchema = z.object({\n id: z.string().optional(),\n title: z.string().min(1),\n content: z.string().optional(),\n imageUrl: z.string().optional(),\n linkUrl: z.string().optional(),\n linkText: z.string().optional(),\n startDate: z.string().optional(),\n endDate: z.string().optional(),\n active: z.boolean().default(true),\n sortOrder: z.number().default(0),\n});\n\nexport type Announcement = z.infer<typeof AnnouncementSchema>;\n\nexport const AnnouncementsSchema = z.array(AnnouncementSchema);\nexport type Announcements = z.infer<typeof AnnouncementsSchema>;\n\n// =============================================================================\n// COMPLETE SITE DATA\n// =============================================================================\n\nexport const SiteDataSchema = z.object({\n business: BusinessInfoSchema,\n hours: HoursSchema,\n services: ServicesSchema,\n gallery: GallerySchema,\n testimonials: TestimonialsSchema,\n faq: FAQSchema,\n team: TeamSchema.optional(),\n menu: MenuSchema.optional(),\n products: ProductsSchema.optional(),\n announcements: AnnouncementsSchema.optional(),\n});\n\nexport type SiteData = z.infer<typeof SiteDataSchema>;\n\n// =============================================================================\n// PARTIAL SITE DATA (for merging with defaults)\n// =============================================================================\n\nexport const PartialSiteDataSchema = z.object({\n business: BusinessInfoSchema.partial().optional(),\n hours: HoursSchema.optional(),\n services: ServicesSchema.optional(),\n gallery: GallerySchema.optional(),\n testimonials: TestimonialsSchema.optional(),\n faq: FAQSchema.optional(),\n team: TeamSchema.optional(),\n menu: MenuSchema.optional(),\n products: ProductsSchema.optional(),\n announcements: AnnouncementsSchema.optional(),\n});\n\nexport type PartialSiteData = z.infer<typeof PartialSiteDataSchema>;\n\n// =============================================================================\n// SHEET CONFIGURATION\n// =============================================================================\n\nexport type SheetMode = 'public_csv' | 'private_api';\n\nexport interface SheetTabConfig {\n name: string;\n required: boolean;\n csvUrl?: string;\n}\n\nexport interface PublicCsvConfig {\n mode: 'public_csv';\n tabs: {\n business: string;\n hours?: string;\n services?: string;\n gallery?: string;\n testimonials?: string;\n faq?: string;\n team?: string;\n menu?: string;\n products?: string;\n announcements?: string;\n };\n}\n\nexport interface PrivateApiConfig {\n mode: 'private_api';\n sheetId: string;\n clientEmail: string;\n privateKey: string;\n tabs?: {\n business?: string;\n hours?: string;\n services?: string;\n gallery?: string;\n testimonials?: string;\n faq?: string;\n team?: string;\n menu?: string;\n products?: string;\n announcements?: string;\n };\n}\n\n/**\n * Inline data configuration - pass data directly without Google Sheets.\n * This is useful for:\n * - Rapid prototyping\n * - Automated site generation from CSV/JSON leads\n * - Testing without network requests\n * - Demo sites with pre-populated content\n */\nexport interface InlineDataConfig {\n mode: 'inline';\n data: PartialSiteData;\n}\n\nexport type SheetConfig = PublicCsvConfig | PrivateApiConfig | InlineDataConfig;\n\n// =============================================================================\n// UTILITY TYPES\n// =============================================================================\n\nexport interface ContactFormData {\n name: string;\n email: string;\n phone?: string;\n service?: string;\n message: string;\n}\n\nexport interface ContactFormResult {\n success: boolean;\n messageId?: string;\n error?: string;\n}\n","/**\n * CSV Parser\n *\n * A robust CSV parser that handles:\n * - Quoted fields with embedded commas\n * - Escaped quotes within quoted fields\n * - Various line endings (CRLF, LF)\n * - Empty values\n * - Header normalization\n */\n\nexport interface ParsedRow {\n [key: string]: string;\n}\n\n/**\n * Parse a CSV string into an array of objects.\n * Headers are normalized: lowercased and spaces replaced with underscores.\n */\nexport function parseCSV(csvText: string): ParsedRow[] {\n const lines = csvText.split(/\\r?\\n/);\n if (lines.length < 2) return [];\n\n // Parse header row\n const headers = parseCSVLine(lines[0]).map(normalizeHeader);\n if (headers.length === 0) return [];\n\n const rows: ParsedRow[] = [];\n\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i].trim();\n if (!line) continue;\n\n const values = parseCSVLine(line);\n const row: ParsedRow = {};\n\n for (let j = 0; j < headers.length; j++) {\n row[headers[j]] = values[j]?.trim() ?? '';\n }\n\n rows.push(row);\n }\n\n return rows;\n}\n\n/**\n * Parse a single CSV line, handling quoted fields correctly.\n */\nfunction parseCSVLine(line: string): string[] {\n const values: string[] = [];\n let current = '';\n let inQuotes = false;\n let i = 0;\n\n while (i < line.length) {\n const char = line[i];\n const nextChar = line[i + 1];\n\n if (inQuotes) {\n if (char === '\"') {\n if (nextChar === '\"') {\n // Escaped quote\n current += '\"';\n i += 2;\n } else {\n // End of quoted field\n inQuotes = false;\n i++;\n }\n } else {\n current += char;\n i++;\n }\n } else {\n if (char === '\"') {\n inQuotes = true;\n i++;\n } else if (char === ',') {\n values.push(current);\n current = '';\n i++;\n } else {\n current += char;\n i++;\n }\n }\n }\n\n // Push the last value\n values.push(current);\n\n return values;\n}\n\n/**\n * Normalize a header string:\n * - Convert to lowercase\n * - Replace spaces with underscores\n * - Remove special characters\n */\nexport function normalizeHeader(header: string): string {\n return header\n .toLowerCase()\n .trim()\n .replace(/\\s+/g, '_')\n .replace(/[^a-z0-9_]/g, '');\n}\n\n/**\n * Convert CSV rows to typed objects using a mapping function.\n */\nexport function mapRows<T>(\n rows: ParsedRow[],\n mapper: (row: ParsedRow, index: number) => T | null\n): T[] {\n return rows\n .map((row, index) => mapper(row, index))\n .filter((item): item is T => item !== null);\n}\n\n/**\n * Parse a boolean value from CSV (handles various formats).\n */\nexport function parseBoolean(value: string | undefined): boolean {\n if (!value) return false;\n const lower = value.toLowerCase().trim();\n return lower === 'true' || lower === 'yes' || lower === '1';\n}\n\n/**\n * Parse a number value from CSV.\n */\nexport function parseNumber(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const num = parseFloat(value);\n return isNaN(num) ? undefined : num;\n}\n\n/**\n * Parse an integer value from CSV.\n */\nexport function parseInteger(value: string | undefined): number | undefined {\n if (!value) return undefined;\n const num = parseInt(value, 10);\n return isNaN(num) ? undefined : num;\n}\n\n/**\n * Parse a sort order, defaulting to 0.\n */\nexport function parseSortOrder(value: string | undefined): number {\n return parseInteger(value) ?? 0;\n}\n","/**\n * Google Drive URL Utilities\n *\n * Handles conversion of various Google Drive sharing URLs to direct image URLs.\n * This is essential because Google Drive sharing URLs don't work directly with\n * Next.js Image component or standard <img> tags.\n */\n\n/**\n * Convert a Google Drive sharing URL to a direct view URL.\n *\n * Supported input formats:\n * - https://drive.google.com/file/d/FILE_ID/view?usp=sharing\n * - https://drive.google.com/file/d/FILE_ID/view\n * - https://drive.google.com/open?id=FILE_ID\n * - https://drive.google.com/uc?id=FILE_ID\n * - https://drive.google.com/uc?export=view&id=FILE_ID\n *\n * Output format:\n * - https://drive.google.com/uc?export=view&id=FILE_ID\n */\nexport function normalizeGoogleDriveUrl(url: string | undefined): string | undefined {\n if (!url) return undefined;\n\n // If it's not a Google Drive URL, return as-is\n if (!url.includes('drive.google.com')) {\n return url;\n }\n\n // Extract the file ID using various patterns\n let fileId: string | null = null;\n\n // Pattern 1: /file/d/FILE_ID/\n const filePattern = /\\/file\\/d\\/([a-zA-Z0-9_-]+)/;\n const fileMatch = url.match(filePattern);\n if (fileMatch) {\n fileId = fileMatch[1];\n }\n\n // Pattern 2: ?id=FILE_ID or &id=FILE_ID\n if (!fileId) {\n const idPattern = /[?&]id=([a-zA-Z0-9_-]+)/;\n const idMatch = url.match(idPattern);\n if (idMatch) {\n fileId = idMatch[1];\n }\n }\n\n // Pattern 3: /open?id=FILE_ID\n if (!fileId) {\n const openPattern = /\\/open\\?id=([a-zA-Z0-9_-]+)/;\n const openMatch = url.match(openPattern);\n if (openMatch) {\n fileId = openMatch[1];\n }\n }\n\n if (!fileId) {\n // Could not extract file ID, return original URL\n return url;\n }\n\n // Return the normalized direct view URL\n return `https://drive.google.com/uc?export=view&id=${fileId}`;\n}\n\n/**\n * Get a thumbnail URL for a Google Drive file.\n *\n * @param url - Original Google Drive URL\n * @param size - Thumbnail size (default: 400)\n * @returns Thumbnail URL or undefined\n */\nexport function getGoogleDriveThumbnail(\n url: string | undefined,\n size: number = 400\n): string | undefined {\n if (!url) return undefined;\n\n if (!url.includes('drive.google.com')) {\n return url;\n }\n\n // Extract file ID\n const normalizedUrl = normalizeGoogleDriveUrl(url);\n if (!normalizedUrl) return undefined;\n\n const idMatch = normalizedUrl.match(/id=([a-zA-Z0-9_-]+)/);\n if (!idMatch) return undefined;\n\n return `https://drive.google.com/thumbnail?id=${idMatch[1]}&sz=w${size}`;\n}\n\n/**\n * Check if a URL is a Google Drive URL.\n */\nexport function isGoogleDriveUrl(url: string | undefined): boolean {\n if (!url) return false;\n return url.includes('drive.google.com');\n}\n\n/**\n * Extract the file ID from a Google Drive URL.\n */\nexport function extractGoogleDriveFileId(url: string | undefined): string | null {\n if (!url) return null;\n\n // Pattern 1: /file/d/FILE_ID/\n const filePattern = /\\/file\\/d\\/([a-zA-Z0-9_-]+)/;\n const fileMatch = url.match(filePattern);\n if (fileMatch) return fileMatch[1];\n\n // Pattern 2: ?id=FILE_ID or &id=FILE_ID\n const idPattern = /[?&]id=([a-zA-Z0-9_-]+)/;\n const idMatch = url.match(idPattern);\n if (idMatch) return idMatch[1];\n\n return null;\n}\n\n/**\n * Process all image URLs in an object, converting Google Drive URLs to direct URLs.\n * This is useful for processing entire data objects.\n */\nexport function processImageUrls<T extends Record<string, unknown>>(\n obj: T,\n imageFields: string[] = ['imageUrl', 'logoUrl', 'heroImageUrl', 'ogImageUrl']\n): T {\n const result = { ...obj };\n\n for (const field of imageFields) {\n if (field in result && typeof result[field] === 'string') {\n (result as Record<string, unknown>)[field] = normalizeGoogleDriveUrl(result[field] as string);\n }\n }\n\n return result;\n}\n\n/**\n * Process an array of objects, normalizing image URLs in each.\n */\nexport function processImageUrlsInArray<T extends Record<string, unknown>>(\n arr: T[],\n imageFields: string[] = ['imageUrl', 'image_url', 'url']\n): T[] {\n return arr.map((item) => processImageUrls(item, imageFields));\n}\n","/**\n * Google Sheets Integration\n *\n * Provides data fetching from Google Sheets in two modes:\n * 1. Public CSV: Fetch published sheets via CSV URLs (simpler, no auth)\n * 2. Private API: Fetch via Google Sheets API with service account (more secure)\n *\n * Both modes return the same SiteData structure.\n */\n\nimport {\n type SiteData,\n type PartialSiteData,\n type SheetConfig,\n type PublicCsvConfig,\n type PrivateApiConfig,\n type InlineDataConfig,\n type BusinessInfo,\n type HoursEntry,\n type Service,\n type GalleryItem,\n type Testimonial,\n type FAQItem,\n type TeamMember,\n type MenuItem,\n type Product,\n type Announcement,\n type DayOfWeek,\n} from './types';\nimport { parseCSV, type ParsedRow, parseBoolean, parseNumber, parseSortOrder } from './csv-parser';\nimport { normalizeGoogleDriveUrl } from './google-drive';\n\n// =============================================================================\n// CONFIGURATION\n// =============================================================================\n\nconst DEFAULT_REVALIDATE = 300; // 5 minutes\n\nexport interface FetchOptions {\n revalidate?: number;\n cache?: RequestCache;\n}\n\n// =============================================================================\n// PUBLIC CSV MODE\n// =============================================================================\n\n/**\n * Fetch data from a published Google Sheet CSV URL.\n */\nasync function fetchCSV(url: string, options: FetchOptions = {}): Promise<string> {\n const response = await fetch(url, {\n next: { revalidate: options.revalidate ?? DEFAULT_REVALIDATE },\n cache: options.cache,\n });\n\n if (!response.ok) {\n throw new Error(`Failed to fetch CSV: ${response.status} ${response.statusText}`);\n }\n\n return response.text();\n}\n\n/**\n * Fetch and parse a CSV tab from a public sheet.\n */\nasync function fetchPublicTab<T>(\n url: string | undefined,\n parser: (rows: ParsedRow[]) => T,\n options: FetchOptions = {}\n): Promise<T | undefined> {\n if (!url) return undefined;\n\n try {\n const csvText = await fetchCSV(url, options);\n const rows = parseCSV(csvText);\n return parser(rows);\n } catch (error) {\n console.error(`Error fetching public tab from ${url}:`, error);\n return undefined;\n }\n}\n\n/**\n * Fetch all data from a public CSV configuration.\n */\nexport async function fetchPublicSheetData(\n config: PublicCsvConfig,\n options: FetchOptions = {}\n): Promise<PartialSiteData> {\n const [business, hours, services, gallery, testimonials, faq, team, menu, products, announcements] =\n await Promise.all([\n fetchPublicTab(config.tabs.business, parseBusinessRows, options),\n fetchPublicTab(config.tabs.hours, parseHoursRows, options),\n fetchPublicTab(config.tabs.services, parseServicesRows, options),\n fetchPublicTab(config.tabs.gallery, parseGalleryRows, options),\n fetchPublicTab(config.tabs.testimonials, parseTestimonialsRows, options),\n fetchPublicTab(config.tabs.faq, parseFAQRows, options),\n fetchPublicTab(config.tabs.team, parseTeamRows, options),\n fetchPublicTab(config.tabs.menu, parseMenuRows, options),\n fetchPublicTab(config.tabs.products, parseProductsRows, options),\n fetchPublicTab(config.tabs.announcements, parseAnnouncementsRows, options),\n ]);\n\n return {\n business,\n hours,\n services,\n gallery,\n testimonials,\n faq,\n team,\n menu,\n products,\n announcements,\n };\n}\n\n// =============================================================================\n// PRIVATE API MODE\n// =============================================================================\n\n/**\n * Create a JWT for Google Sheets API authentication.\n * Uses Web Crypto API - no external dependencies needed.\n */\nasync function createJWT(clientEmail: string, privateKey: string): Promise<string> {\n const now = Math.floor(Date.now() / 1000);\n\n const header = {\n alg: 'RS256',\n typ: 'JWT',\n };\n\n const payload = {\n iss: clientEmail,\n scope: 'https://www.googleapis.com/auth/spreadsheets.readonly',\n aud: 'https://oauth2.googleapis.com/token',\n iat: now,\n exp: now + 3600, // 1 hour\n };\n\n // Encode header and payload\n const encoder = new TextEncoder();\n const headerB64 = btoa(JSON.stringify(header))\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n const payloadB64 = btoa(JSON.stringify(payload))\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n\n const signInput = `${headerB64}.${payloadB64}`;\n\n // Parse PEM private key\n const pemContents = privateKey\n .replace(/-----BEGIN PRIVATE KEY-----/g, '')\n .replace(/-----END PRIVATE KEY-----/g, '')\n .replace(/\\\\n/g, '')\n .replace(/\\n/g, '')\n .replace(/\\s/g, '');\n\n const binaryKey = Uint8Array.from(atob(pemContents), (c) => c.charCodeAt(0));\n\n // Import key for signing\n const cryptoKey = await crypto.subtle.importKey(\n 'pkcs8',\n binaryKey,\n { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' },\n false,\n ['sign']\n );\n\n // Sign\n const signature = await crypto.subtle.sign(\n 'RSASSA-PKCS1-v1_5',\n cryptoKey,\n encoder.encode(signInput)\n );\n\n // Encode signature\n const signatureB64 = btoa(String.fromCharCode(...new Uint8Array(signature)))\n .replace(/\\+/g, '-')\n .replace(/\\//g, '_')\n .replace(/=/g, '');\n\n return `${signInput}.${signatureB64}`;\n}\n\n/**\n * Get an access token for the Google Sheets API.\n */\nasync function getAccessToken(clientEmail: string, privateKey: string): Promise<string> {\n const jwt = await createJWT(clientEmail, privateKey);\n\n const response = await fetch('https://oauth2.googleapis.com/token', {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: new URLSearchParams({\n grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',\n assertion: jwt,\n }),\n });\n\n if (!response.ok) {\n throw new Error(`Failed to get access token: ${response.status}`);\n }\n\n const data = await response.json();\n return data.access_token;\n}\n\n/**\n * Fetch a single tab from the Google Sheets API.\n */\nasync function fetchPrivateTab<T>(\n sheetId: string,\n tabName: string,\n accessToken: string,\n parser: (rows: ParsedRow[]) => T\n): Promise<T | undefined> {\n try {\n const url = `https://sheets.googleapis.com/v4/spreadsheets/${sheetId}/values/${encodeURIComponent(tabName)}`;\n\n const response = await fetch(url, {\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n\n if (!response.ok) {\n if (response.status === 404) {\n // Tab doesn't exist, return undefined\n return undefined;\n }\n throw new Error(`Failed to fetch tab ${tabName}: ${response.status}`);\n }\n\n const data = await response.json();\n const values: string[][] = data.values || [];\n\n if (values.length < 2) return undefined;\n\n // Convert array format to objects\n const headers = values[0].map((h: string) =>\n h.toLowerCase().trim().replace(/\\s+/g, '_').replace(/[^a-z0-9_]/g, '')\n );\n const rows: ParsedRow[] = [];\n\n for (let i = 1; i < values.length; i++) {\n const row: ParsedRow = {};\n for (let j = 0; j < headers.length; j++) {\n row[headers[j]] = values[i][j]?.trim() ?? '';\n }\n rows.push(row);\n }\n\n return parser(rows);\n } catch (error) {\n console.error(`Error fetching private tab ${tabName}:`, error);\n return undefined;\n }\n}\n\n/**\n * Fetch all data from a private API configuration.\n */\nexport async function fetchPrivateSheetData(\n config: PrivateApiConfig,\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n _options: FetchOptions = {}\n): Promise<PartialSiteData> {\n const accessToken = await getAccessToken(config.clientEmail, config.privateKey);\n\n const tabs = config.tabs || {};\n const sheetId = config.sheetId;\n\n const [business, hours, services, gallery, testimonials, faq, team, menu, products, announcements] =\n await Promise.all([\n fetchPrivateTab(sheetId, tabs.business || 'business', accessToken, parseBusinessRows),\n fetchPrivateTab(sheetId, tabs.hours || 'hours', accessToken, parseHoursRows),\n fetchPrivateTab(sheetId, tabs.services || 'services', accessToken, parseServicesRows),\n fetchPrivateTab(sheetId, tabs.gallery || 'gallery', accessToken, parseGalleryRows),\n fetchPrivateTab(sheetId, tabs.testimonials || 'testimonials', accessToken, parseTestimonialsRows),\n fetchPrivateTab(sheetId, tabs.faq || 'faq', accessToken, parseFAQRows),\n fetchPrivateTab(sheetId, tabs.team || 'team', accessToken, parseTeamRows),\n fetchPrivateTab(sheetId, tabs.menu || 'menu', accessToken, parseMenuRows),\n fetchPrivateTab(sheetId, tabs.products || 'products', accessToken, parseProductsRows),\n fetchPrivateTab(sheetId, tabs.announcements || 'announcements', accessToken, parseAnnouncementsRows),\n ]);\n\n return {\n business,\n hours,\n services,\n gallery,\n testimonials,\n faq,\n team,\n menu,\n products,\n announcements,\n };\n}\n\n// =============================================================================\n// INLINE DATA MODE\n// =============================================================================\n\n/**\n * Process inline data configuration.\n * Simply returns the provided data - no network requests needed.\n */\nexport function fetchInlineData(config: InlineDataConfig): PartialSiteData {\n return config.data;\n}\n\n// =============================================================================\n// UNIFIED FETCH\n// =============================================================================\n\n/**\n * Fetch site data using the provided configuration.\n * Automatically detects the mode and fetches accordingly.\n *\n * Supported modes:\n * - 'public_csv': Fetch from published Google Sheet CSV URLs\n * - 'private_api': Fetch via Google Sheets API with service account\n * - 'inline': Use provided data directly (no network requests)\n */\nexport async function fetchSheetData(\n config: SheetConfig,\n options: FetchOptions = {}\n): Promise<PartialSiteData> {\n switch (config.mode) {\n case 'public_csv':\n return fetchPublicSheetData(config, options);\n case 'private_api':\n return fetchPrivateSheetData(config, options);\n case 'inline':\n return fetchInlineData(config);\n }\n}\n\n// =============================================================================\n// ROW PARSERS\n// =============================================================================\n\n/**\n * Parse business info from rows (key-value format).\n */\nfunction parseBusinessRows(rows: ParsedRow[]): Partial<BusinessInfo> {\n const data: Record<string, string> = {};\n\n for (const row of rows) {\n const key = row.key?.toLowerCase().replace(/\\s+/g, '_');\n const value = row.value;\n if (key && value) {\n data[key] = value;\n }\n }\n\n return {\n name: data.name || data.business_name || '',\n tagline: data.tagline,\n description: data.description || data.about,\n aboutShort: data.about_short,\n aboutLong: data.about_long,\n phone: data.phone,\n phoneAlt: data.phone_alt || data.phone_secondary,\n email: data.email,\n addressLine1: data.address_line1 || data.address || data.street,\n addressLine2: data.address_line2,\n city: data.city,\n state: data.state,\n zip: data.zip || data.zipcode || data.postal_code,\n country: data.country || 'USA',\n googleMapsUrl: data.google_maps_url || data.maps_url,\n mapsEmbedUrl: data.maps_embed_url || data.embed_url,\n timezone: data.timezone || 'America/Los_Angeles',\n logoUrl: normalizeGoogleDriveUrl(data.logo_url || data.logo),\n heroImageUrl: normalizeGoogleDriveUrl(data.hero_image_url || data.hero_image || data.hero_photo_url),\n ogImageUrl: normalizeGoogleDriveUrl(data.og_image_url || data.og_image),\n socialYelp: data.social_yelp || data.yelp,\n socialInstagram: data.social_instagram || data.instagram,\n socialFacebook: data.social_facebook || data.facebook,\n socialTwitter: data.social_twitter || data.twitter,\n socialLinkedIn: data.social_linkedin || data.linkedin,\n socialYoutube: data.social_youtube || data.youtube,\n socialTiktok: data.social_tiktok || data.tiktok,\n primaryCtaText: data.primary_cta_text || data.cta_text,\n primaryCtaUrl: data.primary_cta_url || data.cta_url,\n secondaryCtaText: data.secondary_cta_text,\n secondaryCtaUrl: data.secondary_cta_url,\n bookingUrl: data.booking_url || data.booking_or_quote_url,\n bannerEnabled: parseBoolean(data.banner_enabled),\n bannerText: data.banner_text,\n bannerUrl: data.banner_url,\n priceRange: data.price_range as BusinessInfo['priceRange'],\n yearEstablished: parseNumber(data.year_established),\n licenseNumber: data.license_number,\n };\n}\n\n/**\n * Parse hours from rows.\n */\nfunction parseHoursRows(rows: ParsedRow[]): HoursEntry[] {\n const dayMap: Record<string, DayOfWeek> = {\n monday: 'monday',\n mon: 'monday',\n tuesday: 'tuesday',\n tue: 'tuesday',\n tues: 'tuesday',\n wednesday: 'wednesday',\n wed: 'wednesday',\n thursday: 'thursday',\n thu: 'thursday',\n thur: 'thursday',\n thurs: 'thursday',\n friday: 'friday',\n fri: 'friday',\n saturday: 'saturday',\n sat: 'saturday',\n sunday: 'sunday',\n sun: 'sunday',\n };\n\n return rows\n .map((row) => {\n const dayKey = (row.day || row.day_of_week || '').toLowerCase();\n const day = dayMap[dayKey];\n if (!day) return null;\n\n return {\n day,\n open: row.open || row.open_time || row.opens,\n close: row.close || row.close_time || row.closes,\n closed: parseBoolean(row.closed),\n };\n })\n .filter((entry): entry is HoursEntry => entry !== null);\n}\n\n/**\n * Parse services from rows.\n */\nfunction parseServicesRows(rows: ParsedRow[]): Service[] {\n return rows\n .map((row, index) => {\n const title = row.title || row.name || row.service;\n if (!title) return null;\n\n return {\n id: row.id || `service-${index}`,\n title,\n description: row.description || row.desc,\n priceNote: row.price_note || row.price_hint || row.pricing,\n price: parseNumber(row.price),\n duration: row.duration || row.time,\n icon: row.icon,\n imageUrl: normalizeGoogleDriveUrl(row.image_url || row.image),\n featured: parseBoolean(row.featured),\n sortOrder: parseSortOrder(row.sort_order || row.sort),\n category: row.category,\n };\n })\n .filter((service): service is Service => service !== null)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n}\n\n/**\n * Parse gallery items from rows.\n */\nfunction parseGalleryRows(rows: ParsedRow[]): GalleryItem[] {\n return rows\n .map((row, index) => {\n const imageUrl = normalizeGoogleDriveUrl(row.image_url || row.url || row.image);\n if (!imageUrl) return null;\n\n return {\n id: row.id || `gallery-${index}`,\n imageUrl,\n alt: row.alt || row.alt_text || row.description || '',\n caption: row.caption,\n featured: parseBoolean(row.featured),\n sortOrder: parseSortOrder(row.sort_order || row.sort),\n category: row.category,\n };\n })\n .filter((item): item is GalleryItem => item !== null)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n}\n\n/**\n * Parse testimonials from rows.\n */\nfunction parseTestimonialsRows(rows: ParsedRow[]): Testimonial[] {\n return rows\n .map((row, index) => {\n const quote = row.quote || row.text || row.review || row.testimonial;\n const name = row.name || row.author || row.reviewer;\n if (!quote || !name) return null;\n\n return {\n id: row.id || `testimonial-${index}`,\n quote,\n name,\n context: row.context || row.service,\n rating: parseNumber(row.rating),\n source: row.source || row.source_label || row.platform,\n date: row.date,\n imageUrl: normalizeGoogleDriveUrl(row.image_url || row.photo),\n featured: parseBoolean(row.featured),\n sortOrder: parseSortOrder(row.sort_order || row.sort),\n };\n })\n .filter((item): item is Testimonial => item !== null)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n}\n\n/**\n * Parse FAQ items from rows.\n */\nfunction parseFAQRows(rows: ParsedRow[]): FAQItem[] {\n return rows\n .map((row, index) => {\n const question = row.question || row.q;\n const answer = row.answer || row.a;\n if (!question || !answer) return null;\n\n return {\n id: row.id || `faq-${index}`,\n question,\n answer,\n category: row.category,\n sortOrder: parseSortOrder(row.sort_order || row.sort),\n };\n })\n .filter((item): item is FAQItem => item !== null)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n}\n\n/**\n * Parse team members from rows.\n */\nfunction parseTeamRows(rows: ParsedRow[]): TeamMember[] {\n return rows\n .map((row, index) => {\n const name = row.name;\n if (!name) return null;\n\n return {\n id: row.id || `team-${index}`,\n name,\n role: row.role || row.title || row.position,\n bio: row.bio || row.description,\n imageUrl: normalizeGoogleDriveUrl(row.image_url || row.photo || row.image),\n email: row.email,\n phone: row.phone,\n sortOrder: parseSortOrder(row.sort_order || row.sort),\n };\n })\n .filter((item): item is TeamMember => item !== null)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n}\n\n/**\n * Parse menu items from rows.\n */\nfunction parseMenuRows(rows: ParsedRow[]): MenuItem[] {\n return rows\n .map((row, index) => {\n const name = row.name || row.item || row.title;\n if (!name) return null;\n\n const dietary = row.dietary || row.tags || row.dietary_tags;\n\n return {\n id: row.id || `menu-${index}`,\n name,\n description: row.description || row.desc,\n price: parseNumber(row.price),\n priceNote: row.price_note || row.pricing,\n category: row.category || row.section,\n imageUrl: normalizeGoogleDriveUrl(row.image_url || row.image),\n dietary: dietary ? dietary.split(',').map((s: string) => s.trim()) : undefined,\n featured: parseBoolean(row.featured),\n available: row.available !== undefined ? parseBoolean(row.available) : true,\n sortOrder: parseSortOrder(row.sort_order || row.sort),\n };\n })\n .filter((item): item is MenuItem => item !== null)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n}\n\n/**\n * Parse products from rows.\n */\nfunction parseProductsRows(rows: ParsedRow[]): Product[] {\n const products = rows\n .map((row, index): Product | null => {\n const name = row.name || row.product || row.title;\n if (!name) return null;\n\n const images = row.images || row.additional_images;\n\n const product: Product = {\n name,\n featured: parseBoolean(row.featured),\n sortOrder: parseSortOrder(row.sort_order || row.sort),\n inStock: row.in_stock !== undefined ? parseBoolean(row.in_stock) : true,\n };\n\n if (row.id) product.id = row.id;\n else product.id = `product-${index}`;\n\n if (row.description || row.desc) product.description = row.description || row.desc;\n if (parseNumber(row.price) !== undefined) product.price = parseNumber(row.price);\n if (row.price_note || row.pricing) product.priceNote = row.price_note || row.pricing;\n if (row.category) product.category = row.category;\n\n const imageUrl = normalizeGoogleDriveUrl(row.image_url || row.image);\n if (imageUrl) product.imageUrl = imageUrl;\n\n if (images) {\n product.images = images\n .split(',')\n .map((s: string) => normalizeGoogleDriveUrl(s.trim()))\n .filter(Boolean) as string[];\n }\n\n if (row.sku) product.sku = row.sku;\n if (row.purchase_url || row.buy_url || row.shop_url) {\n product.purchaseUrl = row.purchase_url || row.buy_url || row.shop_url;\n }\n\n return product;\n })\n .filter((item): item is Product => item !== null);\n\n return products.sort((a, b) => a.sortOrder - b.sortOrder);\n}\n\n/**\n * Parse announcements from rows.\n */\nfunction parseAnnouncementsRows(rows: ParsedRow[]): Announcement[] {\n const announcements = rows\n .map((row, index): Announcement | null => {\n const title = row.title || row.headline;\n if (!title) return null;\n\n const announcement: Announcement = {\n title,\n sortOrder: parseSortOrder(row.sort_order || row.sort),\n active: row.active !== undefined ? parseBoolean(row.active) : true,\n };\n\n if (row.id) announcement.id = row.id;\n else announcement.id = `announcement-${index}`;\n\n if (row.content || row.description || row.body) {\n announcement.content = row.content || row.description || row.body;\n }\n\n const imageUrl = normalizeGoogleDriveUrl(row.image_url || row.image);\n if (imageUrl) announcement.imageUrl = imageUrl;\n\n if (row.link_url || row.url || row.link) {\n announcement.linkUrl = row.link_url || row.url || row.link;\n }\n if (row.link_text || row.cta) announcement.linkText = row.link_text || row.cta;\n if (row.start_date) announcement.startDate = row.start_date;\n if (row.end_date) announcement.endDate = row.end_date;\n\n return announcement;\n })\n .filter((item): item is Announcement => item !== null);\n\n return announcements.sort((a, b) => a.sortOrder - b.sortOrder);\n}\n\n// =============================================================================\n// MERGE WITH DEFAULTS\n// =============================================================================\n\n/**\n * Merge partial site data with defaults to create complete site data.\n */\nexport function mergeSiteData(\n partial: PartialSiteData,\n defaults: SiteData\n): SiteData {\n return {\n business: {\n ...defaults.business,\n ...partial.business,\n },\n hours: partial.hours ?? defaults.hours,\n services: partial.services ?? defaults.services,\n gallery: partial.gallery ?? defaults.gallery,\n testimonials: partial.testimonials ?? defaults.testimonials,\n faq: partial.faq ?? defaults.faq,\n team: partial.team ?? defaults.team,\n menu: partial.menu ?? defaults.menu,\n products: partial.products ?? defaults.products,\n announcements: partial.announcements ?? defaults.announcements,\n };\n}\n","/**\n * Default Site Data\n *\n * Provides fallback data when Google Sheets data is unavailable.\n * These defaults are used during development and as graceful fallbacks.\n */\n\nimport type { SiteData } from './types';\n\n/**\n * Create default site data with customizable business name.\n */\nexport function createDefaultSiteData(businessName: string = 'Your Business'): SiteData {\n return {\n business: {\n name: businessName,\n tagline: 'Quality Service You Can Trust',\n description: `Welcome to ${businessName}. We are dedicated to providing exceptional service to our community.`,\n aboutShort: `${businessName} has been serving our community with dedication and excellence.`,\n aboutLong: `${businessName} was founded with a simple mission: to provide outstanding service with a personal touch. Our team of experienced professionals is committed to exceeding your expectations every time.`,\n phone: '(555) 123-4567',\n email: 'info@example.com',\n addressLine1: '123 Main Street',\n city: 'Anytown',\n state: 'CA',\n zip: '12345',\n country: 'USA',\n timezone: 'America/Los_Angeles',\n primaryCtaText: 'Contact Us',\n priceRange: '$$',\n },\n hours: [\n { day: 'monday', open: '9:00 AM', close: '5:00 PM', closed: false },\n { day: 'tuesday', open: '9:00 AM', close: '5:00 PM', closed: false },\n { day: 'wednesday', open: '9:00 AM', close: '5:00 PM', closed: false },\n { day: 'thursday', open: '9:00 AM', close: '5:00 PM', closed: false },\n { day: 'friday', open: '9:00 AM', close: '5:00 PM', closed: false },\n { day: 'saturday', open: '10:00 AM', close: '3:00 PM', closed: false },\n { day: 'sunday', closed: true },\n ],\n services: [\n {\n id: 'service-1',\n title: 'Service One',\n description: 'Our primary service offering, designed to meet your needs.',\n priceNote: 'Starting at $50',\n sortOrder: 1,\n },\n {\n id: 'service-2',\n title: 'Service Two',\n description: 'Another excellent option for our valued customers.',\n priceNote: 'Call for pricing',\n sortOrder: 2,\n },\n {\n id: 'service-3',\n title: 'Service Three',\n description: 'A specialized service for unique requirements.',\n priceNote: 'Custom quote',\n sortOrder: 3,\n },\n ],\n gallery: [],\n testimonials: [\n {\n id: 'testimonial-1',\n quote: 'Excellent service! I highly recommend them to anyone looking for quality work.',\n name: 'Happy Customer',\n rating: 5,\n sortOrder: 1,\n },\n {\n id: 'testimonial-2',\n quote: 'Professional, timely, and great attention to detail. Will definitely return!',\n name: 'Satisfied Client',\n rating: 5,\n sortOrder: 2,\n },\n ],\n faq: [\n {\n id: 'faq-1',\n question: 'What are your hours of operation?',\n answer: 'We are open Monday through Friday from 9 AM to 5 PM, and Saturday from 10 AM to 3 PM. We are closed on Sundays.',\n sortOrder: 1,\n },\n {\n id: 'faq-2',\n question: 'How can I contact you?',\n answer: 'You can reach us by phone, email, or by filling out the contact form on our website. We typically respond within 24 hours.',\n sortOrder: 2,\n },\n {\n id: 'faq-3',\n question: 'Do you offer free estimates?',\n answer: 'Yes! We offer free estimates for all our services. Contact us to schedule a consultation.',\n sortOrder: 3,\n },\n ],\n };\n}\n\n/**\n * Default site data instance.\n */\nexport const DEFAULT_SITE_DATA = createDefaultSiteData();\n\n/**\n * Industry-specific default data generators.\n */\nexport const industryDefaults = {\n tailor: (): SiteData => ({\n ...createDefaultSiteData('Expert Tailoring'),\n services: [\n { id: 's1', title: 'Alterations', description: 'Expert alterations for all garments', priceNote: 'Starting at $15', sortOrder: 1 },\n { id: 's2', title: 'Hemming', description: 'Professional hemming for pants, skirts, and dresses', priceNote: 'From $12', sortOrder: 2 },\n { id: 's3', title: 'Wedding & Formal', description: 'Specialized alterations for wedding dresses and formal wear', priceNote: 'Custom quote', sortOrder: 3 },\n { id: 's4', title: 'Custom Tailoring', description: 'Made-to-measure suits and garments', priceNote: 'By consultation', sortOrder: 4 },\n ],\n faq: [\n { id: 'f1', question: 'How long do alterations take?', answer: 'Most alterations are completed within 3-5 business days. Rush service is available for an additional fee.', sortOrder: 1 },\n { id: 'f2', question: 'Do you work on leather or suede?', answer: 'Yes, we have experience with leather and suede garments. These require specialized care and may take longer.', sortOrder: 2 },\n { id: 'f3', question: 'Can you match fabric for repairs?', answer: 'We maintain an extensive fabric library and can often find close matches. Bring your garment in for assessment.', sortOrder: 3 },\n ],\n }),\n\n restaurant: (): SiteData => ({\n ...createDefaultSiteData('Local Restaurant'),\n services: [],\n menu: [\n { id: 'm1', name: 'Signature Dish', description: 'Our house specialty', price: 18.99, category: 'Entrees', sortOrder: 1 },\n { id: 'm2', name: 'Fresh Salad', description: 'Garden fresh ingredients', price: 12.99, category: 'Salads', sortOrder: 2 },\n { id: 'm3', name: 'Daily Special', description: 'Ask your server for today\\'s special', priceNote: 'Market price', category: 'Specials', sortOrder: 3 },\n ],\n faq: [\n { id: 'f1', question: 'Do you take reservations?', answer: 'Yes! We recommend reservations for parties of 4 or more, especially on weekends.', sortOrder: 1 },\n { id: 'f2', question: 'Do you offer takeout?', answer: 'Yes, we offer both takeout and delivery through our website.', sortOrder: 2 },\n { id: 'f3', question: 'Do you accommodate dietary restrictions?', answer: 'Absolutely! We have vegetarian, vegan, and gluten-free options. Please inform your server of any allergies.', sortOrder: 3 },\n ],\n }),\n\n salon: (): SiteData => ({\n ...createDefaultSiteData('Beauty Salon'),\n services: [\n { id: 's1', title: 'Haircut', description: 'Professional cut and style', priceNote: 'From $35', sortOrder: 1 },\n { id: 's2', title: 'Color Services', description: 'Full color, highlights, and balayage', priceNote: 'From $75', sortOrder: 2 },\n { id: 's3', title: 'Styling', description: 'Blowouts and special occasion styling', priceNote: 'From $45', sortOrder: 3 },\n { id: 's4', title: 'Treatments', description: 'Deep conditioning and keratin treatments', priceNote: 'From $50', sortOrder: 4 },\n ],\n faq: [\n { id: 'f1', question: 'Do I need an appointment?', answer: 'Appointments are recommended but we do accept walk-ins based on availability.', sortOrder: 1 },\n { id: 'f2', question: 'What is your cancellation policy?', answer: 'We require 24-hour notice for cancellations to avoid a cancellation fee.', sortOrder: 2 },\n { id: 'f3', question: 'Do you offer consultations?', answer: 'Yes! Free consultations are available for color services and major transformations.', sortOrder: 3 },\n ],\n }),\n\n homeKitchen: (): SiteData => ({\n ...createDefaultSiteData('Home Kitchen'),\n services: [],\n products: [\n { id: 'p1', name: 'Fresh Baked Goods', description: 'Made fresh daily', priceNote: 'Varies', category: 'Baked Goods', sortOrder: 1 },\n { id: 'p2', name: 'Preserves & Jams', description: 'Homemade with local ingredients', priceNote: 'From $8', category: 'Preserves', sortOrder: 2 },\n { id: 'p3', name: 'Custom Orders', description: 'Special occasion cakes and treats', priceNote: 'By quote', category: 'Custom', sortOrder: 3 },\n ],\n faq: [\n { id: 'f1', question: 'Do you accommodate dietary restrictions?', answer: 'Yes! We offer gluten-free, vegan, and sugar-free options. Please inquire about specific needs.', sortOrder: 1 },\n { id: 'f2', question: 'How far in advance should I order?', answer: 'For custom orders, we recommend at least 1 week notice. 2 weeks for large orders.', sortOrder: 2 },\n { id: 'f3', question: 'Do you deliver?', answer: 'Local delivery is available for orders over $25. Contact us for delivery area details.', sortOrder: 3 },\n ],\n }),\n\n repair: (): SiteData => ({\n ...createDefaultSiteData('Repair Shop'),\n services: [\n { id: 's1', title: 'Basic Repair', description: 'Standard repairs and fixes', priceNote: 'From $20', sortOrder: 1 },\n { id: 's2', title: 'Restoration', description: 'Full restoration services', priceNote: 'By quote', sortOrder: 2 },\n { id: 's3', title: 'Rush Service', description: 'Same-day or next-day service', priceNote: '+50%', sortOrder: 3 },\n { id: 's4', title: 'Custom Work', description: 'Specialized and custom requests', priceNote: 'By consultation', sortOrder: 4 },\n ],\n faq: [\n { id: 'f1', question: 'How long do repairs take?', answer: 'Standard repairs typically take 3-5 business days. Rush service is available.', sortOrder: 1 },\n { id: 'f2', question: 'Do you offer a warranty?', answer: 'Yes, all repairs come with a 90-day warranty against workmanship defects.', sortOrder: 2 },\n { id: 'f3', question: 'Do you provide estimates?', answer: 'Yes, we provide free estimates before beginning any work.', sortOrder: 3 },\n ],\n }),\n\n professional: (): SiteData => ({\n ...createDefaultSiteData('Professional Services'),\n services: [\n { id: 's1', title: 'Consultation', description: 'Initial consultation and assessment', priceNote: 'Free', sortOrder: 1 },\n { id: 's2', title: 'Standard Service', description: 'Our core service offering', priceNote: 'From $100', sortOrder: 2 },\n { id: 's3', title: 'Premium Package', description: 'Comprehensive service with priority support', priceNote: 'From $250', sortOrder: 3 },\n { id: 's4', title: 'Ongoing Support', description: 'Monthly retainer for continuous support', priceNote: 'Monthly', sortOrder: 4 },\n ],\n faq: [\n { id: 'f1', question: 'What is your availability?', answer: 'We maintain flexible hours to accommodate our clients. Contact us to schedule an appointment.', sortOrder: 1 },\n { id: 'f2', question: 'Do you offer remote services?', answer: 'Yes, many of our services can be provided remotely via video conference.', sortOrder: 2 },\n { id: 'f3', question: 'What forms of payment do you accept?', answer: 'We accept all major credit cards, checks, and bank transfers.', sortOrder: 3 },\n ],\n }),\n};\n"],"mappings":"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","names":[]}