@anker-in/ui 0.1.19 → 0.2.1

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/cn.ts","../src/components/DemoRoom/components/Title.tsx","../src/components/DemoRoom/components/StudioCard.tsx","../src/components/DemoRoom/components/StudioMap.tsx","../src/api/types.ts","../src/api/hooks.ts","../src/components/DemoRoom/components/AntdMobileIsolated.tsx","../src/components/DemoRoom/utils/addressParser.ts","../src/components/DemoRoom/components/RoomsList.module.css","../src/components/DemoRoom/components/LocationFilter.tsx","../src/components/DemoRoom/components/RoomsList.tsx","../src/api/client.ts","../src/components/DemoRoom/DemoRoom.tsx"],"names":["twMerge","clsx","jsx","React","jsxs","useState","useEffect","useRef","items","useMemo","List","IndexBar"],"mappings":"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","file":"demo-room.js","sourcesContent":["import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import React from 'react'\nimport { cn } from '@/utils/cn'\n\nexport interface TitleProps extends React.HTMLAttributes<HTMLDivElement> {\n title?: string\n subTitle?: string\n}\n\nexport const Title: React.FC<TitleProps> = ({\n title = '',\n ...props\n}) => {\n return (\n <div className={cn('w-full')} {...props}>\n {/* Section Title */}\n <h2 className=\"text-[32px] min-l:text-[48px] font-bold mb-12 text-[#080A0F]\">\n {title}\n </h2>\n </div>\n )\n}\n\nTitle.displayName = 'Title'\n","import React from 'react'\nimport { cn } from '@/utils/cn'\n\nexport interface StudioCardProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Demo room code (unique identifier)\n */\n code: string\n /**\n * Studio name\n */\n name: string\n /**\n * Available time\n */\n availableTime: string\n /**\n * Full address\n */\n address: string\n city: string\n state: string\n zipCode: string\n country?: string\n /**\n * Available euifyMake models\n */\n euifyMakeModel: string\n /**\n * Distance from user location (optional)\n */\n distance?: number\n /**\n * Callback when \"Schedule Now\" is clicked, receives demo room code\n */\n onSchedule?: (code: string) => void\n /**\n * 可配置的文案数据\n */\n pageData?: {\n scheduleNow?: string\n available?: string\n away?: string\n noAvailableTime?: string\n }\n}\n\nexport const StudioCard: React.FC<StudioCardProps> = ({\n code,\n name,\n availableTime,\n address,\n euifyMakeModel,\n distance,\n onSchedule,\n pageData = {\n scheduleNow: 'Schedule Now',\n available: 'Available',\n away: 'away',\n },\n className,\n style,\n ...props\n}) => {\n const [isHovered, setIsHovered] = React.useState(false)\n\n const handleScheduleClick = () => {\n onSchedule?.(code)\n }\n\n // 格式化距离显示\n const formatDistance = (dist: number) => {\n if (dist < 1) {\n return `${Math.round(dist * 1000)} m`\n }\n return `${dist.toFixed(1)} km`\n }\n\n return (\n <div\n {...props}\n className={cn(\n 'p-6 cursor-pointer transition-colors duration-200 border-b border-[#E4E5E6] last:border-b-0',\n className\n )}\n style={{\n backgroundColor: isHovered ? '#f3f4f6' : 'transparent',\n ...style,\n }}\n onMouseEnter={(e) => {\n setIsHovered(true)\n props.onMouseEnter?.(e)\n }}\n onMouseLeave={(e) => {\n setIsHovered(false)\n props.onMouseLeave?.(e)\n }}\n >\n {/* Studio Name and Distance */}\n <div className=\"flex items-start justify-between mb-4\">\n <h3 className=\"text-[24px] l:text-[20px] font-bold text-[#080A0F]\">\n {name}\n </h3>\n {distance !== undefined && (\n <span className=\"text-[16px] l:text-[14px] font-medium text-[#2E8B57] bg-[#E8F5E9] px-3 py-1 rounded-full whitespace-nowrap ml-2\">\n {formatDistance(distance)} {pageData.away}\n </span>\n )}\n </div>\n\n {/* Available Time */}\n {availableTime && (\n <div className=\"flex items-start gap-3 mb-3\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"flex-shrink-0 mt-0.5\"\n >\n <rect\n x=\"3\"\n y=\"4\"\n width=\"14\"\n height=\"13\"\n rx=\"2\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M3 8H17\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M6 2V4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M14 2V4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n <div>\n <p className=\"text-[16px] l:text-[12px] text-[#2A2C32]\">\n {availableTime === pageData.noAvailableTime\n ? ''\n : pageData.available}{' '}\n {availableTime}\n </p>\n </div>\n </div>\n )}\n\n {/* Address */}\n <div className=\"flex items-start gap-3 mb-3\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"flex-shrink-0 mt-0.5\"\n >\n <path\n d=\"M10 10C11.1046 10 12 9.10457 12 8C12 6.89543 11.1046 6 10 6C8.89543 6 8 6.89543 8 8C8 9.10457 8.89543 10 10 10Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M10 18C10 18 16 13 16 8C16 4.68629 13.3137 2 10 2C6.68629 2 4 4.68629 4 8C4 13 10 18 10 18Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n </svg>\n <div className=\"flex-1\">\n <p className=\"text-[16px] l:text-[14px] text-[#2A2C32] break-words\">\n {address}\n </p>\n </div>\n </div>\n\n {/* euifyMake Models */}\n <div className=\"flex items-start gap-3 mb-6\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"flex-shrink-0 mt-0.5\"\n >\n <path\n d=\"M14.4643 7.4929H9.65565M3.16391 18.7132H20.8171C22.0122 18.7132 22.981 17.7563 22.981 16.576L23 13.8348L22.981 6.42431C22.981 5.24396 22.0122 4.28711 20.8171 4.28711H3.16391C1.96882 4.28711 1 5.24396 1 6.42431V16.576C1 17.7563 1.96882 18.7132 3.16391 18.7132Z\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M5.32812 18.2325V14.4238C5.32812 13.8715 5.77584 13.4238 6.32813 13.4238H17.7925C18.3447 13.4238 18.7925 13.8715 18.7925 14.4238V18.2325\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n <div>\n <p className=\"text-[16px] l:text-[14px] text-[#2A2C32]\">\n {euifyMakeModel}\n </p>\n </div>\n </div>\n\n {/* Schedule Button */}\n <button\n onClick={handleScheduleClick}\n className={cn(\n 'w-fit px-[28px] l:px-[20px] l:py-[8px] py-3 rounded-full',\n 'bg-white text-gray-900 border-2 border-gray-900',\n 'font-bold text-[16px] l:text-[14px]',\n 'hover:bg-gray-900 hover:text-white',\n 'transition-all duration-200'\n )}\n >\n {pageData.scheduleNow}\n </button>\n </div>\n )\n}\n\nStudioCard.displayName = 'StudioCard'\n","import React, { useState } from 'react'\nimport { cn } from '@/utils/cn'\n\nexport interface StudioLocation {\n id: string\n name: string\n address: string\n city: string\n state: string\n zipCode: string\n country: string\n lat: number\n lng: number\n availableTime?: string\n euifyMakeModel?: string\n distance?: number\n}\n\nexport interface StudioMapProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * 谷歌地图 API Key\n */\n googleMapsApiKey: string\n /**\n * 工作室位置数据\n */\n locations?: StudioLocation[]\n /**\n * 当前 hover 的位置 ID\n */\n hoveredLocationId?: string | null\n /**\n * 默认中心点\n */\n defaultCenter?: { lat: number; lng: number }\n /**\n * 默认缩放级别\n */\n defaultZoom?: number\n /**\n * 地图高度\n */\n mapHeight?: string\n /**\n * 点击 Schedule Now 的回调\n */\n onSchedule?: (demoRoomCode: string) => void\n /**\n * 可配置的文案数据\n */\n pageData?: {\n apiKeyRequired?: string\n loadingMap?: string\n scheduleNow?: string\n available?: string\n noAvailableTime?: string\n }\n}\n\nconst defaultLocations: StudioLocation[] = [\n {\n id: '1',\n name: 'Design District Demo Room',\n address: '111 8th St',\n city: 'San Francisco',\n state: 'CA',\n zipCode: '94108',\n country: 'United States',\n lat: 37.7749,\n lng: -122.4194,\n availableTime: 'Oct 28, 2:00 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n]\n\nexport const StudioMap: React.FC<StudioMapProps> = ({\n googleMapsApiKey,\n locations = defaultLocations,\n hoveredLocationId,\n defaultCenter = { lat: 39.8283, lng: -98.5795 }, // US center\n defaultZoom = 4,\n mapHeight = '600px',\n onSchedule,\n pageData = {\n apiKeyRequired: 'Google Maps API Key is required',\n loadingMap: 'Loading map...',\n scheduleNow: 'Schedule Now',\n available: 'Available',\n },\n className,\n ...props\n}) => {\n const [_selectedLocation, setSelectedLocation] =\n useState<StudioLocation | null>(null)\n const [isLoaded, setIsLoaded] = useState(false)\n const mapRef = React.useRef<HTMLDivElement>(null)\n const googleMapRef = React.useRef<google.maps.Map | null>(null)\n const markersRef = React.useRef<google.maps.Marker[]>([])\n const infoWindowRef = React.useRef<google.maps.InfoWindow | null>(null)\n\n // 加载谷歌地图脚本\n React.useEffect(() => {\n if (!googleMapsApiKey) {\n console.error('Google Maps API Key is required')\n return\n }\n\n // 检查脚本是否已加载\n if (window.google && window.google.maps) {\n setIsLoaded(true)\n return\n }\n\n const script = document.createElement('script')\n script.src = `https://maps.googleapis.com/maps/api/js?key=${googleMapsApiKey}&libraries=places`\n script.async = true\n script.defer = true\n script.onload = () => setIsLoaded(true)\n script.onerror = () => console.error('Failed to load Google Maps script')\n document.head.appendChild(script)\n\n return () => {\n // 清理脚本(可选)\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }, [googleMapsApiKey])\n\n // 初始化地图\n React.useEffect(() => {\n if (!isLoaded || !mapRef.current || googleMapRef.current) return\n\n // 创建地图\n const map = new google.maps.Map(mapRef.current, {\n center: defaultCenter,\n zoom: defaultZoom,\n styles: [\n {\n featureType: 'all',\n elementType: 'geometry',\n stylers: [{ color: '#E0F2F1' }],\n },\n {\n featureType: 'water',\n elementType: 'geometry',\n stylers: [{ color: '#B2EBF2' }],\n },\n {\n featureType: 'road',\n elementType: 'geometry',\n stylers: [{ color: '#ffffff' }],\n },\n ],\n mapTypeControl: false,\n streetViewControl: false,\n fullscreenControl: true,\n })\n\n googleMapRef.current = map\n\n // 创建信息窗口\n infoWindowRef.current = new google.maps.InfoWindow()\n }, [isLoaded, defaultCenter, defaultZoom])\n\n // 添加标记点\n React.useEffect(() => {\n if (!googleMapRef.current || !isLoaded) return\n\n // 清除旧标记\n markersRef.current.forEach((marker) => marker.setMap(null))\n markersRef.current = []\n\n // 过滤并验证有效的位置数据\n const validLocations = locations.filter((location) => {\n const lat = Number(location.lat)\n const lng = Number(location.lng)\n const isValid =\n !isNaN(lat) &&\n !isNaN(lng) &&\n isFinite(lat) &&\n isFinite(lng) &&\n lat >= -90 &&\n lat <= 90 &&\n lng >= -180 &&\n lng <= 180\n if (!isValid) {\n console.warn('Invalid location coordinates:', location)\n }\n return isValid\n })\n\n // 添加新标记\n validLocations.forEach((location) => {\n const lat = Number(location.lat)\n const lng = Number(location.lng)\n\n // 创建自定义SVG图标\n const svgIcon = {\n url: `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(`\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"24\" cy=\"24\" r=\"22\" fill=\"#00000010\"/>\n <circle cx=\"24\" cy=\"24\" r=\"10\" fill=\"#000000\"/>\n <circle cx=\"24\" cy=\"24\" r=\"5\" fill=\"#3ADB67\"/>\n </svg>\n `)}`,\n scaledSize: { width: 48, height: 48 },\n anchor: { x: 24, y: 24 },\n } as google.maps.Icon\n\n const marker = new google.maps.Marker({\n position: { lat, lng },\n map: googleMapRef.current,\n title: location.name,\n icon: svgIcon,\n })\n\n marker.addListener('click', () => {\n setSelectedLocation(location)\n\n // 创建信息窗口内容\n const content = `\n <div style=\"padding: 0 16px 16px 16px; font-weight: 700; font-family: 'MontForAnker'; max-width: 420px;\">\n <h3 style=\"margin: 0 0 16px 0; font-size: 24px; color: #080A0F;\">${location.name}</h3>\n ${\n location.availableTime\n ? `<div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"4\" width=\"14\" height=\"13\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n <path d=\"M3 8H17\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M6 2V4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M14 2V4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n <div>\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32;\">${location.availableTime === pageData?.noAvailableTime ? '' : pageData.available} ${location.availableTime}</p>\n </div>\n </div>`\n : ''\n }\n <div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 10C11.1046 10 12 9.10457 12 8C12 6.89543 11.1046 6 10 6C8.89543 6 8 6.89543 8 8C8 9.10457 8.89543 10 10 10Z\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n <path d=\"M10 18C10 18 16 13 16 8C16 4.68629 13.3137 2 10 2C6.68629 2 4 4.68629 4 8C4 13 10 18 10 18Z\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n </svg>\n <div style=\"flex: 1;\">\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32; word-wrap: break-word;\">${location.address}</p>\n </div>\n </div>\n ${\n location.euifyMakeModel\n ? `<div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 24px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14.4643 7.4929H9.65565M3.16391 18.7132H20.8171C22.0122 18.7132 22.981 17.7563 22.981 16.576L23 13.8348L22.981 6.42431C22.981 5.24396 22.0122 4.28711 20.8171 4.28711H3.16391C1.96882 4.28711 1 5.24396 1 6.42431V16.576C1 17.7563 1.96882 18.7132 3.16391 18.7132Z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5.32812 18.2325V14.4238C5.32812 13.8715 5.77584 13.4238 6.32813 13.4238H17.7925C18.3447 13.4238 18.7925 13.8715 18.7925 14.4238V18.2325\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <div>\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32;\">${location.euifyMakeModel}</p>\n </div>\n </div>`\n : ''\n }\n <button\n id=\"schedule-btn-${location.id}\"\n style=\"\n width: fit-content;\n padding: 12px 28px;\n background: #fff;\n color: #111827;\n border: 2px solid #111827;\n border-radius: 9999px;\n font-weight: 700;\n cursor: pointer;\n font-size: 16px;\n transition: all 0.2s;\n \"\n onmouseover=\"this.style.background='#111827'; this.style.color='#fff';\"\n onmouseout=\"this.style.background='#fff'; this.style.color='#111827';\"\n >\n ${pageData.scheduleNow}\n </button>\n </div>\n `\n\n if (infoWindowRef.current) {\n infoWindowRef.current.setContent(content)\n infoWindowRef.current.open(googleMapRef.current, marker)\n\n // 添加按钮点击事件监听\n google.maps.event.addListenerOnce(\n infoWindowRef.current,\n 'domready',\n () => {\n const btn = document.getElementById(`schedule-btn-${location.id}`)\n if (btn) {\n btn.addEventListener('click', () => {\n if (onSchedule) {\n onSchedule(location.id)\n }\n })\n }\n }\n )\n }\n\n // 移动地图中心到标记位置\n googleMapRef.current?.panTo({ lat: location.lat, lng: location.lng })\n })\n\n markersRef.current.push(marker)\n })\n\n // 自动调整地图视图以显示所有标记\n if (validLocations.length > 0 && googleMapRef.current) {\n const bounds = new google.maps.LatLngBounds()\n validLocations.forEach((location) => {\n const lat = Number(location.lat)\n const lng = Number(location.lng)\n bounds.extend({ lat, lng })\n })\n googleMapRef.current.fitBounds(bounds)\n }\n }, [isLoaded, locations, onSchedule])\n\n // 处理 hover 状态变化\n React.useEffect(() => {\n if (!isLoaded || !googleMapRef.current || !hoveredLocationId) {\n // 如果没有 hover,关闭信息窗口\n if (!hoveredLocationId && infoWindowRef.current) {\n infoWindowRef.current.close()\n }\n return\n }\n\n // 找到对应的位置和标记\n const location = locations.find((loc) => loc.id === hoveredLocationId)\n const markerIndex = locations.findIndex(\n (loc) => loc.id === hoveredLocationId\n )\n const marker = markersRef.current[markerIndex]\n\n if (location && marker) {\n // 创建信息窗口内容\n const content = `\n <div style=\"padding: 0 16px 16px 16px; font-weight: 700; font-family: 'MontForAnker'; max-width: 420px;\">\n <h3 style=\"margin: 0 0 16px 0; font-size: 24px; color: #080A0F;\">${location.name}</h3>\n ${\n location.availableTime\n ? `<div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"4\" width=\"14\" height=\"13\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n <path d=\"M3 8H17\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M6 2V4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M14 2V4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n <div>\n <p style=\"margin: 0;font-size: 16px; color: #2A2C32;\">${location.availableTime === pageData?.noAvailableTime ? '' : pageData.available} ${location.availableTime}</p>\n </div>\n </div>`\n : ''\n }\n <div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 10C11.1046 10 12 9.10457 12 8C12 6.89543 11.1046 6 10 6C8.89543 6 8 6.89543 8 8C8 9.10457 8.89543 10 10 10Z\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n <path d=\"M10 18C10 18 16 13 16 8C16 4.68629 13.3137 2 10 2C6.68629 2 4 4.68629 4 8C4 13 10 18 10 18Z\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n </svg>\n <div style=\"flex: 1;\">\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32; word-wrap: break-word;\">${location.address}</p>\n </div>\n </div>\n ${\n location.euifyMakeModel\n ? `<div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 24px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14.4643 7.4929H9.65565M3.16391 18.7132H20.8171C22.0122 18.7132 22.981 17.7563 22.981 16.576L23 13.8348L22.981 6.42431C22.981 5.24396 22.0122 4.28711 20.8171 4.28711H3.16391C1.96882 4.28711 1 5.24396 1 6.42431V16.576C1 17.7563 1.96882 18.7132 3.16391 18.7132Z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5.32812 18.2325V14.4238C5.32812 13.8715 5.77584 13.4238 6.32813 13.4238H17.7925C18.3447 13.4238 18.7925 13.8715 18.7925 14.4238V18.2325\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <div>\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32;\">${location.euifyMakeModel}</p>\n </div>\n </div>`\n : ''\n }\n <button\n id=\"schedule-btn-hover-${location.id}\"\n style=\"\n width: fit-content;\n padding: 12px 28px;\n background: #fff;\n color: #111827;\n border: 2px solid #111827;\n border-radius: 9999px;\n font-weight: 700;\n cursor: pointer;\n font-size: 16px;\n transition: all 0.2s;\n \"\n onmouseover=\"this.style.background='#111827'; this.style.color='#fff';\"\n onmouseout=\"this.style.background='#fff'; this.style.color='#111827';\"\n >\n ${pageData.scheduleNow}\n </button>\n </div>\n `\n\n if (infoWindowRef.current) {\n infoWindowRef.current.setContent(content)\n infoWindowRef.current.open(googleMapRef.current, marker)\n\n // 添加按钮点击事件监听\n google.maps.event.addListenerOnce(\n infoWindowRef.current,\n 'domready',\n () => {\n const btn = document.getElementById(\n `schedule-btn-hover-${location.id}`\n )\n if (btn) {\n btn.addEventListener('click', () => {\n if (onSchedule) {\n onSchedule(location.id)\n }\n })\n }\n }\n )\n }\n\n // 移动地图中心到标记位置(可选)\n // googleMapRef.current?.panTo({ lat: location.lat, lng: location.lng })\n }\n }, [hoveredLocationId, isLoaded, locations, onSchedule])\n\n // const handleCloseInfo = useCallback(() => {\n // setSelectedLocation(null)\n // if (infoWindowRef.current) {\n // infoWindowRef.current.close()\n // }\n // }, [])\n\n if (!googleMapsApiKey) {\n return (\n <div\n className={cn(\n 'flex items-center overflow-hidden justify-center bg-gray-100 rounded-[16px]',\n className\n )}\n style={{ height: mapHeight }}\n {...props}\n >\n <p className=\"text-gray-600\">{pageData.apiKeyRequired}</p>\n </div>\n )\n }\n\n return (\n <div\n className={cn('relative w-full rounded-[16px] overflow-hidden', className)}\n {...props}\n >\n <div ref={mapRef} style={{ height: mapHeight }} />\n {!isLoaded && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <div className=\"inline-block animate-spin rounded-full h-8 w-8 border-4 border-gray-300 border-t-gray-900 mb-2\"></div>\n <p className=\"text-gray-600\">{pageData.loadingMap}</p>\n </div>\n </div>\n )}\n </div>\n )\n}\n\nStudioMap.displayName = 'StudioMap'\n","// API 基础类型\nexport interface ApiResponse<T = any> {\n code: number\n message: string\n data: T\n request_id: string\n}\n\n// 时段状态\nexport type TimeslotStatus = 'available' | 'full' | 'disabled'\n\n// 门店类型\nexport type DemoRoomType = 'flagship' | 'standard' | 'popup'\n\n// 门店状态\nexport type DemoRoomStatus = 'enabled' | 'disabled'\n\n// 预约状态\nexport type BookingStatus = 'pending' | 'checked_in' | 'completed' | 'cancelled'\n\n// 问题类型\nexport type QuestionType = 'text' | 'email' | 'tel' | 'phone' | 'radio' | 'radio_with_other' | 'checkbox' | 'textarea' | 'select'\n\n// 时段\nexport interface Timeslot {\n id: number\n start_time: string\n end_time: string\n capacity: number\n booked_count: number\n status: TimeslotStatus\n}\n\n// 门店位置信息\nexport interface DemoRoomLocation {\n country: string\n state: string\n city: string\n}\n\n// 门店\nexport interface DemoRoom {\n code: string\n name: string\n description: string\n equipment?: string[]\n address: string\n location?: DemoRoomLocation\n type: DemoRoomType\n capacity: number\n status: DemoRoomStatus\n timezone: string\n images: string[]\n latitude: number\n longitude: number\n questionnaire_id?: number\n timeslots: Timeslot[]\n}\n\n// 问卷选项\nexport interface QuestionOption {\n label: string\n value?: string\n}\n\n// 问卷问题\nexport interface Question {\n id?: string // 固定字段使用 id(如客户信息字段)\n key?: string // 自定义字段使用 key\n type: QuestionType\n label: string\n description?: string\n placeholder?: string\n hint?: string\n options?: QuestionOption[]\n required: boolean\n}\n\n// 问卷\nexport interface Questionnaire {\n id: number\n name: string\n description: string\n questions: Question[]\n}\n\n// 获取门店列表响应\nexport interface GetDemoRoomsResponse {\n demorooms: DemoRoom[]\n}\n\n// 查询时段响应\nexport interface GetTimeslotsResponse {\n timeslots: Timeslot[]\n timezone: string\n}\n\n// 提交预约请求\nexport interface CreateBookingRequest {\n demoroom_code: string\n timeslot_id: number\n questionnaire_id?: number\n questionnaire_response?: Record<string, any>\n customer_name: string\n customer_email: string\n customer_phone_code: string\n customer_phone_number: string\n}\n\n// 提交预约响应\nexport interface CreateBookingResponse {\n booking_id: string\n demoroom_code: string\n booking_date: string\n booking_time: string\n customer_name: string\n customer_email: string\n status: string\n cancel_token?: string\n created_at?: string\n}\n\n// 预约信息\nexport interface Booking {\n booking_id: number\n demoroom_code: string\n demoroom_name?: string // 门店名称(查询预约详情时返回)\n address?: string // 门店地址(查询预约详情时返回)\n equipment?: string[] // 设备列表(查询预约详情时返回)\n latitude?: number // 纬度(查询预约详情时返回)\n longitude?: number // 经度(查询预约详情时返回)\n timezone?: string // 门店时区(查询预约详情时返回)\n booking_date: string\n booking_time?: string // 预约开始时间(创建预约时返回)\n time_slot?: string // 时间段 HH:MM-HH:MM(查询预约详情时返回)\n customer_name: string\n customer_email: string\n phone_code?: string // 电话区号\n phone_number?: string // 电话号码\n status: BookingStatus\n cancel_token: string\n created_at: string\n}\n\n// 获取预约详情响应\nexport interface GetBookingResponse {\n booking: Booking\n}\n\n// 取消预约响应\nexport interface CancelBookingResponse {\n booking: Booking\n}\n\n// API 错误码\nexport enum ApiErrorCode {\n SUCCESS = 0,\n PARAM_ERROR = 1001,\n UNAUTHORIZED = 1002,\n FORBIDDEN = 1003,\n NOT_FOUND = 1004,\n CONFLICT = 1005,\n INTERNAL_ERROR = 1006,\n}\n\n// API 错误\nexport class ApiError extends Error {\n code: number\n request_id?: string\n\n constructor(code: number, message: string, request_id?: string) {\n super(message)\n this.code = code\n this.request_id = request_id\n this.name = 'ApiError'\n }\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport type { DemoRoomApiClient } from './client'\nimport type {\n DemoRoom,\n GetTimeslotsResponse,\n Questionnaire,\n CreateBookingRequest,\n Booking,\n} from './types'\nimport { ApiError } from './types'\n\ninterface UseApiState<T> {\n data: T | null\n loading: boolean\n error: ApiError | null\n}\n\n/**\n * 获取门店列表 Hook\n */\nexport function useDemoRooms(\n client: DemoRoomApiClient,\n params: {\n team_code?: string\n brand_website?: string\n locale?: string\n },\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<DemoRoom[]>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled) return\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getDemoRooms(params)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, params.team_code, params.brand_website, params.locale, enabled])\n\n return state\n}\n\n/**\n * 获取门店详情 Hook\n */\nexport function useDemoRoom(\n client: DemoRoomApiClient,\n code: string,\n locale?: string,\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<DemoRoom>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled || !code) return\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getDemoRoom(code, locale)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, code, locale, enabled])\n\n return state\n}\n\n/**\n * 查询门店时段 Hook\n */\nexport function useTimeslots(\n client: DemoRoomApiClient,\n code: string,\n params: {\n start_date: string\n end_date: string\n timezone?: string\n },\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<GetTimeslotsResponse>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled || !code || !params.start_date || !params.end_date) return\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getTimeslots(code, params)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, code, params.start_date, params.end_date, params.timezone, enabled])\n\n return state\n}\n\n/**\n * 查询门店问卷 Hook\n */\nexport function useQuestionnaire(\n client: DemoRoomApiClient,\n code: string,\n questionnaire_id: number | undefined,\n locale?: string,\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<Questionnaire>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled || !code || !questionnaire_id) {\n setState({\n data: null,\n loading: false,\n error: null,\n })\n return\n }\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getQuestionnaire(code, questionnaire_id, locale)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, code, questionnaire_id, locale, enabled])\n\n return state\n}\n\n/**\n * 提交预约 Hook\n */\nexport function useCreateBooking(client: DemoRoomApiClient) {\n const [state, setState] = useState<UseApiState<Booking>>({\n data: null,\n loading: false,\n error: null,\n })\n\n const createBooking = useCallback(\n async (data: CreateBookingRequest) => {\n setState({ data: null, loading: true, error: null })\n\n try {\n const result = await client.createBooking(data)\n setState({ data: result, loading: false, error: null })\n return result\n } catch (error) {\n const apiError = error instanceof ApiError ? error : new ApiError(1006, 'Unknown error')\n setState({ data: null, loading: false, error: apiError })\n throw apiError\n }\n },\n [client]\n )\n\n return {\n ...state,\n createBooking,\n }\n}\n\n/**\n * 获取预约详情 Hook\n */\nexport function useBooking(\n client: DemoRoomApiClient,\n token: string,\n locale?: string,\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<Booking>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled || !token) return\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getBooking(token, locale)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, token, locale, enabled])\n\n return state\n}\n\n/**\n * 取消预约 Hook\n */\nexport function useCancelBooking(client: DemoRoomApiClient) {\n const [state, setState] = useState<UseApiState<Booking>>({\n data: null,\n loading: false,\n error: null,\n })\n\n const cancelBooking = useCallback(\n async (token: string, locale?: string) => {\n setState({ data: null, loading: true, error: null })\n\n try {\n const result = await client.cancelBooking(token, locale)\n setState({ data: result, loading: false, error: null })\n return result\n } catch (error) {\n const apiError = error instanceof ApiError ? error : new ApiError(1006, 'Unknown error')\n setState({ data: null, loading: false, error: apiError })\n throw apiError\n }\n },\n [client]\n )\n\n return {\n ...state,\n cancelBooking,\n }\n}\n","import React, { useEffect, useRef } from 'react'\nimport { cn } from '@/utils/cn'\n\nexport interface AntdMobileIsolatedProps {\n children: React.ReactNode\n className?: string\n style?: React.CSSProperties\n}\n\n/**\n * 隔离 antd-mobile 全局样式的包装组件\n * 通过创建一个独立的样式上下文来防止 antd-mobile 的全局样式影响应用其他部分\n */\nexport const AntdMobileIsolated: React.FC<AntdMobileIsolatedProps> = ({\n children,\n className,\n style,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!containerRef.current) return\n\n // 重置容器内可能受影响的全局样式\n const container = containerRef.current\n const originalStyles = {\n fontSize: container.style.fontSize,\n fontFamily: container.style.fontFamily,\n lineHeight: container.style.lineHeight,\n color: container.style.color,\n }\n\n // 应用隔离样式\n container.style.fontSize = '14px'\n container.style.fontFamily =\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif'\n container.style.lineHeight = '1.5'\n container.style.color = '#333'\n\n // 清理函数:恢复原始样式\n return () => {\n container.style.fontSize = originalStyles.fontSize\n container.style.fontFamily = originalStyles.fontFamily\n container.style.lineHeight = originalStyles.lineHeight\n container.style.color = originalStyles.color\n }\n }, [])\n\n return (\n <div\n ref={containerRef}\n className={cn('antd-mobile-isolated', className)}\n style={{\n // 使用 all: revert-layer 来隔离样式\n isolation: 'isolate',\n contain: 'layout style',\n ...style,\n }}\n >\n {children}\n </div>\n )\n}\n\nAntdMobileIsolated.displayName = 'AntdMobileIsolated'\n","/**\n * 地址解析工具\n * 将 room.address 解析为层级结构:Country > State > City\n */\n\nexport interface LocationHierarchy {\n country: string\n state: string\n city: string\n}\n\n/**\n * 已知国家列表(包含多词国家名)\n * 优先匹配多词国家名,避免误判\n */\nconst KNOWN_COUNTRIES = [\n 'United States',\n 'United Kingdom',\n 'American Samoa',\n 'United Arab Emirates',\n 'Bosnia and Herzegovina',\n 'Trinidad and Tobago',\n 'Saint Kitts and Nevis',\n 'Antigua and Barbuda',\n 'Saint Vincent and the Grenadines',\n 'São Tomé and Príncipe',\n 'United States Minor Outlying Islands',\n 'British Virgin Islands',\n 'United States Virgin Islands',\n 'Cayman Islands',\n 'Cook Islands',\n 'Falkland Islands',\n 'Faroe Islands',\n 'Marshall Islands',\n 'Northern Mariana Islands',\n 'Pitcairn Islands',\n 'Solomon Islands',\n 'Turks and Caicos Islands',\n 'Wallis and Futuna',\n]\n\n/**\n * 从地址字符串中提取国家、州、城市信息\n * 支持多种地址格式,从后往前解析\n *\n * 示例:\n * - \"building information, street test, city-test2, Ofu‑Olosega, American Samoa\"\n * => country: \"American Samoa\", state: \"Ofu‑Olosega\", city: \"city-test2\"\n * - \"111 8th St, San Francisco, CA 94108, United States\"\n * => country: \"United States\", state: \"CA\", city: \"San Francisco\"\n */\nexport function parseAddress(address: string): LocationHierarchy {\n // 按逗号分割地址\n const parts = address.split(',').map((part) => part.trim()).filter(Boolean)\n\n // 默认值\n let country = 'United States'\n let state = ''\n let city = ''\n\n if (parts.length === 0) {\n return { country, state, city }\n }\n\n // 从后往前解析\n // 最后一部分通常是国家\n const lastPart = parts[parts.length - 1]\n\n // 检查最后一部分是否是已知国家\n const matchedCountry = KNOWN_COUNTRIES.find(\n (knownCountry) => lastPart.toLowerCase() === knownCountry.toLowerCase()\n )\n\n if (matchedCountry) {\n country = matchedCountry\n\n // 倒数第二部分是州/省\n if (parts.length >= 2) {\n state = parts[parts.length - 2].split(' ')[0] // 去掉邮编\n }\n\n // 倒数第三部分是城市\n if (parts.length >= 3) {\n city = parts[parts.length - 3]\n }\n } else {\n // 如果最后一部分不是已知国家,尝试其他解析方式\n if (parts.length >= 2) {\n // 可能的格式: \"Street, City, State\"\n state = parts[parts.length - 1].split(' ')[0]\n city = parts[parts.length - 2]\n } else if (parts.length === 1) {\n // 只有一个部分,可能是城市\n city = parts[0]\n }\n }\n\n return {\n country: country.trim(),\n state: state.trim(),\n city: city.trim(),\n }\n}\n\n/**\n * 地理位置节点(用于树形结构)\n */\nexport interface LocationNode {\n id: string\n name: string\n type: 'country' | 'state' | 'city'\n count: number // 该位置的门店数量\n children?: LocationNode[]\n}\n\n/**\n * 从门店列表构建地理位置树\n */\nexport function buildLocationTree(\n locations: Array<{ address: string; id: string }>\n): LocationNode[] {\n const tree: Map<string, LocationNode> = new Map()\n\n locations.forEach((location) => {\n const { country, state, city } = parseAddress(location.address)\n\n // 构建国家节点\n const countryId = country\n if (!tree.has(countryId)) {\n tree.set(countryId, {\n id: countryId,\n name: country,\n type: 'country',\n count: 0,\n children: [],\n })\n }\n\n const countryNode = tree.get(countryId)!\n countryNode.count++\n\n // 构建州节点\n if (state) {\n const stateId = `${country}/${state}`\n let stateNode = countryNode.children?.find((n) => n.id === stateId)\n\n if (!stateNode) {\n stateNode = {\n id: stateId,\n name: state,\n type: 'state',\n count: 0,\n children: [],\n }\n countryNode.children?.push(stateNode)\n }\n\n stateNode.count++\n\n // 构建城市节点\n if (city) {\n const cityId = `${country}/${state}/${city}`\n let cityNode = stateNode.children?.find((n) => n.id === cityId)\n\n if (!cityNode) {\n cityNode = {\n id: cityId,\n name: city,\n type: 'city',\n count: 0,\n }\n stateNode.children?.push(cityNode)\n }\n\n cityNode.count++\n }\n }\n })\n\n return Array.from(tree.values())\n}\n\n/**\n * 按字母分组位置列表\n */\nexport function groupByAlphabet<T extends { name: string }>(\n items: T[]\n): Array<{ title: string; items: T[] }> {\n const groups: Map<string, T[]> = new Map()\n\n items.forEach((item) => {\n const firstChar = item.name.charAt(0).toUpperCase()\n const key = /[A-Z]/.test(firstChar) ? firstChar : '#'\n\n if (!groups.has(key)) {\n groups.set(key, [])\n }\n groups.get(key)!.push(item)\n })\n\n return Array.from(groups.entries())\n .sort(([a], [b]) => {\n if (a === '#') return 1\n if (b === '#') return -1\n return a.localeCompare(b)\n })\n .map(([title, items]) => ({\n title,\n items: items.sort((a, b) => a.name.localeCompare(b.name)),\n }))\n}\n","/* antd-mobile 样式隔离 - 使用更强的隔离策略 */\n.antdMobileScope {\n /* 重置所有继承样式,但保持布局相关属性 */\n all: unset;\n\n /* 恢复必要的属性 */\n display: block;\n position: absolute;\n box-sizing: border-box;\n\n /* 阻止继承字体样式 */\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #333;\n\n /* 重置 CSS 变量影响 */\n --adm-color-primary: #1677ff;\n --adm-color-text: #333333;\n --adm-font-size-main: 14px;\n}\n\n/* 确保 antd-mobile 组件内部样式正常工作 */\n.antdMobileScope *,\n.antdMobileScope *::before,\n.antdMobileScope *::after {\n box-sizing: border-box;\n}\n\n/* 阻止全局样式继承 */\n.antd-mobile-isolated-container .antdMobileScope :not([class*=\"adm-\"]) {\n all: unset;\n}\n\n/* 保持 antd-mobile 组件样式 */\n.antd-mobile-isolated-container .antdMobileScope [class*=\"adm-\"] {\n all: revert;\n}\n\n/* 隐藏 List.Item 的右侧箭头 */\n.antd-mobile-isolated-container .antdMobileScope .adm-list-item-content-arrow {\n display: none !important;\n}\n","import React, { useState, useMemo } from 'react'\nimport { cn } from '@/utils/cn'\nimport IndexBar from 'antd-mobile/es/components/index-bar'\nimport List from 'antd-mobile/es/components/list'\nimport 'antd-mobile/es/components/index-bar/index-bar.css'\nimport 'antd-mobile/es/components/list/list.css'\nimport { AntdMobileIsolated } from './AntdMobileIsolated'\nimport { groupByAlphabet } from '../utils/addressParser'\nimport styles from './RoomsList.module.css'\n\nexport type LocationLevel = 'country' | 'state' | 'city'\n\nexport interface LocationFilterProps {\n locations: Array<{\n id: string\n country: string\n state: string\n city: string\n }>\n onSelect?: (selection: LocationSelection) => void\n visible?: boolean\n onClose?: () => void\n pageData?: {\n allLocations?: string\n clear?: string\n country?: string\n state?: string\n city?: string\n noStudiosFound?: string\n }\n}\n\nexport interface LocationSelection {\n level: LocationLevel\n country?: string\n state?: string\n city?: string\n}\n\ninterface LocationItem {\n name: string\n code: string\n count: number\n parentCode?: string\n}\n\nexport const LocationFilter: React.FC<LocationFilterProps> = ({\n locations,\n onSelect,\n visible = false,\n onClose,\n pageData = {\n allLocations: 'All Locations',\n clear: 'Clear',\n country: 'Country',\n state: 'State',\n city: 'City',\n noStudiosFound: 'No studios found in this location',\n },\n}) => {\n const [currentLevel, setCurrentLevel] = useState<LocationLevel>('country')\n const [selectedCountry, setSelectedCountry] = useState<string>()\n const [selectedState, setSelectedState] = useState<string>()\n const [searchQuery, setSearchQuery] = useState('')\n\n // 构建位置数据\n const locationData = useMemo(() => {\n const countries = new Map<string, LocationItem>()\n const states = new Map<string, LocationItem>()\n const cities = new Map<string, LocationItem>()\n\n locations.forEach((location) => {\n const { country, state, city } = location\n\n // 统计国家\n if (country) {\n const existing = countries.get(country)\n countries.set(country, {\n name: country,\n code: country,\n count: (existing?.count || 0) + 1,\n })\n }\n\n // 统计州\n if (state) {\n const stateKey = `${country}/${state}`\n const existing = states.get(stateKey)\n states.set(stateKey, {\n name: state,\n code: stateKey,\n count: (existing?.count || 0) + 1,\n parentCode: country,\n })\n }\n\n // 统计城市\n if (city) {\n const cityKey = `${country}/${state}/${city}`\n const existing = cities.get(cityKey)\n cities.set(cityKey, {\n name: city,\n code: cityKey,\n count: (existing?.count || 0) + 1,\n parentCode: `${country}/${state}`,\n })\n }\n })\n\n return {\n countries: Array.from(countries.values()),\n states: Array.from(states.values()),\n cities: Array.from(cities.values()),\n }\n }, [locations])\n\n // 根据当前层级和选择过滤数据\n const filteredItems = useMemo(() => {\n let items: LocationItem[] = []\n\n switch (currentLevel) {\n case 'country':\n items = locationData.countries\n break\n case 'state':\n items = selectedCountry\n ? locationData.states.filter((s) => s.parentCode === selectedCountry)\n : []\n break\n case 'city':\n items = selectedState\n ? locationData.cities.filter((c) => c.parentCode === selectedState)\n : []\n break\n }\n\n // 应用搜索过滤\n if (searchQuery) {\n items = items.filter((item) =>\n item.name.toLowerCase().includes(searchQuery.toLowerCase())\n )\n }\n\n return items\n }, [currentLevel, selectedCountry, selectedState, locationData, searchQuery])\n\n // 按字母分组\n const groupedItems = useMemo(\n () => groupByAlphabet(filteredItems),\n [filteredItems]\n )\n\n // 判断是否显示字母索引条(数据少于10条时不显示)\n const showIndexBar = filteredItems.length >= 10\n\n const handleItemClick = (item: LocationItem) => {\n // 处理\"All\"选项\n if (item.code === '__all__') {\n if (currentLevel === 'country') {\n // 选择所有国家\n onSelect?.({\n level: 'country',\n })\n onClose?.()\n } else if (currentLevel === 'state') {\n // 选择该国家下的所有州\n onSelect?.({\n level: 'state',\n country: selectedCountry,\n })\n onClose?.()\n } else if (currentLevel === 'city') {\n // 选择该州下的所有城市\n const parts = selectedState?.split('/') || []\n onSelect?.({\n level: 'city',\n country: parts[0],\n state: parts[1],\n })\n onClose?.()\n }\n return\n }\n\n // 正常选择逻辑\n if (currentLevel === 'country') {\n setSelectedCountry(item.code)\n setCurrentLevel('state')\n } else if (currentLevel === 'state') {\n setSelectedState(item.code)\n setCurrentLevel('city')\n } else if (currentLevel === 'city') {\n // 选择城市,触发回调\n const parts = item.code.split('/')\n onSelect?.({\n level: 'city',\n country: parts[0],\n state: parts[1],\n city: parts[2],\n })\n onClose?.()\n }\n }\n\n const handleTabClick = (level: LocationLevel) => {\n setCurrentLevel(level)\n if (level === 'country') {\n setSelectedCountry(undefined)\n setSelectedState(undefined)\n } else if (level === 'state') {\n setSelectedState(undefined)\n }\n }\n\n if (!visible) return null\n\n return (\n <div\n style={{ height: '724px' }}\n className={cn(\n 'w-full rounded-b-[12px] absolute z-10 bottom-[-2px] left-0 bg-white border border-[#E4E5E6]',\n styles.antdMobileScope\n )}\n >\n {/* Header with tabs */}\n <div\n style={{ background: '#F8F8F8' }}\n className=\"h-[76px] font-bold text-[14px] flex flex-col\"\n >\n {/* Tabs */}\n <div className=\"flex items-center text-[16px] px-[20px] gap-[16px] py-[24px]\">\n <button\n onClick={() => handleTabClick('country')}\n className={cn(\n 'pb-[4px] transition-colors',\n currentLevel === 'country'\n ? 'text-[#080A0F] border-b-2 border-[#3ADB67]'\n : 'text-[#080A0F]'\n )}\n >\n {pageData.country}\n </button>\n <button\n onClick={() => handleTabClick('state')}\n disabled={!selectedCountry}\n className={cn(\n 'pb-[4px] transition-colors',\n currentLevel === 'state'\n ? 'text-[#080A0F] border-b-2 border-[#3ADB67]'\n : 'text-[#080A0F]',\n !selectedCountry && 'opacity-50 cursor-not-allowed'\n )}\n >\n {pageData.state}\n </button>\n <button\n onClick={() => handleTabClick('city')}\n disabled={!selectedState}\n className={cn(\n 'pb-[4px] transition-colors',\n currentLevel === 'city'\n ? 'text-[#080A0F] border-b-2 border-[#3ADB67]'\n : 'text-[#080A0F]',\n !selectedState && 'opacity-50 cursor-not-allowed'\n )}\n >\n {pageData.city}\n </button>\n </div>\n </div>\n\n {/* Content */}\n <AntdMobileIsolated style={{ height: 'calc(100% - 76px)' }}>\n {showIndexBar ? (\n <div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>\n {/* All option */}\n <List>\n <List.Item\n onClick={() => handleItemClick({ code: '__all__', name: pageData.allLocations || 'All', count: filteredItems.length })}\n key=\"__all__\"\n className='text-[16px] !pl-[24px] font-bold'\n style={{ cursor: 'pointer', borderBottom: '1px solid #E4E5E6' }}\n >\n {pageData.allLocations}\n </List.Item>\n </List>\n <IndexBar style={{ flex: 1 }}>\n {groupedItems.map((group) => {\n const { title, items } = group\n return (\n <IndexBar.Panel index={title} title={title} key={title}>\n <List>\n {items.map((item) => (\n <List.Item\n onClick={() => handleItemClick(item)}\n key={item.code}\n className='text-[16px] !pl-[24px]'\n style={{ cursor: 'pointer' }}\n >\n {item.name}\n </List.Item>\n ))}\n </List>\n </IndexBar.Panel>\n )\n })}\n </IndexBar>\n </div>\n ) : (\n <div style={{ height: '100%', overflow: 'auto' }}>\n <List>\n {/* All option */}\n <List.Item\n onClick={() => handleItemClick({ code: '__all__', name: pageData.allLocations || 'All', count: filteredItems.length })}\n key=\"__all__\"\n className='text-[16px] !pl-[24px] font-bold'\n style={{ cursor: 'pointer', borderBottom: '1px solid #E4E5E6' }}\n >\n {pageData.allLocations}\n </List.Item>\n {filteredItems.map((item) => (\n <List.Item\n onClick={() => handleItemClick(item)}\n key={item.code}\n className='text-[16px] !pl-[24px]'\n style={{ cursor: 'pointer' }}\n >\n {item.name}\n </List.Item>\n ))}\n </List>\n </div>\n )}\n </AntdMobileIsolated>\n </div>\n )\n}\n\nLocationFilter.displayName = 'LocationFilter'\n","import React, { useMemo, useState } from 'react'\nimport { cn } from '@/utils/cn'\nimport { Title } from './Title'\nimport { StudioCard } from './StudioCard'\nimport { StudioLocation, StudioMap } from './StudioMap'\nimport { useDemoRooms } from '@/api/hooks'\nimport type { DemoRoomApiClient } from '@/api/client'\nimport { LocationFilter, type LocationSelection } from './LocationFilter'\nimport type { DemoRoomPageData } from '../types/pageData'\n\nexport interface RoomsListProps extends React.HTMLAttributes<HTMLDivElement> {\n googleMapsApiKey?: string\n layoutClassName?: string\n apiClient: DemoRoomApiClient\n teamCode?: string\n brandWebsite?: string\n /**\n * Callback when user clicks \"Schedule Now\" button\n * @param demoRoomCode - The demo room code\n */\n onSchedule?: (demoRoomCode: string) => void\n /**\n * 页面可配置数据(文案、图标等)\n */\n pageData?: DemoRoomPageData\n}\n\n// 默认 pageData 配置\nconst defaultPageData: Required<DemoRoomPageData> = {\n title: 'Find a Studio Near You',\n loadingText: 'Loading demo rooms...',\n errorTitle: 'Failed to load demo rooms',\n machine: 'eufymake E1',\n locationFilter: {\n allLocations: 'All Locations',\n clear: 'Clear',\n country: 'Country',\n state: 'State',\n city: 'City',\n noStudiosFound: 'No studios found in this location',\n },\n studioCard: {\n scheduleNow: 'Schedule Now',\n available: 'Available',\n away: 'away',\n },\n map: {\n apiKeyRequired: 'Google Maps API Key is required',\n loadingMap: 'Loading map...',\n scheduleNow: 'Schedule Now',\n available: 'Available',\n },\n defaultCountry: 'United States',\n noAvailableTime: 'No available time',\n}\n\n// 默认测试数据 - 美国主要城市的工作室位置\nconst defaultStudioLocations: StudioLocation[] = [\n {\n id: '1',\n name: 'Design District Demo Room',\n address: '111 8th St, San Francisco, CA, United States',\n city: 'San Francisco',\n state: 'CA',\n zipCode: '94108',\n country: 'United States',\n lat: 37.7749,\n lng: -122.4194,\n availableTime: 'Oct 28, 2:00 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n {\n id: '2',\n name: 'Brooklyn Creative Studio',\n address: '456 Broadway, Brooklyn, NY, United States',\n city: 'Brooklyn',\n state: 'NY',\n zipCode: '11211',\n country: 'United States',\n lat: 40.7128,\n lng: -74.006,\n availableTime: 'Oct 29, 3:00 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n {\n id: '3',\n name: 'Austin Innovation Hub',\n address: '789 Tech Blvd, Austin, TX, United States',\n city: 'Austin',\n state: 'TX',\n zipCode: '78701',\n country: 'United States',\n lat: 30.2672,\n lng: -97.7431,\n availableTime: 'Oct 30, 1:00 PM',\n euifyMakeModel: 'euifyMake M5',\n },\n {\n id: '4',\n name: 'Seattle Maker Space',\n address: '321 Pine St, Seattle, WA, United States',\n city: 'Seattle',\n state: 'WA',\n zipCode: '98101',\n country: 'United States',\n lat: 47.6062,\n lng: -122.3321,\n availableTime: 'Oct 31, 11:00 AM',\n euifyMakeModel: 'euifyMake E1',\n },\n {\n id: '5',\n name: 'Chicago Design Center',\n address: '654 Michigan Ave, Chicago, IL, United States',\n city: 'Chicago',\n state: 'IL',\n zipCode: '60611',\n country: 'United States',\n lat: 41.8781,\n lng: -87.6298,\n availableTime: 'Nov 1, 2:30 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n {\n id: '6',\n name: 'Miami Beach Studio',\n address: '987 Ocean Drive, Miami Beach, FL, United States',\n city: 'Miami Beach',\n state: 'FL',\n zipCode: '33139',\n country: 'United States',\n lat: 25.7617,\n lng: -80.1918,\n availableTime: 'Nov 2, 10:00 AM',\n euifyMakeModel: 'euifyMake M5',\n },\n {\n id: '7',\n name: 'Denver Mountain Studio',\n address: '147 16th St, Denver, CO, United States',\n city: 'Denver',\n state: 'CO',\n zipCode: '80202',\n country: 'United States',\n lat: 39.7392,\n lng: -104.9903,\n availableTime: 'Nov 3, 4:00 PM',\n euifyMakeModel: 'euifyMake E1',\n },\n {\n id: '8',\n name: 'Los Angeles Creative Lab',\n address: '258 Main St, Los Angeles, CA, United States',\n city: 'Los Angeles',\n state: 'CA',\n zipCode: '90012',\n country: 'United States',\n lat: 34.0522,\n lng: -118.2437,\n availableTime: 'Nov 4, 1:00 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n]\n\nexport const RoomsList: React.FC<RoomsListProps> = ({\n googleMapsApiKey,\n className,\n apiClient,\n teamCode,\n brandWebsite,\n onSchedule,\n pageData,\n ...props\n}) => {\n // 合并用户提供的 pageData 和默认配置\n const mergedPageData = useMemo(\n () => ({\n ...defaultPageData,\n ...pageData,\n locationFilter: {\n ...defaultPageData.locationFilter,\n ...pageData?.locationFilter,\n },\n studioCard: { ...defaultPageData.studioCard, ...pageData?.studioCard },\n map: { ...defaultPageData.map, ...pageData?.map },\n }),\n [pageData]\n )\n\n // 状态管理\n const [showLocationFilter, setShowLocationFilter] = useState(false)\n const [selectedLocation, setSelectedLocation] = useState<LocationSelection>()\n const [hoveredRoomId, setHoveredRoomId] = useState<string | null>(null)\n\n // 使用 API 获取门店列表\n const {\n data: demoRooms,\n loading,\n error,\n } = useDemoRooms(apiClient, {\n team_code: teamCode,\n brand_website: brandWebsite,\n })\n console.log(demoRooms)\n\n // 将 API 返回的 DemoRoom 类型转换为 StudioLocation 类型\n const studioLocations = useMemo<StudioLocation[]>(() => {\n if (!demoRooms) return defaultStudioLocations\n\n return demoRooms.map((room) => {\n // 获取下一个可用时段\n const nextAvailableTimeslot = room?.timeslots?.find(\n (slot) => slot.status === 'available'\n )\n\n // 使用 API 返回的 location 数据,不再解析 address\n const country = room.location?.country || mergedPageData.defaultCountry\n const state = room.location?.state || ''\n const city = room.location?.city || ''\n\n // 拼接完整地址: room.address 可能只包含街道地址,需要加上 location 信息\n const addressParts = [room.address, city, state, country].filter(Boolean)\n const fullAddress = addressParts.join(', ')\n\n return {\n id: room.code,\n name: room.name,\n address: fullAddress,\n city,\n state,\n zipCode: '',\n country,\n lat: Number(room.latitude) || 0,\n lng: Number(room.longitude) || 0,\n availableTime: nextAvailableTimeslot\n ? `${nextAvailableTimeslot.start_time}`\n : mergedPageData.noAvailableTime,\n euifyMakeModel: room?.equipment?.join(', ') || '',\n }\n })\n }, [demoRooms, mergedPageData.defaultCountry, mergedPageData.noAvailableTime])\n\n // 根据选择的位置过滤门店\n const filteredStudioLocations = useMemo(() => {\n if (!selectedLocation) return studioLocations\n\n return studioLocations.filter((location) => {\n // 直接使用 location 对象中的 country, state, city 字段进行比较\n if (selectedLocation.city) {\n return (\n location.country === selectedLocation.country &&\n location.state === selectedLocation.state &&\n location.city === selectedLocation.city\n )\n }\n\n if (selectedLocation.state) {\n return (\n location.country === selectedLocation.country &&\n location.state === selectedLocation.state\n )\n }\n\n if (selectedLocation.country) {\n return location.country === selectedLocation.country\n }\n\n return true\n })\n }, [studioLocations, selectedLocation])\n\n // 获取当前选择的位置名称\n const getSelectedLocationName = () => {\n if (!selectedLocation) return mergedPageData.locationFilter.allLocations\n if (selectedLocation.city) return selectedLocation.city\n if (selectedLocation.state) return selectedLocation.state\n if (selectedLocation.country) return selectedLocation.country\n return mergedPageData.locationFilter.allLocations\n }\n\n // 处理位置选择\n const handleLocationSelect = (selection: LocationSelection) => {\n setSelectedLocation(selection)\n setShowLocationFilter(false)\n }\n\n // 清除位置过滤\n const handleClearFilter = () => {\n setSelectedLocation(undefined)\n }\n\n return (\n <div className={className} {...props}>\n {/* Section Title */}\n <Title title={mergedPageData.title}></Title>\n\n {/* Loading State */}\n {loading && (\n <div className=\"flex items-center justify-center h-[794px]\">\n <div className=\"text-center\">\n <div className=\"text-lg font-medium\">\n {mergedPageData.loadingText}\n </div>\n </div>\n </div>\n )}\n\n {/* Error State */}\n {error && (\n <div className=\"flex items-center justify-center h-[794px]\">\n <div className=\"text-center\" style={{ color: '#FF4D4D' }}>\n <div className=\"text-lg font-medium\">\n {mergedPageData.errorTitle}\n </div>\n <div className=\"text-sm mt-2\">{error.message}</div>\n </div>\n </div>\n )}\n\n {/* Content */}\n {!loading && !error && (\n <div className=\"flex h-[794px] gap-4\">\n <div\n className=\"flex-none relative w-[420px] l:!w-full\"\n style={{ height: '794px' }}\n >\n {/* Filter Header */}\n <div className={cn(\n \"mb-4 bg-white border border-[#E4E5E6] px-[20px] py-[16px]\",\n showLocationFilter ? \"rounded-t-[12px] rounded-b-none\" : \"rounded-[12px]\"\n )}>\n {/* First Row */}\n <div className=\"h-[40px] font-bold text-[16px] l:text-[14px] gap-10 l:gap-4 flex items-center\">\n <button\n className=\"flex cursor-pointer items-center hover:text-[#3ADB67] transition-colors\"\n onClick={() => setShowLocationFilter(!showLocationFilter)}\n >\n <span className=\"mr-1\">{getSelectedLocationName()}</span>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={cn(\n \"transition-transform duration-300\",\n showLocationFilter && \"rotate-180\"\n )}\n >\n <path\n d=\"M16.7661 9.23364C17.078 9.5455 17.0779 10.0516 16.7661 10.3635L12.5991 14.5305C12.2874 14.842 11.782 14.8418 11.4702 14.5305L7.30322 10.3635C6.99135 10.0516 6.99135 9.54552 7.30322 9.23364C7.615 8.9221 8.1203 8.92219 8.43213 9.23364L12.0347 12.8362L15.6362 9.23364C15.9481 8.92183 16.4543 8.92181 16.7661 9.23364Z\"\n fill=\"currentColor\"\n />\n </svg>\n </button>\n {selectedLocation && false && (\n <button\n onClick={handleClearFilter}\n className=\"ml-auto text-[14px] text-[#2E8B57] hover:underline\"\n >\n {mergedPageData.locationFilter.clear}\n </button>\n )}\n <div className=\"flex text-[#767880] cursor-not-allowed\">\n {mergedPageData.machine}\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n >\n <path\n d=\"M16.7661 9.23364C17.078 9.5455 17.0779 10.0516 16.7661 10.3635L12.5991 14.5305C12.2874 14.842 11.782 14.8418 11.4702 14.5305L7.30322 10.3635C6.99135 10.0516 6.99135 9.54552 7.30322 9.23364C7.615 8.9221 8.1203 8.92219 8.43213 9.23364L12.0347 12.8362L15.6362 9.23364C15.9481 8.92183 16.4543 8.92181 16.7661 9.23364Z\"\n fill=\"currentColor\"\n />\n </svg>\n </div>\n </div>\n </div>\n\n {/* Room List */}\n <div\n style={{ maxHeight: '706px', overflow: 'auto' }}\n className=\"rounded-[12px] bg-white border h-[706px] border-[#E4E5E6]\"\n >\n {filteredStudioLocations.length === 0 ? (\n <div className=\"flex items-center justify-center h-[200px] text-[#767880]\">\n {mergedPageData.locationFilter.noStudiosFound}\n </div>\n ) : (\n filteredStudioLocations.map((item) => {\n return (\n <StudioCard\n key={item.id}\n code={item.id}\n name={item?.name}\n availableTime={item?.availableTime || ''}\n address={item?.address}\n city={item?.city}\n state={item?.state}\n zipCode={item?.zipCode}\n euifyMakeModel={item?.euifyMakeModel || ''}\n onSchedule={onSchedule}\n onMouseEnter={() => setHoveredRoomId(item.id)}\n pageData={{\n ...mergedPageData.studioCard,\n noAvailableTime: mergedPageData?.noAvailableTime,\n }}\n />\n )\n })\n )}\n </div>\n\n {/* Location Filter Overlay */}\n <LocationFilter\n locations={studioLocations.map((loc) => ({\n id: loc.id,\n country: loc.country,\n state: loc.state,\n city: loc.city,\n }))}\n visible={showLocationFilter}\n onSelect={handleLocationSelect}\n onClose={() => setShowLocationFilter(false)}\n pageData={mergedPageData.locationFilter}\n />\n </div>\n {googleMapsApiKey && (\n <div className={cn('flex-1 l:!hidden')}>\n <StudioMap\n googleMapsApiKey={googleMapsApiKey}\n locations={filteredStudioLocations}\n hoveredLocationId={hoveredRoomId}\n onSchedule={onSchedule}\n mapHeight=\"794px\"\n pageData={{\n ...mergedPageData.map,\n noAvailableTime: pageData?.noAvailableTime,\n }}\n />\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n\nRoomsList.displayName = 'RoomsList'\n","import type {\n ApiResponse,\n DemoRoom,\n GetDemoRoomsResponse,\n GetTimeslotsResponse,\n Questionnaire,\n CreateBookingRequest,\n Booking,\n GetBookingResponse,\n CancelBookingResponse,\n} from './types'\nimport { ApiError, ApiErrorCode } from './types'\n\nexport interface DemoRoomApiConfig {\n baseUrl: string\n apiKey: string\n locale?: string\n timeout?: number\n}\n\nexport class DemoRoomApiClient {\n private config: DemoRoomApiConfig\n\n constructor(config: DemoRoomApiConfig) {\n this.config = {\n timeout: 30000,\n ...config,\n }\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.config.baseUrl}${endpoint}`\n\n const headers: Record<string, string> = {\n 'X-API-Key': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...(options.headers as Record<string, string>),\n }\n\n // 添加语言偏好\n if (this.config.locale) {\n headers['Accept-Language'] = this.config.locale\n }\n\n try {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout)\n\n const response = await fetch(url, {\n ...options,\n headers,\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n const data: ApiResponse<T> = await response.json()\n\n if (data.code !== ApiErrorCode.SUCCESS) {\n throw new ApiError(data.code, data.message, data.request_id)\n }\n\n return data.data\n } catch (error) {\n if (error instanceof ApiError) {\n throw error\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new ApiError(ApiErrorCode.INTERNAL_ERROR, 'Request timeout')\n }\n throw new ApiError(ApiErrorCode.INTERNAL_ERROR, error.message)\n }\n\n throw new ApiError(ApiErrorCode.INTERNAL_ERROR, 'Unknown error')\n }\n }\n\n /**\n * 获取门店列表\n * @param params.team_code 团队编码\n * @param params.brand_website 品牌站点\n * @param params.locale 语言偏好(可选)\n */\n async getDemoRooms(params: {\n team_code?: string\n brand_website?: string\n locale?: string\n }): Promise<DemoRoom[]> {\n const searchParams = new URLSearchParams()\n\n if (params.team_code) {\n searchParams.append('team_code', params.team_code)\n }\n\n if (params.brand_website) {\n searchParams.append('brand_website', params.brand_website)\n }\n\n if (params.locale) {\n searchParams.append('locale', params.locale)\n }\n\n const response = await this.request<GetDemoRoomsResponse>(\n `/api/v1/store/demorooms?${searchParams.toString()}`\n )\n\n return response.demorooms\n }\n\n /**\n * 获取门店详情\n * @param code 门店编码\n * @param locale 语言偏好(可选)\n */\n async getDemoRoom(code: string, locale?: string): Promise<DemoRoom> {\n const searchParams = new URLSearchParams()\n if (locale) {\n searchParams.append('locale', locale)\n }\n\n const query = searchParams.toString()\n return this.request<DemoRoom>(\n `/api/v1/store/demorooms/${code}${query ? `?${query}` : ''}`\n )\n }\n\n /**\n * 查询门店时段\n * @param code 门店编码\n * @param params.start_date 开始日期 (YYYY-MM-DD)\n * @param params.end_date 结束日期 (YYYY-MM-DD)\n * @param params.timezone 时区(可选)\n */\n async getTimeslots(\n code: string,\n params: {\n start_date: string\n end_date: string\n timezone?: string\n }\n ): Promise<GetTimeslotsResponse> {\n const searchParams = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n })\n\n if (params.timezone) {\n searchParams.append('timezone', params.timezone)\n }\n\n return this.request<GetTimeslotsResponse>(\n `/api/v1/store/demorooms/${code}/timeslots?${searchParams.toString()}`\n )\n }\n\n /**\n * 查询门店问卷\n * @param code 门店编码\n * @param questionnaire_id 问卷ID\n * @param locale 语言偏好(可选)\n */\n async getQuestionnaire(\n code: string,\n questionnaire_id: number,\n locale?: string\n ): Promise<Questionnaire> {\n const searchParams = new URLSearchParams()\n if (locale) {\n searchParams.append('locale', locale)\n }\n\n const query = searchParams.toString()\n return this.request<Questionnaire>(\n `/api/v1/store/demorooms/${code}/questionnaires/${questionnaire_id}${query ? `?${query}` : ''}`\n )\n }\n\n /**\n * 提交预约\n * @param data 预约数据\n */\n async createBooking(data: CreateBookingRequest): Promise<Booking> {\n return this.request<Booking>('/api/v1/store/bookings', {\n method: 'POST',\n body: JSON.stringify(data),\n })\n }\n\n /**\n * 根据 token 获取预约详情(支持多语言)\n * @param token 预约凭证 (cancel_token)\n * @param locale 语言偏好(可选,也可以通过 Accept-Language Header)\n */\n async getBooking(token: string, locale?: string): Promise<Booking> {\n const headers: Record<string, string> = {}\n\n // 如果指定了 locale,通过 Accept-Language Header 传递\n if (locale) {\n headers['Accept-Language'] = locale\n }\n\n const response = await this.request<GetBookingResponse>(\n `/api/v1/store/bookings/${token}`,\n { headers }\n )\n return response.booking\n }\n\n /**\n * 取消预约(支持多语言邮件通知)\n * @param token 预约凭证 (cancel_token)\n * @param locale 语言偏好(可选,用于邮件通知)\n */\n async cancelBooking(token: string, locale?: string): Promise<Booking> {\n const headers: Record<string, string> = {}\n\n // 如果指定了 locale,通过 Accept-Language Header 传递\n if (locale) {\n headers['Accept-Language'] = locale\n }\n\n const response = await this.request<CancelBookingResponse>(\n `/api/v1/store/bookings/${token}/cancel`,\n {\n method: 'POST',\n headers,\n }\n )\n return response.booking\n }\n}\n\n// 创建默认客户端实例的辅助函数\nexport function createDemoRoomApi(config: DemoRoomApiConfig): DemoRoomApiClient {\n return new DemoRoomApiClient(config)\n}\n","import React, { useMemo } from 'react'\nimport { cn } from '@/utils/cn'\nimport { RoomsList } from './components/RoomsList'\nimport { createDemoRoomApi } from '@/api'\nimport type { DemoRoomApiClient } from '@/api'\nimport type { DemoRoomPageData } from './types/pageData'\n\nexport interface DemoRoomProps extends React.HTMLAttributes<HTMLDivElement> {\n layoutClassName?: string\n /**\n * 谷歌地图 API Key\n */\n googleMapsApiKey?: string\n /**\n * API 配置\n */\n apiConfig: {\n baseUrl: string\n apiKey: string\n locale?: string\n }\n /**\n * 团队编码或品牌站点(二选一)\n */\n teamCode?: string\n brandWebsite?: string\n /**\n * Callback when user clicks \"Schedule Now\" button\n * @param demoRoomCode - The demo room code\n */\n onSchedule?: (demoRoomCode: string) => void\n /**\n * 页面可配置数据(文案、图标等)\n */\n pageData?: DemoRoomPageData\n}\n\nexport const DemoRoom: React.FC<DemoRoomProps> = ({\n className,\n layoutClassName,\n googleMapsApiKey,\n apiConfig,\n teamCode,\n brandWebsite,\n onSchedule,\n pageData,\n ...props\n}) => {\n // 创建 API 客户端实例\n const apiClient = useMemo<DemoRoomApiClient>(\n () => createDemoRoomApi(apiConfig),\n [apiConfig]\n )\n\n return (\n <div className={cn(className)} {...props}>\n <RoomsList\n className={layoutClassName}\n googleMapsApiKey={googleMapsApiKey}\n apiClient={apiClient}\n teamCode={teamCode}\n brandWebsite={brandWebsite}\n onSchedule={onSchedule}\n pageData={pageData}\n ></RoomsList>\n </div>\n )\n}\n\nDemoRoom.displayName = 'DemoRoom'\n"]}
1
+ {"version":3,"sources":["../src/utils/cn.ts","../src/components/DemoRoom/components/Title.tsx","../src/components/DemoRoom/components/StudioCard.tsx","../src/components/DemoRoom/components/StudioMap.tsx","../src/api/types.ts","../src/api/hooks.ts","../src/components/DemoRoom/components/AntdMobileIsolated.tsx","../src/components/DemoRoom/utils/addressParser.ts","../src/components/DemoRoom/components/RoomsList.module.css","../src/components/DemoRoom/components/LocationFilter.tsx","../src/components/DemoRoom/components/RoomsList.tsx","../src/api/client.ts","../src/components/DemoRoom/DemoRoom.tsx"],"names":["twMerge","clsx","jsx","React","jsxs","useState","useEffect","useRef","items","useMemo","List","IndexBar"],"mappings":"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","file":"demo-room.js","sourcesContent":["import { clsx, type ClassValue } from 'clsx'\nimport { twMerge } from 'tailwind-merge'\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","import React from 'react'\nimport { cn } from '@/utils/cn'\n\nexport interface TitleProps extends React.HTMLAttributes<HTMLDivElement> {\n title?: string\n subTitle?: string\n}\n\nexport const Title: React.FC<TitleProps> = ({\n title = '',\n ...props\n}) => {\n return (\n <div className={cn('w-full')} {...props}>\n {/* Section Title */}\n <h2 className=\"text-[32px] min-l:text-[48px] font-bold mb-12 text-[#080A0F]\">\n {title}\n </h2>\n </div>\n )\n}\n\nTitle.displayName = 'Title'\n","import React from 'react'\nimport { cn } from '@/utils/cn'\n\nexport interface StudioCardProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * Demo room code (unique identifier)\n */\n code: string\n /**\n * Studio name\n */\n name: string\n /**\n * Available time\n */\n availableTime: string\n /**\n * Full address\n */\n address: string\n city: string\n state: string\n zipCode: string\n country?: string\n /**\n * Available euifyMake models\n */\n euifyMakeModel: string\n /**\n * Distance from user location (optional)\n */\n distance?: number\n /**\n * Callback when \"Schedule Now\" is clicked, receives demo room code\n */\n onSchedule?: (code: string) => void\n /**\n * 可配置的文案数据\n */\n pageData?: {\n scheduleNow?: string\n available?: string\n away?: string\n noAvailableTime?: string\n }\n}\n\nexport const StudioCard: React.FC<StudioCardProps> = ({\n code,\n name,\n availableTime,\n address,\n euifyMakeModel,\n distance,\n onSchedule,\n pageData = {\n scheduleNow: 'Schedule Now',\n available: 'Available',\n away: 'away',\n },\n className,\n style,\n ...props\n}) => {\n const [isHovered, setIsHovered] = React.useState(false)\n\n const handleScheduleClick = () => {\n onSchedule?.(code)\n }\n\n // 格式化距离显示\n const formatDistance = (dist: number) => {\n if (dist < 1) {\n return `${Math.round(dist * 1000)} m`\n }\n return `${dist.toFixed(1)} km`\n }\n\n return (\n <div\n {...props}\n className={cn(\n 'p-6 cursor-pointer transition-colors duration-200 border-b border-[#E4E5E6] last:border-b-0',\n className\n )}\n style={{\n backgroundColor: isHovered ? '#f3f4f6' : 'transparent',\n ...style,\n }}\n onMouseEnter={(e) => {\n setIsHovered(true)\n props.onMouseEnter?.(e)\n }}\n onMouseLeave={(e) => {\n setIsHovered(false)\n props.onMouseLeave?.(e)\n }}\n >\n {/* Studio Name and Distance */}\n <div className=\"flex items-start justify-between mb-4\">\n <h3 className=\"text-[24px] l:text-[20px] font-bold text-[#080A0F]\">\n {name}\n </h3>\n {distance !== undefined && (\n <span className=\"text-[16px] l:text-[14px] font-medium text-[#2E8B57] bg-[#E8F5E9] px-3 py-1 rounded-full whitespace-nowrap ml-2\">\n {formatDistance(distance)} {pageData.away}\n </span>\n )}\n </div>\n\n {/* Available Time */}\n {availableTime && (\n <div className=\"flex items-start gap-3 mb-3\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"flex-shrink-0 mt-0.5\"\n >\n <rect\n x=\"3\"\n y=\"4\"\n width=\"14\"\n height=\"13\"\n rx=\"2\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M3 8H17\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M6 2V4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n <path\n d=\"M14 2V4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n <div>\n <p className=\"text-[16px] l:text-[12px] text-[#2A2C32]\">\n {availableTime === pageData.noAvailableTime\n ? ''\n : pageData.available}{' '}\n {availableTime}\n </p>\n </div>\n </div>\n )}\n\n {/* Address */}\n <div className=\"flex items-start gap-3 mb-3\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"flex-shrink-0 mt-0.5\"\n >\n <path\n d=\"M10 10C11.1046 10 12 9.10457 12 8C12 6.89543 11.1046 6 10 6C8.89543 6 8 6.89543 8 8C8 9.10457 8.89543 10 10 10Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n <path\n d=\"M10 18C10 18 16 13 16 8C16 4.68629 13.3137 2 10 2C6.68629 2 4 4.68629 4 8C4 13 10 18 10 18Z\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n />\n </svg>\n <div className=\"flex-1\">\n <p className=\"text-[16px] l:text-[14px] text-[#2A2C32] break-words\">\n {address}\n </p>\n </div>\n </div>\n\n {/* euifyMake Models */}\n <div className=\"flex items-start gap-3 mb-6\">\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"flex-shrink-0 mt-0.5\"\n >\n <path\n d=\"M14.4643 7.4929H9.65565M3.16391 18.7132H20.8171C22.0122 18.7132 22.981 17.7563 22.981 16.576L23 13.8348L22.981 6.42431C22.981 5.24396 22.0122 4.28711 20.8171 4.28711H3.16391C1.96882 4.28711 1 5.24396 1 6.42431V16.576C1 17.7563 1.96882 18.7132 3.16391 18.7132Z\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M5.32812 18.2325V14.4238C5.32812 13.8715 5.77584 13.4238 6.32813 13.4238H17.7925C18.3447 13.4238 18.7925 13.8715 18.7925 14.4238V18.2325\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n <div>\n <p className=\"text-[16px] l:text-[14px] text-[#2A2C32]\">\n {euifyMakeModel}\n </p>\n </div>\n </div>\n\n {/* Schedule Button */}\n <button\n onClick={handleScheduleClick}\n className={cn(\n 'w-fit px-[28px] l:px-[20px] l:py-[8px] py-3 rounded-full',\n 'bg-white text-gray-900 border-2 border-gray-900',\n 'font-bold text-[16px] l:text-[14px]',\n 'hover:bg-gray-900 hover:text-white',\n 'transition-all duration-200'\n )}\n >\n {pageData.scheduleNow}\n </button>\n </div>\n )\n}\n\nStudioCard.displayName = 'StudioCard'\n","import React, { useState } from 'react'\nimport { cn } from '@/utils/cn'\n\nexport interface StudioLocation {\n id: string\n name: string\n address: string\n city: string\n state: string\n zipCode: string\n country: string\n lat: number\n lng: number\n availableTime?: string\n euifyMakeModel?: string\n distance?: number\n}\n\nexport interface StudioMapProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * 谷歌地图 API Key\n */\n googleMapsApiKey: string\n /**\n * 工作室位置数据\n */\n locations?: StudioLocation[]\n /**\n * 当前 hover 的位置 ID\n */\n hoveredLocationId?: string | null\n /**\n * 默认中心点\n */\n defaultCenter?: { lat: number; lng: number }\n /**\n * 默认缩放级别\n */\n defaultZoom?: number\n /**\n * 地图高度\n */\n mapHeight?: string\n /**\n * 点击 Schedule Now 的回调\n */\n onSchedule?: (demoRoomCode: string) => void\n /**\n * 可配置的文案数据\n */\n pageData?: {\n apiKeyRequired?: string\n loadingMap?: string\n scheduleNow?: string\n available?: string\n noAvailableTime?: string\n }\n}\n\nconst defaultLocations: StudioLocation[] = [\n {\n id: '1',\n name: 'Design District Demo Room',\n address: '111 8th St',\n city: 'San Francisco',\n state: 'CA',\n zipCode: '94108',\n country: 'United States',\n lat: 37.7749,\n lng: -122.4194,\n availableTime: 'Oct 28, 2:00 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n]\n\nexport const StudioMap: React.FC<StudioMapProps> = ({\n googleMapsApiKey,\n locations = defaultLocations,\n hoveredLocationId,\n defaultCenter = { lat: 39.8283, lng: -98.5795 }, // US center\n defaultZoom = 4,\n mapHeight = '600px',\n onSchedule,\n pageData = {\n apiKeyRequired: 'Google Maps API Key is required',\n loadingMap: 'Loading map...',\n scheduleNow: 'Schedule Now',\n available: 'Available',\n },\n className,\n ...props\n}) => {\n const [_selectedLocation, setSelectedLocation] =\n useState<StudioLocation | null>(null)\n const [isLoaded, setIsLoaded] = useState(false)\n const mapRef = React.useRef<HTMLDivElement>(null)\n const googleMapRef = React.useRef<google.maps.Map | null>(null)\n const markersRef = React.useRef<google.maps.Marker[]>([])\n const infoWindowRef = React.useRef<google.maps.InfoWindow | null>(null)\n\n // 加载谷歌地图脚本\n React.useEffect(() => {\n if (!googleMapsApiKey) {\n console.error('Google Maps API Key is required')\n return\n }\n\n // 检查脚本是否已加载\n if (window.google && window.google.maps) {\n setIsLoaded(true)\n return\n }\n\n const script = document.createElement('script')\n script.src = `https://maps.googleapis.com/maps/api/js?key=${googleMapsApiKey}&libraries=places`\n script.async = true\n script.defer = true\n script.onload = () => setIsLoaded(true)\n script.onerror = () => console.error('Failed to load Google Maps script')\n document.head.appendChild(script)\n\n return () => {\n // 清理脚本(可选)\n if (script.parentNode) {\n script.parentNode.removeChild(script)\n }\n }\n }, [googleMapsApiKey])\n\n // 初始化地图\n React.useEffect(() => {\n if (!isLoaded || !mapRef.current || googleMapRef.current) return\n\n // 创建地图\n const map = new google.maps.Map(mapRef.current, {\n center: defaultCenter,\n zoom: defaultZoom,\n styles: [\n {\n featureType: 'all',\n elementType: 'geometry',\n stylers: [{ color: '#E0F2F1' }],\n },\n {\n featureType: 'water',\n elementType: 'geometry',\n stylers: [{ color: '#B2EBF2' }],\n },\n {\n featureType: 'road',\n elementType: 'geometry',\n stylers: [{ color: '#ffffff' }],\n },\n ],\n mapTypeControl: false,\n streetViewControl: false,\n fullscreenControl: true,\n })\n\n googleMapRef.current = map\n\n // 创建信息窗口\n infoWindowRef.current = new google.maps.InfoWindow()\n }, [isLoaded, defaultCenter, defaultZoom])\n\n // 添加标记点\n React.useEffect(() => {\n if (!googleMapRef.current || !isLoaded) return\n\n // 清除旧标记\n markersRef.current.forEach((marker) => marker.setMap(null))\n markersRef.current = []\n\n // 过滤并验证有效的位置数据\n const validLocations = locations.filter((location) => {\n const lat = Number(location.lat)\n const lng = Number(location.lng)\n const isValid =\n !isNaN(lat) &&\n !isNaN(lng) &&\n isFinite(lat) &&\n isFinite(lng) &&\n lat >= -90 &&\n lat <= 90 &&\n lng >= -180 &&\n lng <= 180\n if (!isValid) {\n console.warn('Invalid location coordinates:', location)\n }\n return isValid\n })\n\n // 添加新标记\n validLocations.forEach((location) => {\n const lat = Number(location.lat)\n const lng = Number(location.lng)\n\n // 创建自定义SVG图标\n const svgIcon = {\n url: `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(`\n <svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"24\" cy=\"24\" r=\"22\" fill=\"#00000010\"/>\n <circle cx=\"24\" cy=\"24\" r=\"10\" fill=\"#000000\"/>\n <circle cx=\"24\" cy=\"24\" r=\"5\" fill=\"#3ADB67\"/>\n </svg>\n `)}`,\n scaledSize: { width: 48, height: 48 },\n anchor: { x: 24, y: 24 },\n } as google.maps.Icon\n\n const marker = new google.maps.Marker({\n position: { lat, lng },\n map: googleMapRef.current,\n title: location.name,\n icon: svgIcon,\n })\n\n marker.addListener('click', () => {\n setSelectedLocation(location)\n\n // 创建信息窗口内容\n const content = `\n <div style=\"padding: 0 16px 16px 16px; font-weight: 700; font-family: 'MontForAnker'; max-width: 420px;\">\n <h3 style=\"margin: 0 0 16px 0; font-size: 24px; color: #080A0F;\">${location.name}</h3>\n ${\n location.availableTime\n ? `<div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"4\" width=\"14\" height=\"13\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n <path d=\"M3 8H17\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M6 2V4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M14 2V4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n <div>\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32;\">${location.availableTime === pageData?.noAvailableTime ? '' : pageData.available} ${location.availableTime}</p>\n </div>\n </div>`\n : ''\n }\n <div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 10C11.1046 10 12 9.10457 12 8C12 6.89543 11.1046 6 10 6C8.89543 6 8 6.89543 8 8C8 9.10457 8.89543 10 10 10Z\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n <path d=\"M10 18C10 18 16 13 16 8C16 4.68629 13.3137 2 10 2C6.68629 2 4 4.68629 4 8C4 13 10 18 10 18Z\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n </svg>\n <div style=\"flex: 1;\">\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32; word-wrap: break-word;\">${location.address}</p>\n </div>\n </div>\n ${\n location.euifyMakeModel\n ? `<div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 24px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14.4643 7.4929H9.65565M3.16391 18.7132H20.8171C22.0122 18.7132 22.981 17.7563 22.981 16.576L23 13.8348L22.981 6.42431C22.981 5.24396 22.0122 4.28711 20.8171 4.28711H3.16391C1.96882 4.28711 1 5.24396 1 6.42431V16.576C1 17.7563 1.96882 18.7132 3.16391 18.7132Z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5.32812 18.2325V14.4238C5.32812 13.8715 5.77584 13.4238 6.32813 13.4238H17.7925C18.3447 13.4238 18.7925 13.8715 18.7925 14.4238V18.2325\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <div>\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32;\">${location.euifyMakeModel}</p>\n </div>\n </div>`\n : ''\n }\n <button\n id=\"schedule-btn-${location.id}\"\n style=\"\n width: fit-content;\n padding: 12px 28px;\n background: #fff;\n color: #111827;\n border: 2px solid #111827;\n border-radius: 9999px;\n font-weight: 700;\n cursor: pointer;\n font-size: 16px;\n transition: all 0.2s;\n \"\n onmouseover=\"this.style.background='#111827'; this.style.color='#fff';\"\n onmouseout=\"this.style.background='#fff'; this.style.color='#111827';\"\n >\n ${pageData.scheduleNow}\n </button>\n </div>\n `\n\n if (infoWindowRef.current) {\n infoWindowRef.current.setContent(content)\n infoWindowRef.current.open(googleMapRef.current, marker)\n\n // 添加按钮点击事件监听\n google.maps.event.addListenerOnce(\n infoWindowRef.current,\n 'domready',\n () => {\n const btn = document.getElementById(`schedule-btn-${location.id}`)\n if (btn) {\n btn.addEventListener('click', () => {\n if (onSchedule) {\n onSchedule(location.id)\n }\n })\n }\n }\n )\n }\n\n // 移动地图中心到标记位置\n googleMapRef.current?.panTo({ lat: location.lat, lng: location.lng })\n })\n\n markersRef.current.push(marker)\n })\n\n // 自动调整地图视图以显示所有标记\n if (validLocations.length > 0 && googleMapRef.current) {\n const bounds = new google.maps.LatLngBounds()\n validLocations.forEach((location) => {\n const lat = Number(location.lat)\n const lng = Number(location.lng)\n bounds.extend({ lat, lng })\n })\n googleMapRef.current.fitBounds(bounds)\n }\n }, [isLoaded, locations, onSchedule])\n\n // 处理 hover 状态变化\n React.useEffect(() => {\n if (!isLoaded || !googleMapRef.current || !hoveredLocationId) {\n // 如果没有 hover,关闭信息窗口\n if (!hoveredLocationId && infoWindowRef.current) {\n infoWindowRef.current.close()\n }\n return\n }\n\n // 找到对应的位置和标记\n const location = locations.find((loc) => loc.id === hoveredLocationId)\n const markerIndex = locations.findIndex(\n (loc) => loc.id === hoveredLocationId\n )\n const marker = markersRef.current[markerIndex]\n\n if (location && marker) {\n // 创建信息窗口内容\n const content = `\n <div style=\"padding: 0 16px 16px 16px; font-weight: 700; font-family: 'MontForAnker'; max-width: 420px;\">\n <h3 style=\"margin: 0 0 16px 0; font-size: 24px; color: #080A0F;\">${location.name}</h3>\n ${\n location.availableTime\n ? `<div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect x=\"3\" y=\"4\" width=\"14\" height=\"13\" rx=\"2\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n <path d=\"M3 8H17\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M6 2V4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n <path d=\"M14 2V4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"/>\n </svg>\n <div>\n <p style=\"margin: 0;font-size: 16px; color: #2A2C32;\">${location.availableTime === pageData?.noAvailableTime ? '' : pageData.available} ${location.availableTime}</p>\n </div>\n </div>`\n : ''\n }\n <div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 12px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M10 10C11.1046 10 12 9.10457 12 8C12 6.89543 11.1046 6 10 6C8.89543 6 8 6.89543 8 8C8 9.10457 8.89543 10 10 10Z\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n <path d=\"M10 18C10 18 16 13 16 8C16 4.68629 13.3137 2 10 2C6.68629 2 4 4.68629 4 8C4 13 10 18 10 18Z\" stroke=\"currentColor\" stroke-width=\"1.5\"/>\n </svg>\n <div style=\"flex: 1;\">\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32; word-wrap: break-word;\">${location.address}</p>\n </div>\n </div>\n ${\n location.euifyMakeModel\n ? `<div style=\"display: flex; align-items: flex-start; gap: 12px; margin-bottom: 24px;\">\n <svg style=\"flex-shrink: 0; margin-top: 2px;\" width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M14.4643 7.4929H9.65565M3.16391 18.7132H20.8171C22.0122 18.7132 22.981 17.7563 22.981 16.576L23 13.8348L22.981 6.42431C22.981 5.24396 22.0122 4.28711 20.8171 4.28711H3.16391C1.96882 4.28711 1 5.24396 1 6.42431V16.576C1 17.7563 1.96882 18.7132 3.16391 18.7132Z\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M5.32812 18.2325V14.4238C5.32812 13.8715 5.77584 13.4238 6.32813 13.4238H17.7925C18.3447 13.4238 18.7925 13.8715 18.7925 14.4238V18.2325\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n <div>\n <p style=\"margin: 0; font-size: 16px; color: #2A2C32;\">${location.euifyMakeModel}</p>\n </div>\n </div>`\n : ''\n }\n <button\n id=\"schedule-btn-hover-${location.id}\"\n style=\"\n width: fit-content;\n padding: 12px 28px;\n background: #fff;\n color: #111827;\n border: 2px solid #111827;\n border-radius: 9999px;\n font-weight: 700;\n cursor: pointer;\n font-size: 16px;\n transition: all 0.2s;\n \"\n onmouseover=\"this.style.background='#111827'; this.style.color='#fff';\"\n onmouseout=\"this.style.background='#fff'; this.style.color='#111827';\"\n >\n ${pageData.scheduleNow}\n </button>\n </div>\n `\n\n if (infoWindowRef.current) {\n infoWindowRef.current.setContent(content)\n infoWindowRef.current.open(googleMapRef.current, marker)\n\n // 添加按钮点击事件监听\n google.maps.event.addListenerOnce(\n infoWindowRef.current,\n 'domready',\n () => {\n const btn = document.getElementById(\n `schedule-btn-hover-${location.id}`\n )\n if (btn) {\n btn.addEventListener('click', () => {\n if (onSchedule) {\n onSchedule(location.id)\n }\n })\n }\n }\n )\n }\n\n // 移动地图中心到标记位置(可选)\n // googleMapRef.current?.panTo({ lat: location.lat, lng: location.lng })\n }\n }, [hoveredLocationId, isLoaded, locations, onSchedule])\n\n // const handleCloseInfo = useCallback(() => {\n // setSelectedLocation(null)\n // if (infoWindowRef.current) {\n // infoWindowRef.current.close()\n // }\n // }, [])\n\n if (!googleMapsApiKey) {\n return (\n <div\n className={cn(\n 'flex items-center overflow-hidden justify-center bg-gray-100 rounded-[16px]',\n className\n )}\n style={{ height: mapHeight }}\n {...props}\n >\n <p className=\"text-gray-600\">{pageData.apiKeyRequired}</p>\n </div>\n )\n }\n\n return (\n <div\n className={cn('relative w-full rounded-[16px] overflow-hidden', className)}\n {...props}\n >\n <div ref={mapRef} style={{ height: mapHeight }} />\n {!isLoaded && (\n <div className=\"absolute inset-0 flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <div className=\"inline-block animate-spin rounded-full h-8 w-8 border-4 border-gray-300 border-t-gray-900 mb-2\"></div>\n <p className=\"text-gray-600\">{pageData.loadingMap}</p>\n </div>\n </div>\n )}\n </div>\n )\n}\n\nStudioMap.displayName = 'StudioMap'\n","// API 基础类型\nexport interface ApiResponse<T = any> {\n code: number\n message: string\n data: T\n request_id: string\n}\n\n// 时段状态\nexport type TimeslotStatus = 'available' | 'full' | 'disabled'\n\n// 门店类型\nexport type DemoRoomType = 'flagship' | 'standard' | 'popup'\n\n// 门店状态\nexport type DemoRoomStatus = 'enabled' | 'disabled'\n\n// 预约状态\nexport type BookingStatus = 'pending' | 'checked_in' | 'completed' | 'cancelled'\n\n// 问题类型\nexport type QuestionType = 'text' | 'email' | 'tel' | 'phone' | 'radio' | 'radio_with_other' | 'checkbox' | 'textarea' | 'select'\n\n// 时段\nexport interface Timeslot {\n id: number\n start_time: string\n end_time: string\n capacity: number\n booked_count: number\n status: TimeslotStatus\n}\n\n// 门店位置信息\nexport interface DemoRoomLocation {\n country: string\n state: string\n city: string\n}\n\n// 门店\nexport interface DemoRoom {\n code: string\n name: string\n description: string\n equipment?: string[]\n address: string\n location?: DemoRoomLocation\n type: DemoRoomType\n capacity: number\n status: DemoRoomStatus\n timezone: string\n images: string[]\n latitude: number\n longitude: number\n questionnaire_id?: number\n timeslots: Timeslot[]\n}\n\n// 问卷选项\nexport interface QuestionOption {\n label: string\n value?: string\n}\n\n// 问卷问题\nexport interface Question {\n id?: string // 固定字段使用 id(如客户信息字段)\n key?: string // 自定义字段使用 key\n type: QuestionType\n label: string\n description?: string\n placeholder?: string\n hint?: string\n options?: QuestionOption[]\n required: boolean\n is_default?: boolean // 是否为默认题目(首次预约时显示)\n order?: number // 题目顺序\n}\n\n// 问卷\nexport interface Questionnaire {\n id: number\n name: string\n description: string\n questions: Question[]\n}\n\n// 获取门店列表响应\nexport interface GetDemoRoomsResponse {\n demorooms: DemoRoom[]\n}\n\n// 查询时段响应\nexport interface GetTimeslotsResponse {\n timeslots: Timeslot[]\n timezone: string\n}\n\n// 提交预约请求\nexport interface CreateBookingRequest {\n demoroom_code: string\n timeslot_id: number\n questionnaire_id?: number\n questionnaire_response?: Record<string, any>\n customer_name: string\n customer_email: string\n customer_phone_code: string\n customer_phone_number: string\n has_booked_before?: number // 1 - 以前预约过,0 - 首次预约(默认)\n}\n\n// 提交预约响应\nexport interface CreateBookingResponse {\n booking_id: string\n demoroom_code: string\n booking_date: string\n booking_time: string\n customer_name: string\n customer_email: string\n status: string\n cancel_token?: string\n created_at?: string\n}\n\n// 预约信息\nexport interface Booking {\n booking_id: number\n demoroom_code: string\n demoroom_name?: string // 门店名称(查询预约详情时返回)\n address?: string // 门店地址(查询预约详情时返回)\n equipment?: string[] // 设备列表(查询预约详情时返回)\n latitude?: number // 纬度(查询预约详情时返回)\n longitude?: number // 经度(查询预约详情时返回)\n timezone?: string // 门店时区(查询预约详情时返回)\n booking_date: string\n booking_time?: string // 预约开始时间(创建预约时返回)\n time_slot?: string // 时间段 HH:MM-HH:MM(查询预约详情时返回)\n customer_name: string\n customer_email: string\n phone_code?: string // 电话区号\n phone_number?: string // 电话号码\n status: BookingStatus\n cancel_token: string\n created_at: string\n}\n\n// 获取预约详情响应\nexport interface GetBookingResponse {\n booking: Booking\n}\n\n// 取消预约响应\nexport interface CancelBookingResponse {\n booking: Booking\n}\n\n// API 错误码\nexport enum ApiErrorCode {\n SUCCESS = 0,\n PARAM_ERROR = 1001,\n UNAUTHORIZED = 1002,\n FORBIDDEN = 1003,\n NOT_FOUND = 1004,\n CONFLICT = 1005,\n INTERNAL_ERROR = 1006,\n}\n\n// API 错误\nexport class ApiError extends Error {\n code: number\n request_id?: string\n\n constructor(code: number, message: string, request_id?: string) {\n super(message)\n this.code = code\n this.request_id = request_id\n this.name = 'ApiError'\n }\n}\n","import { useState, useEffect, useCallback } from 'react'\nimport type { DemoRoomApiClient } from './client'\nimport type {\n DemoRoom,\n GetTimeslotsResponse,\n Questionnaire,\n CreateBookingRequest,\n Booking,\n} from './types'\nimport { ApiError } from './types'\n\ninterface UseApiState<T> {\n data: T | null\n loading: boolean\n error: ApiError | null\n}\n\n/**\n * 获取门店列表 Hook\n */\nexport function useDemoRooms(\n client: DemoRoomApiClient,\n params: {\n team_code?: string\n brand_website?: string\n locale?: string\n },\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<DemoRoom[]>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled) return\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getDemoRooms(params)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, params.team_code, params.brand_website, params.locale, enabled])\n\n return state\n}\n\n/**\n * 获取门店详情 Hook\n */\nexport function useDemoRoom(\n client: DemoRoomApiClient,\n code: string,\n locale?: string,\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<DemoRoom>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled || !code) return\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getDemoRoom(code, locale)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, code, locale, enabled])\n\n return state\n}\n\n/**\n * 查询门店时段 Hook\n */\nexport function useTimeslots(\n client: DemoRoomApiClient,\n code: string,\n params: {\n start_date: string\n end_date: string\n timezone?: string\n },\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<GetTimeslotsResponse>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled || !code || !params.start_date || !params.end_date) return\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getTimeslots(code, params)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, code, params.start_date, params.end_date, params.timezone, enabled])\n\n return state\n}\n\n/**\n * 查询门店问卷 Hook\n */\nexport function useQuestionnaire(\n client: DemoRoomApiClient,\n code: string,\n questionnaire_id: number | undefined,\n locale?: string,\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<Questionnaire>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled || !code || !questionnaire_id) {\n setState({\n data: null,\n loading: false,\n error: null,\n })\n return\n }\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getQuestionnaire(code, questionnaire_id, locale)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, code, questionnaire_id, locale, enabled])\n\n return state\n}\n\n/**\n * 提交预约 Hook\n */\nexport function useCreateBooking(client: DemoRoomApiClient) {\n const [state, setState] = useState<UseApiState<Booking>>({\n data: null,\n loading: false,\n error: null,\n })\n\n const createBooking = useCallback(\n async (data: CreateBookingRequest) => {\n setState({ data: null, loading: true, error: null })\n\n try {\n const result = await client.createBooking(data)\n setState({ data: result, loading: false, error: null })\n return result\n } catch (error) {\n const apiError = error instanceof ApiError ? error : new ApiError(1006, 'Unknown error')\n setState({ data: null, loading: false, error: apiError })\n throw apiError\n }\n },\n [client]\n )\n\n return {\n ...state,\n createBooking,\n }\n}\n\n/**\n * 获取预约详情 Hook\n */\nexport function useBooking(\n client: DemoRoomApiClient,\n token: string,\n locale?: string,\n options?: { enabled?: boolean }\n) {\n const [state, setState] = useState<UseApiState<Booking>>({\n data: null,\n loading: true,\n error: null,\n })\n\n const enabled = options?.enabled !== false\n\n useEffect(() => {\n if (!enabled || !token) return\n\n let cancelled = false\n\n const fetchData = async () => {\n setState((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const data = await client.getBooking(token, locale)\n if (!cancelled) {\n setState({ data, loading: false, error: null })\n }\n } catch (error) {\n if (!cancelled) {\n setState({\n data: null,\n loading: false,\n error: error instanceof ApiError ? error : new ApiError(1006, 'Unknown error'),\n })\n }\n }\n }\n\n fetchData()\n\n return () => {\n cancelled = true\n }\n }, [client, token, locale, enabled])\n\n return state\n}\n\n/**\n * 取消预约 Hook\n */\nexport function useCancelBooking(client: DemoRoomApiClient) {\n const [state, setState] = useState<UseApiState<Booking>>({\n data: null,\n loading: false,\n error: null,\n })\n\n const cancelBooking = useCallback(\n async (token: string, locale?: string) => {\n setState({ data: null, loading: true, error: null })\n\n try {\n const result = await client.cancelBooking(token, locale)\n setState({ data: result, loading: false, error: null })\n return result\n } catch (error) {\n const apiError = error instanceof ApiError ? error : new ApiError(1006, 'Unknown error')\n setState({ data: null, loading: false, error: apiError })\n throw apiError\n }\n },\n [client]\n )\n\n return {\n ...state,\n cancelBooking,\n }\n}\n","import React, { useEffect, useRef } from 'react'\nimport { cn } from '@/utils/cn'\n\nexport interface AntdMobileIsolatedProps {\n children: React.ReactNode\n className?: string\n style?: React.CSSProperties\n}\n\n/**\n * 隔离 antd-mobile 全局样式的包装组件\n * 通过创建一个独立的样式上下文来防止 antd-mobile 的全局样式影响应用其他部分\n */\nexport const AntdMobileIsolated: React.FC<AntdMobileIsolatedProps> = ({\n children,\n className,\n style,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!containerRef.current) return\n\n // 重置容器内可能受影响的全局样式\n const container = containerRef.current\n const originalStyles = {\n fontSize: container.style.fontSize,\n fontFamily: container.style.fontFamily,\n lineHeight: container.style.lineHeight,\n color: container.style.color,\n }\n\n // 应用隔离样式\n container.style.fontSize = '14px'\n container.style.fontFamily =\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif'\n container.style.lineHeight = '1.5'\n container.style.color = '#333'\n\n // 清理函数:恢复原始样式\n return () => {\n container.style.fontSize = originalStyles.fontSize\n container.style.fontFamily = originalStyles.fontFamily\n container.style.lineHeight = originalStyles.lineHeight\n container.style.color = originalStyles.color\n }\n }, [])\n\n return (\n <div\n ref={containerRef}\n className={cn('antd-mobile-isolated', className)}\n style={{\n // 使用 all: revert-layer 来隔离样式\n isolation: 'isolate',\n contain: 'layout style',\n ...style,\n }}\n >\n {children}\n </div>\n )\n}\n\nAntdMobileIsolated.displayName = 'AntdMobileIsolated'\n","/**\n * 地址解析工具\n * 将 room.address 解析为层级结构:Country > State > City\n */\n\nexport interface LocationHierarchy {\n country: string\n state: string\n city: string\n}\n\n/**\n * 已知国家列表(包含多词国家名)\n * 优先匹配多词国家名,避免误判\n */\nconst KNOWN_COUNTRIES = [\n 'United States',\n 'United Kingdom',\n 'American Samoa',\n 'United Arab Emirates',\n 'Bosnia and Herzegovina',\n 'Trinidad and Tobago',\n 'Saint Kitts and Nevis',\n 'Antigua and Barbuda',\n 'Saint Vincent and the Grenadines',\n 'São Tomé and Príncipe',\n 'United States Minor Outlying Islands',\n 'British Virgin Islands',\n 'United States Virgin Islands',\n 'Cayman Islands',\n 'Cook Islands',\n 'Falkland Islands',\n 'Faroe Islands',\n 'Marshall Islands',\n 'Northern Mariana Islands',\n 'Pitcairn Islands',\n 'Solomon Islands',\n 'Turks and Caicos Islands',\n 'Wallis and Futuna',\n]\n\n/**\n * 从地址字符串中提取国家、州、城市信息\n * 支持多种地址格式,从后往前解析\n *\n * 示例:\n * - \"building information, street test, city-test2, Ofu‑Olosega, American Samoa\"\n * => country: \"American Samoa\", state: \"Ofu‑Olosega\", city: \"city-test2\"\n * - \"111 8th St, San Francisco, CA 94108, United States\"\n * => country: \"United States\", state: \"CA\", city: \"San Francisco\"\n */\nexport function parseAddress(address: string): LocationHierarchy {\n // 按逗号分割地址\n const parts = address.split(',').map((part) => part.trim()).filter(Boolean)\n\n // 默认值\n let country = 'United States'\n let state = ''\n let city = ''\n\n if (parts.length === 0) {\n return { country, state, city }\n }\n\n // 从后往前解析\n // 最后一部分通常是国家\n const lastPart = parts[parts.length - 1]\n\n // 检查最后一部分是否是已知国家\n const matchedCountry = KNOWN_COUNTRIES.find(\n (knownCountry) => lastPart.toLowerCase() === knownCountry.toLowerCase()\n )\n\n if (matchedCountry) {\n country = matchedCountry\n\n // 倒数第二部分是州/省\n if (parts.length >= 2) {\n state = parts[parts.length - 2].split(' ')[0] // 去掉邮编\n }\n\n // 倒数第三部分是城市\n if (parts.length >= 3) {\n city = parts[parts.length - 3]\n }\n } else {\n // 如果最后一部分不是已知国家,尝试其他解析方式\n if (parts.length >= 2) {\n // 可能的格式: \"Street, City, State\"\n state = parts[parts.length - 1].split(' ')[0]\n city = parts[parts.length - 2]\n } else if (parts.length === 1) {\n // 只有一个部分,可能是城市\n city = parts[0]\n }\n }\n\n return {\n country: country.trim(),\n state: state.trim(),\n city: city.trim(),\n }\n}\n\n/**\n * 地理位置节点(用于树形结构)\n */\nexport interface LocationNode {\n id: string\n name: string\n type: 'country' | 'state' | 'city'\n count: number // 该位置的门店数量\n children?: LocationNode[]\n}\n\n/**\n * 从门店列表构建地理位置树\n */\nexport function buildLocationTree(\n locations: Array<{ address: string; id: string }>\n): LocationNode[] {\n const tree: Map<string, LocationNode> = new Map()\n\n locations.forEach((location) => {\n const { country, state, city } = parseAddress(location.address)\n\n // 构建国家节点\n const countryId = country\n if (!tree.has(countryId)) {\n tree.set(countryId, {\n id: countryId,\n name: country,\n type: 'country',\n count: 0,\n children: [],\n })\n }\n\n const countryNode = tree.get(countryId)!\n countryNode.count++\n\n // 构建州节点\n if (state) {\n const stateId = `${country}/${state}`\n let stateNode = countryNode.children?.find((n) => n.id === stateId)\n\n if (!stateNode) {\n stateNode = {\n id: stateId,\n name: state,\n type: 'state',\n count: 0,\n children: [],\n }\n countryNode.children?.push(stateNode)\n }\n\n stateNode.count++\n\n // 构建城市节点\n if (city) {\n const cityId = `${country}/${state}/${city}`\n let cityNode = stateNode.children?.find((n) => n.id === cityId)\n\n if (!cityNode) {\n cityNode = {\n id: cityId,\n name: city,\n type: 'city',\n count: 0,\n }\n stateNode.children?.push(cityNode)\n }\n\n cityNode.count++\n }\n }\n })\n\n return Array.from(tree.values())\n}\n\n/**\n * 按字母分组位置列表\n */\nexport function groupByAlphabet<T extends { name: string }>(\n items: T[]\n): Array<{ title: string; items: T[] }> {\n const groups: Map<string, T[]> = new Map()\n\n items.forEach((item) => {\n const firstChar = item.name.charAt(0).toUpperCase()\n const key = /[A-Z]/.test(firstChar) ? firstChar : '#'\n\n if (!groups.has(key)) {\n groups.set(key, [])\n }\n groups.get(key)!.push(item)\n })\n\n return Array.from(groups.entries())\n .sort(([a], [b]) => {\n if (a === '#') return 1\n if (b === '#') return -1\n return a.localeCompare(b)\n })\n .map(([title, items]) => ({\n title,\n items: items.sort((a, b) => a.name.localeCompare(b.name)),\n }))\n}\n","/* antd-mobile 样式隔离 - 使用更强的隔离策略 */\n.antdMobileScope {\n /* 重置所有继承样式,但保持布局相关属性 */\n all: unset;\n\n /* 恢复必要的属性 */\n display: block;\n position: absolute;\n box-sizing: border-box;\n\n /* 阻止继承字体样式 */\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;\n font-size: 14px;\n line-height: 1.5;\n color: #333;\n\n /* 重置 CSS 变量影响 */\n --adm-color-primary: #1677ff;\n --adm-color-text: #333333;\n --adm-font-size-main: 14px;\n}\n\n/* 确保 antd-mobile 组件内部样式正常工作 */\n.antdMobileScope *,\n.antdMobileScope *::before,\n.antdMobileScope *::after {\n box-sizing: border-box;\n}\n\n/* 阻止全局样式继承 */\n.antd-mobile-isolated-container .antdMobileScope :not([class*=\"adm-\"]) {\n all: unset;\n}\n\n/* 保持 antd-mobile 组件样式 */\n.antd-mobile-isolated-container .antdMobileScope [class*=\"adm-\"] {\n all: revert;\n}\n\n/* 隐藏 List.Item 的右侧箭头 */\n.antd-mobile-isolated-container .antdMobileScope .adm-list-item-content-arrow {\n display: none !important;\n}\n","import React, { useState, useMemo } from 'react'\nimport { cn } from '@/utils/cn'\nimport IndexBar from 'antd-mobile/es/components/index-bar'\nimport List from 'antd-mobile/es/components/list'\nimport 'antd-mobile/es/components/index-bar/index-bar.css'\nimport 'antd-mobile/es/components/list/list.css'\nimport { AntdMobileIsolated } from './AntdMobileIsolated'\nimport { groupByAlphabet } from '../utils/addressParser'\nimport styles from './RoomsList.module.css'\n\nexport type LocationLevel = 'country' | 'state' | 'city'\n\nexport interface LocationFilterProps {\n locations: Array<{\n id: string\n country: string\n state: string\n city: string\n }>\n onSelect?: (selection: LocationSelection) => void\n visible?: boolean\n onClose?: () => void\n pageData?: {\n allLocations?: string\n clear?: string\n country?: string\n state?: string\n city?: string\n noStudiosFound?: string\n }\n}\n\nexport interface LocationSelection {\n level: LocationLevel\n country?: string\n state?: string\n city?: string\n}\n\ninterface LocationItem {\n name: string\n code: string\n count: number\n parentCode?: string\n}\n\nexport const LocationFilter: React.FC<LocationFilterProps> = ({\n locations,\n onSelect,\n visible = false,\n onClose,\n pageData = {\n allLocations: 'All Locations',\n clear: 'Clear',\n country: 'Country',\n state: 'State',\n city: 'City',\n noStudiosFound: 'No studios found in this location',\n },\n}) => {\n const [currentLevel, setCurrentLevel] = useState<LocationLevel>('country')\n const [selectedCountry, setSelectedCountry] = useState<string>()\n const [selectedState, setSelectedState] = useState<string>()\n const [searchQuery, setSearchQuery] = useState('')\n\n // 构建位置数据\n const locationData = useMemo(() => {\n const countries = new Map<string, LocationItem>()\n const states = new Map<string, LocationItem>()\n const cities = new Map<string, LocationItem>()\n\n locations.forEach((location) => {\n const { country, state, city } = location\n\n // 统计国家\n if (country) {\n const existing = countries.get(country)\n countries.set(country, {\n name: country,\n code: country,\n count: (existing?.count || 0) + 1,\n })\n }\n\n // 统计州\n if (state) {\n const stateKey = `${country}/${state}`\n const existing = states.get(stateKey)\n states.set(stateKey, {\n name: state,\n code: stateKey,\n count: (existing?.count || 0) + 1,\n parentCode: country,\n })\n }\n\n // 统计城市\n if (city) {\n const cityKey = `${country}/${state}/${city}`\n const existing = cities.get(cityKey)\n cities.set(cityKey, {\n name: city,\n code: cityKey,\n count: (existing?.count || 0) + 1,\n parentCode: `${country}/${state}`,\n })\n }\n })\n\n return {\n countries: Array.from(countries.values()),\n states: Array.from(states.values()),\n cities: Array.from(cities.values()),\n }\n }, [locations])\n\n // 根据当前层级和选择过滤数据\n const filteredItems = useMemo(() => {\n let items: LocationItem[] = []\n\n switch (currentLevel) {\n case 'country':\n items = locationData.countries\n break\n case 'state':\n items = selectedCountry\n ? locationData.states.filter((s) => s.parentCode === selectedCountry)\n : []\n break\n case 'city':\n items = selectedState\n ? locationData.cities.filter((c) => c.parentCode === selectedState)\n : []\n break\n }\n\n // 应用搜索过滤\n if (searchQuery) {\n items = items.filter((item) =>\n item.name.toLowerCase().includes(searchQuery.toLowerCase())\n )\n }\n\n return items\n }, [currentLevel, selectedCountry, selectedState, locationData, searchQuery])\n\n // 按字母分组\n const groupedItems = useMemo(\n () => groupByAlphabet(filteredItems),\n [filteredItems]\n )\n\n // 判断是否显示字母索引条(数据少于10条时不显示)\n const showIndexBar = filteredItems.length >= 10\n\n const handleItemClick = (item: LocationItem) => {\n // 处理\"All\"选项\n if (item.code === '__all__') {\n if (currentLevel === 'country') {\n // 选择所有国家\n onSelect?.({\n level: 'country',\n })\n onClose?.()\n } else if (currentLevel === 'state') {\n // 选择该国家下的所有州\n onSelect?.({\n level: 'state',\n country: selectedCountry,\n })\n onClose?.()\n } else if (currentLevel === 'city') {\n // 选择该州下的所有城市\n const parts = selectedState?.split('/') || []\n onSelect?.({\n level: 'city',\n country: parts[0],\n state: parts[1],\n })\n onClose?.()\n }\n return\n }\n\n // 正常选择逻辑\n if (currentLevel === 'country') {\n setSelectedCountry(item.code)\n setCurrentLevel('state')\n } else if (currentLevel === 'state') {\n setSelectedState(item.code)\n setCurrentLevel('city')\n } else if (currentLevel === 'city') {\n // 选择城市,触发回调\n const parts = item.code.split('/')\n onSelect?.({\n level: 'city',\n country: parts[0],\n state: parts[1],\n city: parts[2],\n })\n onClose?.()\n }\n }\n\n const handleTabClick = (level: LocationLevel) => {\n setCurrentLevel(level)\n if (level === 'country') {\n setSelectedCountry(undefined)\n setSelectedState(undefined)\n } else if (level === 'state') {\n setSelectedState(undefined)\n }\n }\n\n if (!visible) return null\n\n return (\n <div\n style={{ height: '724px' }}\n className={cn(\n 'w-full rounded-b-[12px] absolute z-10 bottom-[-2px] left-0 bg-white border border-[#E4E5E6]',\n styles.antdMobileScope\n )}\n >\n {/* Header with tabs */}\n <div\n style={{ background: '#F8F8F8' }}\n className=\"h-[76px] font-bold text-[14px] flex flex-col\"\n >\n {/* Tabs */}\n <div className=\"flex items-center text-[16px] px-[20px] gap-[16px] py-[24px]\">\n <button\n onClick={() => handleTabClick('country')}\n className={cn(\n 'pb-[4px] transition-colors',\n currentLevel === 'country'\n ? 'text-[#080A0F] border-b-2 border-[#3ADB67]'\n : 'text-[#080A0F]'\n )}\n >\n {pageData.country}\n </button>\n <button\n onClick={() => handleTabClick('state')}\n disabled={!selectedCountry}\n className={cn(\n 'pb-[4px] transition-colors',\n currentLevel === 'state'\n ? 'text-[#080A0F] border-b-2 border-[#3ADB67]'\n : 'text-[#080A0F]',\n !selectedCountry && 'opacity-50 cursor-not-allowed'\n )}\n >\n {pageData.state}\n </button>\n <button\n onClick={() => handleTabClick('city')}\n disabled={!selectedState}\n className={cn(\n 'pb-[4px] transition-colors',\n currentLevel === 'city'\n ? 'text-[#080A0F] border-b-2 border-[#3ADB67]'\n : 'text-[#080A0F]',\n !selectedState && 'opacity-50 cursor-not-allowed'\n )}\n >\n {pageData.city}\n </button>\n </div>\n </div>\n\n {/* Content */}\n <AntdMobileIsolated style={{ height: 'calc(100% - 76px)' }}>\n {showIndexBar ? (\n <div style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>\n {/* All option */}\n <List>\n <List.Item\n onClick={() => handleItemClick({ code: '__all__', name: pageData.allLocations || 'All', count: filteredItems.length })}\n key=\"__all__\"\n className='text-[16px] !pl-[24px] font-bold'\n style={{ cursor: 'pointer', borderBottom: '1px solid #E4E5E6' }}\n >\n {pageData.allLocations}\n </List.Item>\n </List>\n <IndexBar style={{ flex: 1 }}>\n {groupedItems.map((group) => {\n const { title, items } = group\n return (\n <IndexBar.Panel index={title} title={title} key={title}>\n <List>\n {items.map((item) => (\n <List.Item\n onClick={() => handleItemClick(item)}\n key={item.code}\n className='text-[16px] !pl-[24px]'\n style={{ cursor: 'pointer' }}\n >\n {item.name}\n </List.Item>\n ))}\n </List>\n </IndexBar.Panel>\n )\n })}\n </IndexBar>\n </div>\n ) : (\n <div style={{ height: '100%', overflow: 'auto' }}>\n <List>\n {/* All option */}\n <List.Item\n onClick={() => handleItemClick({ code: '__all__', name: pageData.allLocations || 'All', count: filteredItems.length })}\n key=\"__all__\"\n className='text-[16px] !pl-[24px] font-bold'\n style={{ cursor: 'pointer', borderBottom: '1px solid #E4E5E6' }}\n >\n {pageData.allLocations}\n </List.Item>\n {filteredItems.map((item) => (\n <List.Item\n onClick={() => handleItemClick(item)}\n key={item.code}\n className='text-[16px] !pl-[24px]'\n style={{ cursor: 'pointer' }}\n >\n {item.name}\n </List.Item>\n ))}\n </List>\n </div>\n )}\n </AntdMobileIsolated>\n </div>\n )\n}\n\nLocationFilter.displayName = 'LocationFilter'\n","import React, { useMemo, useState } from 'react'\nimport { cn } from '@/utils/cn'\nimport { Title } from './Title'\nimport { StudioCard } from './StudioCard'\nimport { StudioLocation, StudioMap } from './StudioMap'\nimport { useDemoRooms } from '@/api/hooks'\nimport type { DemoRoomApiClient } from '@/api/client'\nimport { LocationFilter, type LocationSelection } from './LocationFilter'\nimport type { DemoRoomPageData } from '../types/pageData'\n\nexport interface RoomsListProps extends React.HTMLAttributes<HTMLDivElement> {\n googleMapsApiKey?: string\n layoutClassName?: string\n apiClient: DemoRoomApiClient\n teamCode?: string\n brandWebsite?: string\n /**\n * Callback when user clicks \"Schedule Now\" button\n * @param demoRoomCode - The demo room code\n */\n onSchedule?: (demoRoomCode: string) => void\n /**\n * 页面可配置数据(文案、图标等)\n */\n pageData?: DemoRoomPageData\n}\n\n// 默认 pageData 配置\nconst defaultPageData: Required<DemoRoomPageData> = {\n title: 'Find a Studio Near You',\n loadingText: 'Loading demo rooms...',\n errorTitle: 'Failed to load demo rooms',\n machine: 'eufymake E1',\n locationFilter: {\n allLocations: 'All Locations',\n clear: 'Clear',\n country: 'Country',\n state: 'State',\n city: 'City',\n noStudiosFound: 'No studios found in this location',\n },\n studioCard: {\n scheduleNow: 'Schedule Now',\n available: 'Available',\n away: 'away',\n },\n map: {\n apiKeyRequired: 'Google Maps API Key is required',\n loadingMap: 'Loading map...',\n scheduleNow: 'Schedule Now',\n available: 'Available',\n },\n defaultCountry: 'United States',\n noAvailableTime: 'No available time',\n}\n\n// 默认测试数据 - 美国主要城市的工作室位置\nconst defaultStudioLocations: StudioLocation[] = [\n {\n id: '1',\n name: 'Design District Demo Room',\n address: '111 8th St, San Francisco, CA, United States',\n city: 'San Francisco',\n state: 'CA',\n zipCode: '94108',\n country: 'United States',\n lat: 37.7749,\n lng: -122.4194,\n availableTime: 'Oct 28, 2:00 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n {\n id: '2',\n name: 'Brooklyn Creative Studio',\n address: '456 Broadway, Brooklyn, NY, United States',\n city: 'Brooklyn',\n state: 'NY',\n zipCode: '11211',\n country: 'United States',\n lat: 40.7128,\n lng: -74.006,\n availableTime: 'Oct 29, 3:00 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n {\n id: '3',\n name: 'Austin Innovation Hub',\n address: '789 Tech Blvd, Austin, TX, United States',\n city: 'Austin',\n state: 'TX',\n zipCode: '78701',\n country: 'United States',\n lat: 30.2672,\n lng: -97.7431,\n availableTime: 'Oct 30, 1:00 PM',\n euifyMakeModel: 'euifyMake M5',\n },\n {\n id: '4',\n name: 'Seattle Maker Space',\n address: '321 Pine St, Seattle, WA, United States',\n city: 'Seattle',\n state: 'WA',\n zipCode: '98101',\n country: 'United States',\n lat: 47.6062,\n lng: -122.3321,\n availableTime: 'Oct 31, 11:00 AM',\n euifyMakeModel: 'euifyMake E1',\n },\n {\n id: '5',\n name: 'Chicago Design Center',\n address: '654 Michigan Ave, Chicago, IL, United States',\n city: 'Chicago',\n state: 'IL',\n zipCode: '60611',\n country: 'United States',\n lat: 41.8781,\n lng: -87.6298,\n availableTime: 'Nov 1, 2:30 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n {\n id: '6',\n name: 'Miami Beach Studio',\n address: '987 Ocean Drive, Miami Beach, FL, United States',\n city: 'Miami Beach',\n state: 'FL',\n zipCode: '33139',\n country: 'United States',\n lat: 25.7617,\n lng: -80.1918,\n availableTime: 'Nov 2, 10:00 AM',\n euifyMakeModel: 'euifyMake M5',\n },\n {\n id: '7',\n name: 'Denver Mountain Studio',\n address: '147 16th St, Denver, CO, United States',\n city: 'Denver',\n state: 'CO',\n zipCode: '80202',\n country: 'United States',\n lat: 39.7392,\n lng: -104.9903,\n availableTime: 'Nov 3, 4:00 PM',\n euifyMakeModel: 'euifyMake E1',\n },\n {\n id: '8',\n name: 'Los Angeles Creative Lab',\n address: '258 Main St, Los Angeles, CA, United States',\n city: 'Los Angeles',\n state: 'CA',\n zipCode: '90012',\n country: 'United States',\n lat: 34.0522,\n lng: -118.2437,\n availableTime: 'Nov 4, 1:00 PM',\n euifyMakeModel: 'euifyMake E1, euifyMake M5',\n },\n]\n\nexport const RoomsList: React.FC<RoomsListProps> = ({\n googleMapsApiKey,\n className,\n apiClient,\n teamCode,\n brandWebsite,\n onSchedule,\n pageData,\n ...props\n}) => {\n // 合并用户提供的 pageData 和默认配置\n const mergedPageData = useMemo(\n () => ({\n ...defaultPageData,\n ...pageData,\n locationFilter: {\n ...defaultPageData.locationFilter,\n ...pageData?.locationFilter,\n },\n studioCard: { ...defaultPageData.studioCard, ...pageData?.studioCard },\n map: { ...defaultPageData.map, ...pageData?.map },\n }),\n [pageData]\n )\n\n // 状态管理\n const [showLocationFilter, setShowLocationFilter] = useState(false)\n const [selectedLocation, setSelectedLocation] = useState<LocationSelection>()\n const [hoveredRoomId, setHoveredRoomId] = useState<string | null>(null)\n\n // 使用 API 获取门店列表\n const {\n data: demoRooms,\n loading,\n error,\n } = useDemoRooms(apiClient, {\n team_code: teamCode,\n brand_website: brandWebsite,\n })\n console.log(demoRooms)\n\n // 将 API 返回的 DemoRoom 类型转换为 StudioLocation 类型\n const studioLocations = useMemo<StudioLocation[]>(() => {\n if (!demoRooms) return defaultStudioLocations\n\n return demoRooms.map((room) => {\n // 获取下一个可用时段\n const nextAvailableTimeslot = room?.timeslots?.find(\n (slot) => slot.status === 'available'\n )\n\n // 使用 API 返回的 location 数据,不再解析 address\n const country = room.location?.country || mergedPageData.defaultCountry\n const state = room.location?.state || ''\n const city = room.location?.city || ''\n\n // 拼接完整地址: room.address 可能只包含街道地址,需要加上 location 信息\n const addressParts = [room.address, city, state, country].filter(Boolean)\n const fullAddress = addressParts.join(', ')\n\n return {\n id: room.code,\n name: room.name,\n address: fullAddress,\n city,\n state,\n zipCode: '',\n country,\n lat: Number(room.latitude) || 0,\n lng: Number(room.longitude) || 0,\n availableTime: nextAvailableTimeslot\n ? `${nextAvailableTimeslot.start_time}`\n : mergedPageData.noAvailableTime,\n euifyMakeModel: room?.equipment?.join(', ') || '',\n }\n })\n }, [demoRooms, mergedPageData.defaultCountry, mergedPageData.noAvailableTime])\n\n // 根据选择的位置过滤门店\n const filteredStudioLocations = useMemo(() => {\n if (!selectedLocation) return studioLocations\n\n return studioLocations.filter((location) => {\n // 直接使用 location 对象中的 country, state, city 字段进行比较\n if (selectedLocation.city) {\n return (\n location.country === selectedLocation.country &&\n location.state === selectedLocation.state &&\n location.city === selectedLocation.city\n )\n }\n\n if (selectedLocation.state) {\n return (\n location.country === selectedLocation.country &&\n location.state === selectedLocation.state\n )\n }\n\n if (selectedLocation.country) {\n return location.country === selectedLocation.country\n }\n\n return true\n })\n }, [studioLocations, selectedLocation])\n\n // 获取当前选择的位置名称\n const getSelectedLocationName = () => {\n if (!selectedLocation) return mergedPageData.locationFilter.allLocations\n if (selectedLocation.city) return selectedLocation.city\n if (selectedLocation.state) return selectedLocation.state\n if (selectedLocation.country) return selectedLocation.country\n return mergedPageData.locationFilter.allLocations\n }\n\n // 处理位置选择\n const handleLocationSelect = (selection: LocationSelection) => {\n setSelectedLocation(selection)\n setShowLocationFilter(false)\n }\n\n // 清除位置过滤\n const handleClearFilter = () => {\n setSelectedLocation(undefined)\n }\n\n return (\n <div className={className} {...props}>\n {/* Section Title */}\n <Title title={mergedPageData.title}></Title>\n\n {/* Loading State */}\n {loading && (\n <div className=\"flex items-center justify-center h-[794px]\">\n <div className=\"text-center\">\n <div className=\"text-lg font-medium\">\n {mergedPageData.loadingText}\n </div>\n </div>\n </div>\n )}\n\n {/* Error State */}\n {error && (\n <div className=\"flex items-center justify-center h-[794px]\">\n <div className=\"text-center\" style={{ color: '#FF4D4D' }}>\n <div className=\"text-lg font-medium\">\n {mergedPageData.errorTitle}\n </div>\n <div className=\"text-sm mt-2\">{error.message}</div>\n </div>\n </div>\n )}\n\n {/* Content */}\n {!loading && !error && (\n <div className=\"flex h-[794px] gap-4\">\n <div\n className=\"flex-none relative w-[420px] l:!w-full\"\n style={{ height: '794px' }}\n >\n {/* Filter Header */}\n <div className={cn(\n \"mb-4 bg-white border border-[#E4E5E6] px-[20px] py-[16px]\",\n showLocationFilter ? \"rounded-t-[12px] rounded-b-none\" : \"rounded-[12px]\"\n )}>\n {/* First Row */}\n <div className=\"h-[40px] font-bold text-[16px] l:text-[14px] gap-10 l:gap-4 flex items-center\">\n <button\n className=\"flex cursor-pointer items-center hover:text-[#3ADB67] transition-colors\"\n onClick={() => setShowLocationFilter(!showLocationFilter)}\n >\n <span className=\"mr-1\">{getSelectedLocationName()}</span>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n className={cn(\n \"transition-transform duration-300\",\n showLocationFilter && \"rotate-180\"\n )}\n >\n <path\n d=\"M16.7661 9.23364C17.078 9.5455 17.0779 10.0516 16.7661 10.3635L12.5991 14.5305C12.2874 14.842 11.782 14.8418 11.4702 14.5305L7.30322 10.3635C6.99135 10.0516 6.99135 9.54552 7.30322 9.23364C7.615 8.9221 8.1203 8.92219 8.43213 9.23364L12.0347 12.8362L15.6362 9.23364C15.9481 8.92183 16.4543 8.92181 16.7661 9.23364Z\"\n fill=\"currentColor\"\n />\n </svg>\n </button>\n {selectedLocation && false && (\n <button\n onClick={handleClearFilter}\n className=\"ml-auto text-[14px] text-[#2E8B57] hover:underline\"\n >\n {mergedPageData.locationFilter.clear}\n </button>\n )}\n <div className=\"flex text-[#767880] cursor-not-allowed\">\n {mergedPageData.machine}\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n >\n <path\n d=\"M16.7661 9.23364C17.078 9.5455 17.0779 10.0516 16.7661 10.3635L12.5991 14.5305C12.2874 14.842 11.782 14.8418 11.4702 14.5305L7.30322 10.3635C6.99135 10.0516 6.99135 9.54552 7.30322 9.23364C7.615 8.9221 8.1203 8.92219 8.43213 9.23364L12.0347 12.8362L15.6362 9.23364C15.9481 8.92183 16.4543 8.92181 16.7661 9.23364Z\"\n fill=\"currentColor\"\n />\n </svg>\n </div>\n </div>\n </div>\n\n {/* Room List */}\n <div\n style={{ maxHeight: '706px', overflow: 'auto' }}\n className=\"rounded-[12px] bg-white border h-[706px] border-[#E4E5E6]\"\n >\n {filteredStudioLocations.length === 0 ? (\n <div className=\"flex items-center justify-center h-[200px] text-[#767880]\">\n {mergedPageData.locationFilter.noStudiosFound}\n </div>\n ) : (\n filteredStudioLocations.map((item) => {\n return (\n <StudioCard\n key={item.id}\n code={item.id}\n name={item?.name}\n availableTime={item?.availableTime || ''}\n address={item?.address}\n city={item?.city}\n state={item?.state}\n zipCode={item?.zipCode}\n euifyMakeModel={item?.euifyMakeModel || ''}\n onSchedule={onSchedule}\n onMouseEnter={() => setHoveredRoomId(item.id)}\n pageData={{\n ...mergedPageData.studioCard,\n noAvailableTime: mergedPageData?.noAvailableTime,\n }}\n />\n )\n })\n )}\n </div>\n\n {/* Location Filter Overlay */}\n <LocationFilter\n locations={studioLocations.map((loc) => ({\n id: loc.id,\n country: loc.country,\n state: loc.state,\n city: loc.city,\n }))}\n visible={showLocationFilter}\n onSelect={handleLocationSelect}\n onClose={() => setShowLocationFilter(false)}\n pageData={mergedPageData.locationFilter}\n />\n </div>\n {googleMapsApiKey && (\n <div className={cn('flex-1 l:!hidden')}>\n <StudioMap\n googleMapsApiKey={googleMapsApiKey}\n locations={filteredStudioLocations}\n hoveredLocationId={hoveredRoomId}\n onSchedule={onSchedule}\n mapHeight=\"794px\"\n pageData={{\n ...mergedPageData.map,\n noAvailableTime: pageData?.noAvailableTime,\n }}\n />\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n\nRoomsList.displayName = 'RoomsList'\n","import type {\n ApiResponse,\n DemoRoom,\n GetDemoRoomsResponse,\n GetTimeslotsResponse,\n Questionnaire,\n CreateBookingRequest,\n Booking,\n GetBookingResponse,\n CancelBookingResponse,\n} from './types'\nimport { ApiError, ApiErrorCode } from './types'\n\nexport interface DemoRoomApiConfig {\n baseUrl: string\n apiKey: string\n locale?: string\n timeout?: number\n}\n\nexport class DemoRoomApiClient {\n private config: DemoRoomApiConfig\n\n constructor(config: DemoRoomApiConfig) {\n this.config = {\n timeout: 30000,\n ...config,\n }\n }\n\n private async request<T>(\n endpoint: string,\n options: RequestInit = {}\n ): Promise<T> {\n const url = `${this.config.baseUrl}${endpoint}`\n\n const headers: Record<string, string> = {\n 'X-API-Key': this.config.apiKey,\n 'Content-Type': 'application/json',\n ...(options.headers as Record<string, string>),\n }\n\n // 添加语言偏好\n if (this.config.locale) {\n headers['Accept-Language'] = this.config.locale\n }\n\n try {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout)\n\n const response = await fetch(url, {\n ...options,\n headers,\n signal: controller.signal,\n })\n\n clearTimeout(timeoutId)\n\n const data: ApiResponse<T> = await response.json()\n\n if (data.code !== ApiErrorCode.SUCCESS) {\n throw new ApiError(data.code, data.message, data.request_id)\n }\n\n return data.data\n } catch (error) {\n if (error instanceof ApiError) {\n throw error\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n throw new ApiError(ApiErrorCode.INTERNAL_ERROR, 'Request timeout')\n }\n throw new ApiError(ApiErrorCode.INTERNAL_ERROR, error.message)\n }\n\n throw new ApiError(ApiErrorCode.INTERNAL_ERROR, 'Unknown error')\n }\n }\n\n /**\n * 获取门店列表\n * @param params.team_code 团队编码\n * @param params.brand_website 品牌站点\n * @param params.locale 语言偏好(可选)\n */\n async getDemoRooms(params: {\n team_code?: string\n brand_website?: string\n locale?: string\n }): Promise<DemoRoom[]> {\n const searchParams = new URLSearchParams()\n\n if (params.team_code) {\n searchParams.append('team_code', params.team_code)\n }\n\n if (params.brand_website) {\n searchParams.append('brand_website', params.brand_website)\n }\n\n if (params.locale) {\n searchParams.append('locale', params.locale)\n }\n\n const response = await this.request<GetDemoRoomsResponse>(\n `/api/v1/store/demorooms?${searchParams.toString()}`\n )\n\n return response.demorooms\n }\n\n /**\n * 获取门店详情\n * @param code 门店编码\n * @param locale 语言偏好(可选)\n */\n async getDemoRoom(code: string, locale?: string): Promise<DemoRoom> {\n const searchParams = new URLSearchParams()\n if (locale) {\n searchParams.append('locale', locale)\n }\n\n const query = searchParams.toString()\n return this.request<DemoRoom>(\n `/api/v1/store/demorooms/${code}${query ? `?${query}` : ''}`\n )\n }\n\n /**\n * 查询门店时段\n * @param code 门店编码\n * @param params.start_date 开始日期 (YYYY-MM-DD)\n * @param params.end_date 结束日期 (YYYY-MM-DD)\n * @param params.timezone 时区(可选)\n */\n async getTimeslots(\n code: string,\n params: {\n start_date: string\n end_date: string\n timezone?: string\n }\n ): Promise<GetTimeslotsResponse> {\n const searchParams = new URLSearchParams({\n start_date: params.start_date,\n end_date: params.end_date,\n })\n\n if (params.timezone) {\n searchParams.append('timezone', params.timezone)\n }\n\n return this.request<GetTimeslotsResponse>(\n `/api/v1/store/demorooms/${code}/timeslots?${searchParams.toString()}`\n )\n }\n\n /**\n * 查询门店问卷\n * @param code 门店编码\n * @param questionnaire_id 问卷ID\n * @param locale 语言偏好(可选)\n */\n async getQuestionnaire(\n code: string,\n questionnaire_id: number,\n locale?: string\n ): Promise<Questionnaire> {\n const searchParams = new URLSearchParams()\n if (locale) {\n searchParams.append('locale', locale)\n }\n\n const query = searchParams.toString()\n return this.request<Questionnaire>(\n `/api/v1/store/demorooms/${code}/questionnaires/${questionnaire_id}${query ? `?${query}` : ''}`\n )\n }\n\n /**\n * 提交预约\n * @param data 预约数据\n */\n async createBooking(data: CreateBookingRequest): Promise<Booking> {\n return this.request<Booking>('/api/v1/store/bookings', {\n method: 'POST',\n body: JSON.stringify(data),\n })\n }\n\n /**\n * 根据 token 获取预约详情(支持多语言)\n * @param token 预约凭证 (cancel_token)\n * @param locale 语言偏好(可选,也可以通过 Accept-Language Header)\n */\n async getBooking(token: string, locale?: string): Promise<Booking> {\n const headers: Record<string, string> = {}\n\n // 如果指定了 locale,通过 Accept-Language Header 传递\n if (locale) {\n headers['Accept-Language'] = locale\n }\n\n const response = await this.request<GetBookingResponse>(\n `/api/v1/store/bookings/${token}`,\n { headers }\n )\n return response.booking\n }\n\n /**\n * 取消预约(支持多语言邮件通知)\n * @param token 预约凭证 (cancel_token)\n * @param locale 语言偏好(可选,用于邮件通知)\n */\n async cancelBooking(token: string, locale?: string): Promise<Booking> {\n const headers: Record<string, string> = {}\n\n // 如果指定了 locale,通过 Accept-Language Header 传递\n if (locale) {\n headers['Accept-Language'] = locale\n }\n\n const response = await this.request<CancelBookingResponse>(\n `/api/v1/store/bookings/${token}/cancel`,\n {\n method: 'POST',\n headers,\n }\n )\n return response.booking\n }\n}\n\n// 创建默认客户端实例的辅助函数\nexport function createDemoRoomApi(config: DemoRoomApiConfig): DemoRoomApiClient {\n return new DemoRoomApiClient(config)\n}\n","import React, { useMemo } from 'react'\nimport { cn } from '@/utils/cn'\nimport { RoomsList } from './components/RoomsList'\nimport { createDemoRoomApi } from '@/api'\nimport type { DemoRoomApiClient } from '@/api'\nimport type { DemoRoomPageData } from './types/pageData'\n\nexport interface DemoRoomProps extends React.HTMLAttributes<HTMLDivElement> {\n layoutClassName?: string\n /**\n * 谷歌地图 API Key\n */\n googleMapsApiKey?: string\n /**\n * API 配置\n */\n apiConfig: {\n baseUrl: string\n apiKey: string\n locale?: string\n }\n /**\n * 团队编码或品牌站点(二选一)\n */\n teamCode?: string\n brandWebsite?: string\n /**\n * Callback when user clicks \"Schedule Now\" button\n * @param demoRoomCode - The demo room code\n */\n onSchedule?: (demoRoomCode: string) => void\n /**\n * 页面可配置数据(文案、图标等)\n */\n pageData?: DemoRoomPageData\n}\n\nexport const DemoRoom: React.FC<DemoRoomProps> = ({\n className,\n layoutClassName,\n googleMapsApiKey,\n apiConfig,\n teamCode,\n brandWebsite,\n onSchedule,\n pageData,\n ...props\n}) => {\n // 创建 API 客户端实例\n const apiClient = useMemo<DemoRoomApiClient>(\n () => createDemoRoomApi(apiConfig),\n [apiConfig]\n )\n\n return (\n <div className={cn(className)} {...props}>\n <RoomsList\n className={layoutClassName}\n googleMapsApiKey={googleMapsApiKey}\n apiClient={apiClient}\n teamCode={teamCode}\n brandWebsite={brandWebsite}\n onSchedule={onSchedule}\n pageData={pageData}\n ></RoomsList>\n </div>\n )\n}\n\nDemoRoom.displayName = 'DemoRoom'\n"]}