@sonordev/site-kit 1.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/README.md +376 -0
  2. package/dist/SetupWizard-Cki06kB0.d.mts +12 -0
  3. package/dist/SetupWizard-Cki06kB0.d.ts +12 -0
  4. package/dist/analytics/index.d.mts +93 -0
  5. package/dist/analytics/index.d.ts +93 -0
  6. package/dist/analytics/index.js +89 -0
  7. package/dist/analytics/index.js.map +1 -0
  8. package/dist/analytics/index.mjs +71 -0
  9. package/dist/analytics/index.mjs.map +1 -0
  10. package/dist/api-CWtoFJCO.d.mts +137 -0
  11. package/dist/api-CWtoFJCO.d.ts +137 -0
  12. package/dist/blog/index.d.mts +305 -0
  13. package/dist/blog/index.d.ts +305 -0
  14. package/dist/blog/index.js +1578 -0
  15. package/dist/blog/index.js.map +1 -0
  16. package/dist/blog/index.mjs +1562 -0
  17. package/dist/blog/index.mjs.map +1 -0
  18. package/dist/blog/server.d.mts +229 -0
  19. package/dist/blog/server.d.ts +229 -0
  20. package/dist/blog/server.js +692 -0
  21. package/dist/blog/server.js.map +1 -0
  22. package/dist/blog/server.mjs +666 -0
  23. package/dist/blog/server.mjs.map +1 -0
  24. package/dist/chunk-24277A3Q.mjs +968 -0
  25. package/dist/chunk-24277A3Q.mjs.map +1 -0
  26. package/dist/chunk-373TK6TZ.js +321 -0
  27. package/dist/chunk-373TK6TZ.js.map +1 -0
  28. package/dist/chunk-3MYZS6PD.js +30 -0
  29. package/dist/chunk-3MYZS6PD.js.map +1 -0
  30. package/dist/chunk-43GBM4SX.js +283 -0
  31. package/dist/chunk-43GBM4SX.js.map +1 -0
  32. package/dist/chunk-4XPGGLVP.mjs +53 -0
  33. package/dist/chunk-4XPGGLVP.mjs.map +1 -0
  34. package/dist/chunk-622GAQP5.js +2008 -0
  35. package/dist/chunk-622GAQP5.js.map +1 -0
  36. package/dist/chunk-6BIPAKL4.mjs +28 -0
  37. package/dist/chunk-6BIPAKL4.mjs.map +1 -0
  38. package/dist/chunk-6ZCISNAB.mjs +343 -0
  39. package/dist/chunk-6ZCISNAB.mjs.map +1 -0
  40. package/dist/chunk-72MQFHYJ.js +1429 -0
  41. package/dist/chunk-72MQFHYJ.js.map +1 -0
  42. package/dist/chunk-7557OTHW.js +62 -0
  43. package/dist/chunk-7557OTHW.js.map +1 -0
  44. package/dist/chunk-7FUV73JZ.js +981 -0
  45. package/dist/chunk-7FUV73JZ.js.map +1 -0
  46. package/dist/chunk-7RF6PVHA.mjs +324 -0
  47. package/dist/chunk-7RF6PVHA.mjs.map +1 -0
  48. package/dist/chunk-7RYCHO6D.mjs +134 -0
  49. package/dist/chunk-7RYCHO6D.mjs.map +1 -0
  50. package/dist/chunk-7UKPRW25.mjs +1999 -0
  51. package/dist/chunk-7UKPRW25.mjs.map +1 -0
  52. package/dist/chunk-7URAOG2M.js +14864 -0
  53. package/dist/chunk-7URAOG2M.js.map +1 -0
  54. package/dist/chunk-AFAO3TGS.mjs +810 -0
  55. package/dist/chunk-AFAO3TGS.mjs.map +1 -0
  56. package/dist/chunk-BYLIU6XG.js +343 -0
  57. package/dist/chunk-BYLIU6XG.js.map +1 -0
  58. package/dist/chunk-D63MUKZ6.mjs +4423 -0
  59. package/dist/chunk-D63MUKZ6.mjs.map +1 -0
  60. package/dist/chunk-DDKW2FNA.js +390 -0
  61. package/dist/chunk-DDKW2FNA.js.map +1 -0
  62. package/dist/chunk-DQYMKR27.mjs +341 -0
  63. package/dist/chunk-DQYMKR27.mjs.map +1 -0
  64. package/dist/chunk-DW5UJKHH.js +221 -0
  65. package/dist/chunk-DW5UJKHH.js.map +1 -0
  66. package/dist/chunk-EEZCR6E6.js +50 -0
  67. package/dist/chunk-EEZCR6E6.js.map +1 -0
  68. package/dist/chunk-GCJXQ4AG.mjs +59 -0
  69. package/dist/chunk-GCJXQ4AG.mjs.map +1 -0
  70. package/dist/chunk-JGNQK2G6.mjs +14845 -0
  71. package/dist/chunk-JGNQK2G6.mjs.map +1 -0
  72. package/dist/chunk-JTLOJLWQ.mjs +563 -0
  73. package/dist/chunk-JTLOJLWQ.mjs.map +1 -0
  74. package/dist/chunk-K23A4G76.mjs +202 -0
  75. package/dist/chunk-K23A4G76.mjs.map +1 -0
  76. package/dist/chunk-KKU3K7RG.js +336 -0
  77. package/dist/chunk-KKU3K7RG.js.map +1 -0
  78. package/dist/chunk-KUGMH4ZF.js +571 -0
  79. package/dist/chunk-KUGMH4ZF.js.map +1 -0
  80. package/dist/chunk-LBVWVP72.js +110 -0
  81. package/dist/chunk-LBVWVP72.js.map +1 -0
  82. package/dist/chunk-LIVWLY2P.js +138 -0
  83. package/dist/chunk-LIVWLY2P.js.map +1 -0
  84. package/dist/chunk-M2T6R7BA.mjs +1003 -0
  85. package/dist/chunk-M2T6R7BA.mjs.map +1 -0
  86. package/dist/chunk-MV3QN7PW.mjs +47 -0
  87. package/dist/chunk-MV3QN7PW.mjs.map +1 -0
  88. package/dist/chunk-OB7E654K.js +72 -0
  89. package/dist/chunk-OB7E654K.js.map +1 -0
  90. package/dist/chunk-OIIKTGRL.mjs +380 -0
  91. package/dist/chunk-OIIKTGRL.mjs.map +1 -0
  92. package/dist/chunk-P3UWIUJS.mjs +1427 -0
  93. package/dist/chunk-P3UWIUJS.mjs.map +1 -0
  94. package/dist/chunk-PKN27UMH.mjs +136 -0
  95. package/dist/chunk-PKN27UMH.mjs.map +1 -0
  96. package/dist/chunk-QXV4667R.mjs +105 -0
  97. package/dist/chunk-QXV4667R.mjs.map +1 -0
  98. package/dist/chunk-S7FRYNSU.mjs +315 -0
  99. package/dist/chunk-S7FRYNSU.mjs.map +1 -0
  100. package/dist/chunk-TFLQX7K7.mjs +68 -0
  101. package/dist/chunk-TFLQX7K7.mjs.map +1 -0
  102. package/dist/chunk-UWE5PCYJ.mjs +279 -0
  103. package/dist/chunk-UWE5PCYJ.mjs.map +1 -0
  104. package/dist/chunk-UYFDNX2F.js +4469 -0
  105. package/dist/chunk-UYFDNX2F.js.map +1 -0
  106. package/dist/chunk-W4PALSGM.js +350 -0
  107. package/dist/chunk-W4PALSGM.js.map +1 -0
  108. package/dist/chunk-WECQ6KOB.js +1008 -0
  109. package/dist/chunk-WECQ6KOB.js.map +1 -0
  110. package/dist/chunk-XQQWI6WB.js +814 -0
  111. package/dist/chunk-XQQWI6WB.js.map +1 -0
  112. package/dist/chunk-XZJOZJB6.js +140 -0
  113. package/dist/chunk-XZJOZJB6.js.map +1 -0
  114. package/dist/chunk-ZSMWDLMK.js +63 -0
  115. package/dist/chunk-ZSMWDLMK.js.map +1 -0
  116. package/dist/cli/index.js +37243 -0
  117. package/dist/cli/index.js.map +1 -0
  118. package/dist/cli/index.mjs +37209 -0
  119. package/dist/cli/index.mjs.map +1 -0
  120. package/dist/commerce/index.d.mts +170 -0
  121. package/dist/commerce/index.d.ts +170 -0
  122. package/dist/commerce/index.js +174 -0
  123. package/dist/commerce/index.js.map +1 -0
  124. package/dist/commerce/index.mjs +5 -0
  125. package/dist/commerce/index.mjs.map +1 -0
  126. package/dist/commerce/server.d.mts +107 -0
  127. package/dist/commerce/server.d.ts +107 -0
  128. package/dist/commerce/server.js +187 -0
  129. package/dist/commerce/server.js.map +1 -0
  130. package/dist/commerce/server.mjs +177 -0
  131. package/dist/commerce/server.mjs.map +1 -0
  132. package/dist/config/index.d.mts +43 -0
  133. package/dist/config/index.d.ts +43 -0
  134. package/dist/config/index.js +66 -0
  135. package/dist/config/index.js.map +1 -0
  136. package/dist/config/index.mjs +64 -0
  137. package/dist/config/index.mjs.map +1 -0
  138. package/dist/engage/index.d.mts +33 -0
  139. package/dist/engage/index.d.ts +33 -0
  140. package/dist/engage/index.js +22 -0
  141. package/dist/engage/index.js.map +1 -0
  142. package/dist/engage/index.mjs +5 -0
  143. package/dist/engage/index.mjs.map +1 -0
  144. package/dist/forms/index.d.mts +437 -0
  145. package/dist/forms/index.d.ts +437 -0
  146. package/dist/forms/index.js +1168 -0
  147. package/dist/forms/index.js.map +1 -0
  148. package/dist/forms/index.mjs +1142 -0
  149. package/dist/forms/index.mjs.map +1 -0
  150. package/dist/generators-2XKQMPKH.mjs +4 -0
  151. package/dist/generators-2XKQMPKH.mjs.map +1 -0
  152. package/dist/generators-DTMO36DV.js +33 -0
  153. package/dist/generators-DTMO36DV.js.map +1 -0
  154. package/dist/images/index.d.mts +4 -0
  155. package/dist/images/index.d.ts +4 -0
  156. package/dist/images/index.js +46 -0
  157. package/dist/images/index.js.map +1 -0
  158. package/dist/images/index.mjs +5 -0
  159. package/dist/images/index.mjs.map +1 -0
  160. package/dist/images/server.d.mts +69 -0
  161. package/dist/images/server.d.ts +69 -0
  162. package/dist/images/server.js +21 -0
  163. package/dist/images/server.js.map +1 -0
  164. package/dist/images/server.mjs +4 -0
  165. package/dist/images/server.mjs.map +1 -0
  166. package/dist/index.d.mts +846 -0
  167. package/dist/index.d.ts +846 -0
  168. package/dist/index.js +2623 -0
  169. package/dist/index.js.map +1 -0
  170. package/dist/index.mjs +2416 -0
  171. package/dist/index.mjs.map +1 -0
  172. package/dist/layout/index.d.mts +53 -0
  173. package/dist/layout/index.d.ts +53 -0
  174. package/dist/layout/index.js +187 -0
  175. package/dist/layout/index.js.map +1 -0
  176. package/dist/layout/index.mjs +185 -0
  177. package/dist/layout/index.mjs.map +1 -0
  178. package/dist/llms/index.d.mts +448 -0
  179. package/dist/llms/index.d.ts +448 -0
  180. package/dist/llms/index.js +581 -0
  181. package/dist/llms/index.js.map +1 -0
  182. package/dist/llms/index.mjs +529 -0
  183. package/dist/llms/index.mjs.map +1 -0
  184. package/dist/manifest/index.d.mts +62 -0
  185. package/dist/manifest/index.d.ts +62 -0
  186. package/dist/manifest/index.js +85 -0
  187. package/dist/manifest/index.js.map +1 -0
  188. package/dist/manifest/index.mjs +83 -0
  189. package/dist/manifest/index.mjs.map +1 -0
  190. package/dist/middleware/index.d.mts +63 -0
  191. package/dist/middleware/index.d.ts +63 -0
  192. package/dist/middleware/index.js +54 -0
  193. package/dist/middleware/index.js.map +1 -0
  194. package/dist/middleware/index.mjs +51 -0
  195. package/dist/middleware/index.mjs.map +1 -0
  196. package/dist/migrator-2MQHOFDQ.mjs +4 -0
  197. package/dist/migrator-2MQHOFDQ.mjs.map +1 -0
  198. package/dist/migrator-THJCF6MZ.js +37 -0
  199. package/dist/migrator-THJCF6MZ.js.map +1 -0
  200. package/dist/redirects/index.d.mts +78 -0
  201. package/dist/redirects/index.d.ts +78 -0
  202. package/dist/redirects/index.js +26 -0
  203. package/dist/redirects/index.js.map +1 -0
  204. package/dist/redirects/index.mjs +5 -0
  205. package/dist/redirects/index.mjs.map +1 -0
  206. package/dist/reputation/index.d.mts +57 -0
  207. package/dist/reputation/index.d.ts +57 -0
  208. package/dist/reputation/index.js +21 -0
  209. package/dist/reputation/index.js.map +1 -0
  210. package/dist/reputation/index.mjs +4 -0
  211. package/dist/reputation/index.mjs.map +1 -0
  212. package/dist/robots/index.d.mts +38 -0
  213. package/dist/robots/index.d.ts +38 -0
  214. package/dist/robots/index.js +52 -0
  215. package/dist/robots/index.js.map +1 -0
  216. package/dist/robots/index.mjs +50 -0
  217. package/dist/robots/index.mjs.map +1 -0
  218. package/dist/routing-B5XS-6_W.d.mts +118 -0
  219. package/dist/routing-DZYzyDHw.d.ts +118 -0
  220. package/dist/scanner-GAF5PO5F.js +53 -0
  221. package/dist/scanner-GAF5PO5F.js.map +1 -0
  222. package/dist/scanner-LKJKW7IT.mjs +4 -0
  223. package/dist/scanner-LKJKW7IT.mjs.map +1 -0
  224. package/dist/securityHeaders-nwZ6nP4g.d.mts +24 -0
  225. package/dist/securityHeaders-nwZ6nP4g.d.ts +24 -0
  226. package/dist/seo/index.d.mts +600 -0
  227. package/dist/seo/index.d.ts +600 -0
  228. package/dist/seo/index.js +883 -0
  229. package/dist/seo/index.js.map +1 -0
  230. package/dist/seo/index.mjs +773 -0
  231. package/dist/seo/index.mjs.map +1 -0
  232. package/dist/seo/register-sitemap-cli.js +151 -0
  233. package/dist/seo/register-sitemap-cli.js.map +1 -0
  234. package/dist/seo/register-sitemap-cli.mjs +144 -0
  235. package/dist/seo/register-sitemap-cli.mjs.map +1 -0
  236. package/dist/seo/server.d.mts +107 -0
  237. package/dist/seo/server.d.ts +107 -0
  238. package/dist/seo/server.js +207 -0
  239. package/dist/seo/server.js.map +1 -0
  240. package/dist/seo/server.mjs +186 -0
  241. package/dist/seo/server.mjs.map +1 -0
  242. package/dist/server-api-EWXKOQZA.mjs +4 -0
  243. package/dist/server-api-EWXKOQZA.mjs.map +1 -0
  244. package/dist/server-api-GJPNRYUP.js +81 -0
  245. package/dist/server-api-GJPNRYUP.js.map +1 -0
  246. package/dist/setup/client.d.mts +60 -0
  247. package/dist/setup/client.d.ts +60 -0
  248. package/dist/setup/client.js +31 -0
  249. package/dist/setup/client.js.map +1 -0
  250. package/dist/setup/client.mjs +6 -0
  251. package/dist/setup/client.mjs.map +1 -0
  252. package/dist/setup/index.d.mts +5 -0
  253. package/dist/setup/index.d.ts +5 -0
  254. package/dist/setup/index.js +35 -0
  255. package/dist/setup/index.js.map +1 -0
  256. package/dist/setup/index.mjs +6 -0
  257. package/dist/setup/index.mjs.map +1 -0
  258. package/dist/setup/server.d.mts +14 -0
  259. package/dist/setup/server.d.ts +14 -0
  260. package/dist/setup/server.js +13 -0
  261. package/dist/setup/server.js.map +1 -0
  262. package/dist/setup/server.mjs +4 -0
  263. package/dist/setup/server.mjs.map +1 -0
  264. package/dist/site-config/index.d.mts +24 -0
  265. package/dist/site-config/index.d.ts +24 -0
  266. package/dist/site-config/index.js +17 -0
  267. package/dist/site-config/index.js.map +1 -0
  268. package/dist/site-config/index.mjs +4 -0
  269. package/dist/site-config/index.mjs.map +1 -0
  270. package/dist/sitemap/index.d.mts +96 -0
  271. package/dist/sitemap/index.d.ts +96 -0
  272. package/dist/sitemap/index.js +288 -0
  273. package/dist/sitemap/index.js.map +1 -0
  274. package/dist/sitemap/index.mjs +285 -0
  275. package/dist/sitemap/index.mjs.map +1 -0
  276. package/dist/socket-loader-J26QHHOB.js +16 -0
  277. package/dist/socket-loader-J26QHHOB.js.map +1 -0
  278. package/dist/socket-loader-R7S2YJ2J.mjs +14 -0
  279. package/dist/socket-loader-R7S2YJ2J.mjs.map +1 -0
  280. package/dist/types-0dmq3k20.d.mts +168 -0
  281. package/dist/types-0dmq3k20.d.ts +168 -0
  282. package/dist/types-Blb2QNkV.d.mts +263 -0
  283. package/dist/types-Blb2QNkV.d.ts +263 -0
  284. package/dist/types-BnCwwUX3.d.mts +250 -0
  285. package/dist/types-BnCwwUX3.d.ts +250 -0
  286. package/dist/types-CGlnp43R.d.mts +312 -0
  287. package/dist/types-CGlnp43R.d.ts +312 -0
  288. package/dist/types-D08004rU.d.mts +179 -0
  289. package/dist/types-D08004rU.d.ts +179 -0
  290. package/dist/types-DNSYU7qI.d.mts +127 -0
  291. package/dist/types-DNSYU7qI.d.ts +127 -0
  292. package/dist/types-KZP_VWZp.d.mts +266 -0
  293. package/dist/types-KZP_VWZp.d.ts +266 -0
  294. package/dist/useEventModal-BVTx69XE.d.mts +274 -0
  295. package/dist/useEventModal-Dx1dItTJ.d.ts +274 -0
  296. package/dist/web-vitals-444RLW3B.js +252 -0
  297. package/dist/web-vitals-444RLW3B.js.map +1 -0
  298. package/dist/web-vitals-KPICZIEF.mjs +241 -0
  299. package/dist/web-vitals-KPICZIEF.mjs.map +1 -0
  300. package/package.json +192 -0
@@ -0,0 +1,1427 @@
1
+ 'use client';
2
+ import { useState, useCallback, useEffect } from 'react';
3
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
+
5
+ // src/setup/SetupWizard.tsx
6
+ var AVAILABLE_MODULES = [
7
+ { id: "analytics", name: "Analytics", description: "Page views, events, sessions, web vitals", icon: "\u{1F4CA}", recommended: true },
8
+ { id: "seo", name: "SEO", description: "Managed FAQs, meta tags, schema markup", icon: "\u{1F50D}", recommended: true },
9
+ { id: "forms", name: "Forms", description: "Managed forms with Portal submissions", icon: "\u{1F4DD}", recommended: true },
10
+ { id: "engage", name: "Engage", description: "Live chat, popups, nudges, banners", icon: "\u{1F4AC}", recommended: false },
11
+ { id: "commerce", name: "Commerce", description: "Products, services, checkout", icon: "\u{1F6D2}", recommended: false }
12
+ ];
13
+ function SetupWizard({ config } = {}) {
14
+ const [step, setStep] = useState("welcome");
15
+ const [isLoading, setIsLoading] = useState(false);
16
+ const [error, setError] = useState(null);
17
+ const [isAuthenticated, setIsAuthenticated] = useState(false);
18
+ const [userEmail, setUserEmail] = useState(null);
19
+ const [accessToken, setAccessToken] = useState(null);
20
+ const [organizations, setOrganizations] = useState([]);
21
+ const [selectedOrg, setSelectedOrg] = useState(null);
22
+ const [selectedProject, setSelectedProject] = useState(null);
23
+ const [newProjectName, setNewProjectName] = useState("");
24
+ const [newProjectDomain, setNewProjectDomain] = useState("");
25
+ const [createNewProject, setCreateNewProject] = useState(false);
26
+ const [creatingProject, setCreatingProject] = useState(false);
27
+ const [creatingOrg, setCreatingOrg] = useState(false);
28
+ const [newOrgName, setNewOrgName] = useState("");
29
+ const [showNewOrg, setShowNewOrg] = useState(false);
30
+ const [setupType, setSetupType] = useState(null);
31
+ const [brandConfig, setBrandConfig] = useState({
32
+ businessName: "",
33
+ tagline: "",
34
+ primaryColor: "#3B82F6",
35
+ secondaryColor: void 0,
36
+ logoUrl: ""
37
+ });
38
+ const [selectedModules, setSelectedModules] = useState(["analytics", "seo", "forms"]);
39
+ const [scanResults, setScanResults] = useState(null);
40
+ const [migrationProgress, setMigrationProgress] = useState(0);
41
+ const [migrationLog, setMigrationLog] = useState([]);
42
+ const [scrapeDomain, setScrapeDomain] = useState("");
43
+ const [scrapeStatus, setScrapeStatus] = useState(null);
44
+ const [redirectMappings, setRedirectMappings] = useState([]);
45
+ const [copilotInstructions, setCopilotInstructions] = useState("");
46
+ const [generatingCopilot, setGeneratingCopilot] = useState(false);
47
+ const portalApiUrl = config?.portalApiUrl || "http://localhost:3002";
48
+ const handleCreateOrg = useCallback(async () => {
49
+ if (!newOrgName.trim()) return;
50
+ setCreatingOrg(true);
51
+ try {
52
+ const res = await fetch(`${portalApiUrl}/setup/organizations`, {
53
+ method: "POST",
54
+ headers: { "Content-Type": "application/json", ...accessToken ? { "Authorization": `Bearer ${accessToken}` } : {} },
55
+ body: JSON.stringify({ name: newOrgName })
56
+ });
57
+ if (!res.ok) throw new Error("Failed to create organization");
58
+ const org = await res.json();
59
+ setOrganizations((prev) => [...prev, org]);
60
+ setSelectedOrg(org);
61
+ setNewOrgName("");
62
+ setShowNewOrg(false);
63
+ } catch (err) {
64
+ setError(err.message);
65
+ } finally {
66
+ setCreatingOrg(false);
67
+ }
68
+ }, [portalApiUrl, accessToken, newOrgName]);
69
+ const handleCreateProject = useCallback(async () => {
70
+ if (!selectedOrg || !newProjectName.trim()) return;
71
+ setCreatingProject(true);
72
+ try {
73
+ const res = await fetch(`${portalApiUrl}/setup/projects`, {
74
+ method: "POST",
75
+ headers: { "Content-Type": "application/json", ...accessToken ? { "Authorization": `Bearer ${accessToken}` } : {} },
76
+ body: JSON.stringify({ orgId: selectedOrg.id, name: newProjectName, domain: newProjectDomain || (typeof window !== "undefined" ? window.location.hostname : "localhost") })
77
+ });
78
+ if (!res.ok) throw new Error("Failed to create project");
79
+ const project = await res.json();
80
+ setSelectedProject(project);
81
+ setStep("setup-type");
82
+ } catch (err) {
83
+ setError(err.message);
84
+ } finally {
85
+ setCreatingProject(false);
86
+ }
87
+ }, [portalApiUrl, accessToken, selectedOrg, newProjectName, newProjectDomain]);
88
+ const handleSelectProject = useCallback((project) => {
89
+ setSelectedProject(project);
90
+ setStep("setup-type");
91
+ }, []);
92
+ const callPortalApi = useCallback(async (path, options = {}) => {
93
+ const headers = {
94
+ "Content-Type": "application/json",
95
+ ...options.headers || {}
96
+ };
97
+ if (accessToken) {
98
+ headers["Authorization"] = `Bearer ${accessToken}`;
99
+ }
100
+ return fetch(`${portalApiUrl}${path}`, {
101
+ ...options,
102
+ headers
103
+ });
104
+ }, [portalApiUrl, accessToken]);
105
+ useEffect(() => {
106
+ checkExistingConfig();
107
+ }, []);
108
+ async function checkExistingConfig() {
109
+ try {
110
+ const localRes = await fetch("/_uptrade/api/status");
111
+ const localData = await localRes.json();
112
+ if (localData.configured) {
113
+ setStep("complete");
114
+ return;
115
+ }
116
+ const storedToken = localStorage.getItem("uptrade_access_token");
117
+ if (storedToken) {
118
+ setAccessToken(storedToken);
119
+ const res = await fetch(`${portalApiUrl}/setup/session`, {
120
+ headers: { "Authorization": `Bearer ${storedToken}` }
121
+ });
122
+ const data = await res.json();
123
+ if (data.authenticated) {
124
+ setIsAuthenticated(true);
125
+ setUserEmail(data.email);
126
+ setStep("project");
127
+ }
128
+ }
129
+ } catch {
130
+ }
131
+ }
132
+ function WelcomeStep() {
133
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
134
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
135
+ /* @__PURE__ */ jsx("div", { className: "text-6xl mb-4", children: "\u{1F680}" }),
136
+ /* @__PURE__ */ jsx("h1", { className: "text-3xl font-bold mb-2", children: "Welcome to Uptrade Site-Kit" }),
137
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400 text-lg", children: "Let's set up your project in just a few steps" })
138
+ ] }),
139
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-4 my-8", children: [
140
+ /* @__PURE__ */ jsx(FeatureCard, { icon: "\u{1F4CA}", title: "Analytics", description: "Track page views, events, and user sessions" }),
141
+ /* @__PURE__ */ jsx(FeatureCard, { icon: "\u{1F4DD}", title: "Forms", description: "Managed forms with validation and submissions" }),
142
+ /* @__PURE__ */ jsx(FeatureCard, { icon: "\u{1F4AC}", title: "Engage", description: "Popups, nudges, and live chat widgets" })
143
+ ] }),
144
+ /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(Button, { onClick: () => setStep("auth"), children: "Get Started \u2192" }) })
145
+ ] });
146
+ }
147
+ function AuthStep() {
148
+ const [email, setEmail] = useState("");
149
+ const [password, setPassword] = useState("");
150
+ const [authMode, setAuthMode] = useState("portal");
151
+ const [waitingForPopup, setWaitingForPopup] = useState(false);
152
+ useEffect(() => {
153
+ function handleMessage(event) {
154
+ const portalOrigins = ["https://portal.uptrademedia.com", "http://localhost:5173", "http://localhost:8888"];
155
+ if (!portalOrigins.includes(event.origin)) return;
156
+ if (event.data?.type === "uptrade-auth-success") {
157
+ const { accessToken: token, email: userEmail2 } = event.data;
158
+ if (token) {
159
+ localStorage.setItem("uptrade_access_token", token);
160
+ setAccessToken(token);
161
+ setIsAuthenticated(true);
162
+ setUserEmail(userEmail2);
163
+ setWaitingForPopup(false);
164
+ loadOrganizations(token).then(() => setStep("project"));
165
+ }
166
+ } else if (event.data?.type === "uptrade-auth-error") {
167
+ setError(event.data.message || "Authentication failed");
168
+ setWaitingForPopup(false);
169
+ }
170
+ }
171
+ window.addEventListener("message", handleMessage);
172
+ return () => window.removeEventListener("message", handleMessage);
173
+ }, []);
174
+ async function handlePortalAuth() {
175
+ setWaitingForPopup(true);
176
+ setError(null);
177
+ const portalUrl = portalApiUrl.includes("localhost") ? "http://localhost:5173" : "https://portal.uptrademedia.com";
178
+ const callbackUrl = encodeURIComponent(window.location.origin);
179
+ const popup = window.open(
180
+ `${portalUrl}/auth/site-kit?callback=${callbackUrl}`,
181
+ "uptrade-auth",
182
+ "width=500,height=700,left=100,top=100"
183
+ );
184
+ if (!popup) {
185
+ setError("Popup was blocked. Please allow popups and try again.");
186
+ setWaitingForPopup(false);
187
+ return;
188
+ }
189
+ const pollInterval = setInterval(() => {
190
+ if (popup.closed) {
191
+ clearInterval(pollInterval);
192
+ setWaitingForPopup(false);
193
+ }
194
+ }, 1e3);
195
+ }
196
+ async function handleLogin() {
197
+ if (!email.trim() || !password.trim()) return;
198
+ setIsLoading(true);
199
+ setError(null);
200
+ try {
201
+ const supabaseUrl = config?.url || "https://mwcjtnoqxolplwpkxnfe.supabase.co";
202
+ const supabaseKey = config?.anonKey || "";
203
+ const authRes = await fetch(`${supabaseUrl}/auth/v1/token?grant_type=password`, {
204
+ method: "POST",
205
+ headers: { "Content-Type": "application/json", "apikey": supabaseKey },
206
+ body: JSON.stringify({ email, password })
207
+ });
208
+ if (!authRes.ok) {
209
+ const errData = await authRes.json();
210
+ throw new Error(errData.error_description || errData.msg || "Login failed");
211
+ }
212
+ const authData = await authRes.json();
213
+ const token = authData.access_token;
214
+ localStorage.setItem("uptrade_access_token", token);
215
+ setAccessToken(token);
216
+ const sessionRes = await fetch(`${portalApiUrl}/setup/session`, {
217
+ headers: { "Authorization": `Bearer ${token}` }
218
+ });
219
+ const session = await sessionRes.json();
220
+ if (session.authenticated) {
221
+ setIsAuthenticated(true);
222
+ setUserEmail(session.email);
223
+ await loadOrganizations(token);
224
+ setStep("project");
225
+ } else {
226
+ throw new Error("Authentication failed - user not found in Portal");
227
+ }
228
+ } catch (err) {
229
+ setError(err.message);
230
+ } finally {
231
+ setIsLoading(false);
232
+ }
233
+ }
234
+ async function handleMagicLink() {
235
+ if (!email.trim()) return;
236
+ setIsLoading(true);
237
+ setError(null);
238
+ try {
239
+ const supabaseUrl = config?.url || "https://mwcjtnoqxolplwpkxnfe.supabase.co";
240
+ const supabaseKey = config?.anonKey || "";
241
+ const res = await fetch(`${supabaseUrl}/auth/v1/magiclink`, {
242
+ method: "POST",
243
+ headers: { "Content-Type": "application/json", "apikey": supabaseKey },
244
+ body: JSON.stringify({ email, options: { redirectTo: window.location.href } })
245
+ });
246
+ if (!res.ok) throw new Error("Failed to send magic link");
247
+ alert("Check your email for a login link!");
248
+ } catch (err) {
249
+ setError(err.message);
250
+ } finally {
251
+ setIsLoading(false);
252
+ }
253
+ }
254
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
255
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
256
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Connect to Uptrade" }),
257
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Sign in with your Sonor account" })
258
+ ] }),
259
+ /* @__PURE__ */ jsxs("div", { className: "max-w-md mx-auto", children: [
260
+ /* @__PURE__ */ jsx(Button, { onClick: handlePortalAuth, loading: waitingForPopup, disabled: waitingForPopup, children: waitingForPopup ? "Waiting for Sonor..." : "\u{1F680} Sign in with Sonor" }),
261
+ /* @__PURE__ */ jsx("p", { className: "text-gray-500 text-xs text-center mt-2", children: "Uses your existing Portal session (Google, email, etc.)" })
262
+ ] }),
263
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 max-w-md mx-auto", children: [
264
+ /* @__PURE__ */ jsx("div", { className: "flex-1 border-t border-gray-700" }),
265
+ /* @__PURE__ */ jsx("span", { className: "text-gray-500 text-sm", children: "or sign in directly" }),
266
+ /* @__PURE__ */ jsx("div", { className: "flex-1 border-t border-gray-700" })
267
+ ] }),
268
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-center mb-6", children: [
269
+ /* @__PURE__ */ jsx("button", { className: `px-4 py-2 rounded-lg ${authMode === "login" ? "bg-blue-600" : "bg-gray-700"}`, onClick: () => setAuthMode("login"), children: "Email & Password" }),
270
+ /* @__PURE__ */ jsx("button", { className: `px-4 py-2 rounded-lg ${authMode === "magic" ? "bg-blue-600" : "bg-gray-700"}`, onClick: () => setAuthMode("magic"), children: "Magic Link" })
271
+ ] }),
272
+ /* @__PURE__ */ jsxs("div", { className: "max-w-md mx-auto space-y-4", children: [
273
+ /* @__PURE__ */ jsxs("div", { children: [
274
+ /* @__PURE__ */ jsx("label", { className: "block text-sm text-gray-400 mb-2", children: "Email" }),
275
+ /* @__PURE__ */ jsx(
276
+ "input",
277
+ {
278
+ type: "email",
279
+ value: email,
280
+ onChange: (e) => setEmail(e.target.value),
281
+ placeholder: "you@example.com",
282
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg focus:outline-none focus:border-blue-500"
283
+ }
284
+ )
285
+ ] }),
286
+ authMode === "login" && /* @__PURE__ */ jsxs("div", { children: [
287
+ /* @__PURE__ */ jsx("label", { className: "block text-sm text-gray-400 mb-2", children: "Password" }),
288
+ /* @__PURE__ */ jsx(
289
+ "input",
290
+ {
291
+ type: "password",
292
+ value: password,
293
+ onChange: (e) => setPassword(e.target.value),
294
+ placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
295
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg focus:outline-none focus:border-blue-500"
296
+ }
297
+ )
298
+ ] }),
299
+ /* @__PURE__ */ jsx(
300
+ Button,
301
+ {
302
+ onClick: authMode === "login" ? handleLogin : handleMagicLink,
303
+ loading: isLoading,
304
+ variant: "secondary",
305
+ disabled: !email.trim() || authMode === "login" && !password.trim(),
306
+ children: authMode === "login" ? "Sign In \u2192" : "Send Magic Link \u2192"
307
+ }
308
+ ),
309
+ /* @__PURE__ */ jsxs("p", { className: "text-gray-500 text-sm text-center", children: [
310
+ "Don't have an account?",
311
+ " ",
312
+ /* @__PURE__ */ jsx("a", { href: "https://portal.uptrademedia.com/signup", target: "_blank", className: "text-blue-400 hover:underline", children: "Sign up at Portal" })
313
+ ] })
314
+ ] }),
315
+ error && /* @__PURE__ */ jsx("div", { className: "bg-red-500/10 border border-red-500/30 text-red-400 px-4 py-3 rounded-lg text-center", children: error })
316
+ ] });
317
+ }
318
+ async function loadOrganizations(token) {
319
+ try {
320
+ const authToken = token || accessToken;
321
+ const res = await fetch(`${portalApiUrl}/setup/organizations`, {
322
+ headers: authToken ? { "Authorization": `Bearer ${authToken}` } : {}
323
+ });
324
+ const data = await res.json();
325
+ setOrganizations(Array.isArray(data) ? data : []);
326
+ } catch {
327
+ setError("Failed to load organizations");
328
+ }
329
+ }
330
+ function SetupTypeStep() {
331
+ function handleSelectType(type) {
332
+ setSetupType(type);
333
+ if (type === "new") {
334
+ setBrandConfig((prev) => ({ ...prev, businessName: selectedProject?.name || "" }));
335
+ setStep("brand");
336
+ } else if (type === "existing") {
337
+ setStep("modules");
338
+ } else {
339
+ setScrapeDomain(selectedProject?.domain || "");
340
+ setStep("domain");
341
+ }
342
+ }
343
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-8", children: [
344
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
345
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "What are we setting up?" }),
346
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Choose the flow that matches your project" })
347
+ ] }),
348
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-4 max-w-4xl mx-auto", children: [
349
+ /* @__PURE__ */ jsxs(
350
+ "button",
351
+ {
352
+ onClick: () => handleSelectType("new"),
353
+ className: "p-6 bg-gray-800/50 rounded-xl border-2 border-gray-700 hover:border-blue-500 transition-all text-left group",
354
+ children: [
355
+ /* @__PURE__ */ jsx("div", { className: "text-4xl mb-3", children: "\u{1F195}" }),
356
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-bold mb-2 group-hover:text-blue-400 transition-colors", children: "New Site" }),
357
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400 text-sm mb-3", children: "Brand new project. Nothing exists yet - we'll define everything from scratch." }),
358
+ /* @__PURE__ */ jsxs("ul", { className: "text-xs text-gray-500 space-y-1", children: [
359
+ /* @__PURE__ */ jsx("li", { children: "\u2713 Define brand & colors" }),
360
+ /* @__PURE__ */ jsx("li", { children: "\u2713 Choose modules" }),
361
+ /* @__PURE__ */ jsx("li", { children: "\u2713 Generate scaffolding" })
362
+ ] })
363
+ ]
364
+ }
365
+ ),
366
+ /* @__PURE__ */ jsxs(
367
+ "button",
368
+ {
369
+ onClick: () => handleSelectType("existing"),
370
+ className: "p-6 bg-gray-800/50 rounded-xl border-2 border-gray-700 hover:border-green-500 transition-all text-left group",
371
+ children: [
372
+ /* @__PURE__ */ jsx("div", { className: "text-4xl mb-3", children: "\u{1F527}" }),
373
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-bold mb-2 group-hover:text-green-400 transition-colors", children: "Existing Project" }),
374
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400 text-sm mb-3", children: "NextJS project already built. Adding Portal integration to manage content." }),
375
+ /* @__PURE__ */ jsxs("ul", { className: "text-xs text-gray-500 space-y-1", children: [
376
+ /* @__PURE__ */ jsx("li", { children: "\u2713 Scan for forms & widgets" }),
377
+ /* @__PURE__ */ jsx("li", { children: "\u2713 Migrate to managed versions" }),
378
+ /* @__PURE__ */ jsx("li", { children: "\u2713 Keep existing structure" })
379
+ ] })
380
+ ]
381
+ }
382
+ ),
383
+ /* @__PURE__ */ jsxs(
384
+ "button",
385
+ {
386
+ onClick: () => handleSelectType("rebuild"),
387
+ className: "p-6 bg-gray-800/50 rounded-xl border-2 border-gray-700 hover:border-purple-500 transition-all text-left group",
388
+ children: [
389
+ /* @__PURE__ */ jsx("div", { className: "text-4xl mb-3", children: "\u{1F504}" }),
390
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-bold mb-2 group-hover:text-purple-400 transition-colors", children: "Rebuild" }),
391
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400 text-sm mb-3", children: "Client has a live site we didn't build. Recreating it in NextJS with Portal." }),
392
+ /* @__PURE__ */ jsxs("ul", { className: "text-xs text-gray-500 space-y-1", children: [
393
+ /* @__PURE__ */ jsx("li", { children: "\u2713 Scrape existing site" }),
394
+ /* @__PURE__ */ jsx("li", { children: "\u2713 Extract brand & content" }),
395
+ /* @__PURE__ */ jsx("li", { children: "\u2713 Track redirects for SEO" })
396
+ ] })
397
+ ]
398
+ }
399
+ )
400
+ ] })
401
+ ] });
402
+ }
403
+ function BrandStep() {
404
+ const [isExtracting, setIsExtracting] = useState(false);
405
+ const [extractUrl, setExtractUrl] = useState("");
406
+ const [showExtract, setShowExtract] = useState(false);
407
+ async function handleExtractBrand() {
408
+ if (!extractUrl.trim()) return;
409
+ setIsExtracting(true);
410
+ setError(null);
411
+ try {
412
+ const response = await callPortalApi("/site-scrape/brand-only", {
413
+ method: "POST",
414
+ body: JSON.stringify({ domain: extractUrl.replace(/^https?:\/\//, "").split("/")[0] })
415
+ });
416
+ setBrandConfig((prev) => ({
417
+ ...prev,
418
+ businessName: response.business_name || prev.businessName,
419
+ tagline: response.tagline || prev.tagline,
420
+ primaryColor: response.primary_color || prev.primaryColor,
421
+ logoUrl: response.logo_url || prev.logoUrl
422
+ }));
423
+ setShowExtract(false);
424
+ setExtractUrl("");
425
+ } catch (err) {
426
+ setError(`Failed to extract brand: ${err.message}`);
427
+ } finally {
428
+ setIsExtracting(false);
429
+ }
430
+ }
431
+ function handleContinue() {
432
+ if (!brandConfig.businessName.trim()) return;
433
+ setStep("modules");
434
+ }
435
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
436
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
437
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Define Your Brand" }),
438
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Set up the basic brand identity for this project" })
439
+ ] }),
440
+ !showExtract ? /* @__PURE__ */ jsx("div", { className: "max-w-lg mx-auto", children: /* @__PURE__ */ jsxs(
441
+ "button",
442
+ {
443
+ onClick: () => setShowExtract(true),
444
+ className: "w-full flex items-center justify-center gap-3 p-4 bg-gradient-to-r from-purple-500/10 to-blue-500/10 border border-purple-500/30 rounded-lg hover:border-purple-500/50 transition-all",
445
+ children: [
446
+ /* @__PURE__ */ jsx("span", { className: "text-2xl", children: "\u{1F50D}" }),
447
+ /* @__PURE__ */ jsxs("div", { className: "text-left", children: [
448
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: "Extract from existing website" }),
449
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-400", children: "Auto-detect colors, name, and logo from a live site" })
450
+ ] })
451
+ ]
452
+ }
453
+ ) }) : /* @__PURE__ */ jsxs("div", { className: "max-w-lg mx-auto bg-gray-800/50 rounded-lg border border-gray-700 p-4", children: [
454
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
455
+ /* @__PURE__ */ jsx("span", { className: "text-xl", children: "\u{1F50D}" }),
456
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Extract Brand from Website" })
457
+ ] }),
458
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
459
+ /* @__PURE__ */ jsx(
460
+ "input",
461
+ {
462
+ type: "text",
463
+ value: extractUrl,
464
+ onChange: (e) => setExtractUrl(e.target.value),
465
+ placeholder: "example.com",
466
+ className: "flex-1 px-4 py-2 bg-gray-900 border border-gray-700 rounded-lg",
467
+ onKeyDown: (e) => e.key === "Enter" && handleExtractBrand()
468
+ }
469
+ ),
470
+ /* @__PURE__ */ jsx(Button, { onClick: handleExtractBrand, disabled: isExtracting || !extractUrl.trim(), children: isExtracting ? "Extracting..." : "Extract" })
471
+ ] }),
472
+ /* @__PURE__ */ jsx(
473
+ "button",
474
+ {
475
+ onClick: () => setShowExtract(false),
476
+ className: "text-sm text-gray-500 hover:text-gray-400 mt-2",
477
+ children: "Cancel"
478
+ }
479
+ )
480
+ ] }),
481
+ /* @__PURE__ */ jsxs("div", { className: "max-w-lg mx-auto space-y-4", children: [
482
+ /* @__PURE__ */ jsxs("div", { children: [
483
+ /* @__PURE__ */ jsx("label", { className: "block text-sm text-gray-400 mb-2", children: "Business Name *" }),
484
+ /* @__PURE__ */ jsx(
485
+ "input",
486
+ {
487
+ type: "text",
488
+ value: brandConfig.businessName,
489
+ onChange: (e) => setBrandConfig((prev) => ({ ...prev, businessName: e.target.value })),
490
+ placeholder: "Acme Inc",
491
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg"
492
+ }
493
+ )
494
+ ] }),
495
+ /* @__PURE__ */ jsxs("div", { children: [
496
+ /* @__PURE__ */ jsx("label", { className: "block text-sm text-gray-400 mb-2", children: "Tagline" }),
497
+ /* @__PURE__ */ jsx(
498
+ "input",
499
+ {
500
+ type: "text",
501
+ value: brandConfig.tagline,
502
+ onChange: (e) => setBrandConfig((prev) => ({ ...prev, tagline: e.target.value })),
503
+ placeholder: "Making the world better",
504
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg"
505
+ }
506
+ )
507
+ ] }),
508
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-4", children: /* @__PURE__ */ jsxs("div", { children: [
509
+ /* @__PURE__ */ jsx("label", { className: "block text-sm text-gray-400 mb-2", children: "Primary Color" }),
510
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
511
+ /* @__PURE__ */ jsx(
512
+ "input",
513
+ {
514
+ type: "color",
515
+ value: brandConfig.primaryColor,
516
+ onChange: (e) => setBrandConfig((prev) => ({ ...prev, primaryColor: e.target.value })),
517
+ className: "w-12 h-12 rounded border border-gray-700 cursor-pointer"
518
+ }
519
+ ),
520
+ /* @__PURE__ */ jsx(
521
+ "input",
522
+ {
523
+ type: "text",
524
+ value: brandConfig.primaryColor,
525
+ onChange: (e) => setBrandConfig((prev) => ({ ...prev, primaryColor: e.target.value })),
526
+ className: "flex-1 px-3 py-2 bg-gray-800 border border-gray-700 rounded-lg font-mono text-sm"
527
+ }
528
+ )
529
+ ] })
530
+ ] }) }),
531
+ /* @__PURE__ */ jsxs("div", { children: [
532
+ /* @__PURE__ */ jsx("label", { className: "block text-sm text-gray-400 mb-2", children: "Logo URL (optional)" }),
533
+ /* @__PURE__ */ jsx(
534
+ "input",
535
+ {
536
+ type: "text",
537
+ value: brandConfig.logoUrl,
538
+ onChange: (e) => setBrandConfig((prev) => ({ ...prev, logoUrl: e.target.value })),
539
+ placeholder: "https://example.com/logo.svg",
540
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg"
541
+ }
542
+ ),
543
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: "You can add this later via Portal" })
544
+ ] }),
545
+ /* @__PURE__ */ jsxs("div", { className: "bg-gray-800/50 rounded-lg border border-gray-700 p-4", children: [
546
+ /* @__PURE__ */ jsx("h4", { className: "text-sm text-gray-400 mb-3", children: "Preview" }),
547
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
548
+ /* @__PURE__ */ jsx(
549
+ "div",
550
+ {
551
+ className: "w-12 h-12 rounded-lg flex items-center justify-center text-white font-bold text-xl",
552
+ style: { backgroundColor: brandConfig.primaryColor },
553
+ children: brandConfig.businessName.charAt(0) || "?"
554
+ }
555
+ ),
556
+ /* @__PURE__ */ jsxs("div", { children: [
557
+ /* @__PURE__ */ jsx("div", { className: "font-semibold", children: brandConfig.businessName || "Your Business" }),
558
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-400", children: brandConfig.tagline || "Your tagline here" })
559
+ ] })
560
+ ] }),
561
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2 mt-3", children: [
562
+ /* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded", style: { backgroundColor: brandConfig.primaryColor }, title: "Primary" }),
563
+ /* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded", style: { backgroundColor: brandConfig.secondaryColor ?? "#6B7280" }, title: "Secondary" })
564
+ ] })
565
+ ] })
566
+ ] }),
567
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4", children: [
568
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setStep("setup-type"), children: "\u2190 Back" }),
569
+ /* @__PURE__ */ jsx(Button, { onClick: handleContinue, disabled: !brandConfig.businessName.trim(), children: "Continue \u2192" })
570
+ ] })
571
+ ] });
572
+ }
573
+ function ModulesStep() {
574
+ function toggleModule(moduleId) {
575
+ setSelectedModules((prev) => prev.includes(moduleId) ? prev.filter((m) => m !== moduleId) : [...prev, moduleId]);
576
+ }
577
+ async function handleContinue() {
578
+ try {
579
+ await callPortalApi(`/setup/projects/${selectedProject?.id}`, {
580
+ method: "PATCH",
581
+ body: JSON.stringify({
582
+ brand_primary: brandConfig.primaryColor,
583
+ settings: { brand: brandConfig },
584
+ modules_enabled: selectedModules
585
+ })
586
+ });
587
+ if (setupType === "existing") {
588
+ setStep("scan");
589
+ } else {
590
+ setStep("scaffold");
591
+ }
592
+ } catch (err) {
593
+ setError(err.message);
594
+ }
595
+ }
596
+ function handleBack() {
597
+ if (setupType === "existing") {
598
+ setStep("setup-type");
599
+ } else {
600
+ setStep("brand");
601
+ }
602
+ }
603
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
604
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
605
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Select Modules" }),
606
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Choose which Uptrade modules to enable" })
607
+ ] }),
608
+ /* @__PURE__ */ jsx("div", { className: "max-w-2xl mx-auto space-y-3", children: AVAILABLE_MODULES.map((mod) => /* @__PURE__ */ jsxs(
609
+ "button",
610
+ {
611
+ onClick: () => toggleModule(mod.id),
612
+ className: `w-full flex items-center gap-4 p-4 rounded-lg border-2 transition-all text-left ${selectedModules.includes(mod.id) ? "bg-blue-500/10 border-blue-500" : "bg-gray-800/50 border-gray-700 hover:border-gray-600"}`,
613
+ children: [
614
+ /* @__PURE__ */ jsx("div", { className: "text-3xl", children: mod.icon }),
615
+ /* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
616
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
617
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: mod.name }),
618
+ mod.recommended && /* @__PURE__ */ jsx("span", { className: "text-xs bg-green-500/20 text-green-400 px-2 py-0.5 rounded", children: "Recommended" })
619
+ ] }),
620
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-400", children: mod.description })
621
+ ] }),
622
+ /* @__PURE__ */ jsx("div", { className: `w-6 h-6 rounded-full border-2 flex items-center justify-center ${selectedModules.includes(mod.id) ? "bg-blue-500 border-blue-500" : "border-gray-600"}`, children: selectedModules.includes(mod.id) && /* @__PURE__ */ jsx("span", { className: "text-white text-sm", children: "\u2713" }) })
623
+ ]
624
+ },
625
+ mod.id
626
+ )) }),
627
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4", children: [
628
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: handleBack, children: "\u2190 Back" }),
629
+ /* @__PURE__ */ jsx(Button, { onClick: handleContinue, disabled: selectedModules.length === 0, children: "Continue \u2192" })
630
+ ] })
631
+ ] });
632
+ }
633
+ function ScaffoldStep() {
634
+ const [scaffolding, setScaffolding] = useState(false);
635
+ const [scaffoldLog, setScaffoldLog] = useState([]);
636
+ async function handleScaffold() {
637
+ setScaffolding(true);
638
+ setScaffoldLog(["Starting scaffolding..."]);
639
+ const steps = [];
640
+ if (selectedModules.includes("analytics")) steps.push("\u2713 Analytics provider configured");
641
+ if (selectedModules.includes("seo")) {
642
+ steps.push("\u2713 SEO utilities ready");
643
+ steps.push("\u2713 ManagedFAQ component available");
644
+ }
645
+ if (selectedModules.includes("forms")) steps.push("\u2713 Forms integration configured");
646
+ if (selectedModules.includes("engage")) steps.push("\u2713 Engage widgets ready");
647
+ if (selectedModules.includes("commerce")) steps.push("\u2713 Commerce hooks available");
648
+ for (const step2 of steps) {
649
+ await new Promise((r) => setTimeout(r, 400));
650
+ setScaffoldLog((prev) => [...prev, step2]);
651
+ }
652
+ setScaffoldLog((prev) => [...prev, "", "\u{1F389} Scaffolding complete!"]);
653
+ setScaffolding(false);
654
+ }
655
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
656
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
657
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Project Scaffolding" }),
658
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Setting up your selected modules" })
659
+ ] }),
660
+ /* @__PURE__ */ jsxs("div", { className: "max-w-lg mx-auto", children: [
661
+ /* @__PURE__ */ jsxs("div", { className: "bg-gray-800/50 rounded-lg border border-gray-700 p-4", children: [
662
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold mb-2", children: "Configuration" }),
663
+ /* @__PURE__ */ jsxs("div", { className: "text-sm text-gray-400 space-y-1", children: [
664
+ /* @__PURE__ */ jsxs("p", { children: [
665
+ /* @__PURE__ */ jsx("strong", { children: "Brand:" }),
666
+ " ",
667
+ brandConfig.businessName
668
+ ] }),
669
+ /* @__PURE__ */ jsxs("p", { children: [
670
+ /* @__PURE__ */ jsx("strong", { children: "Modules:" }),
671
+ " ",
672
+ selectedModules.join(", ")
673
+ ] })
674
+ ] })
675
+ ] }),
676
+ scaffoldLog.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-4 bg-gray-900 rounded-lg p-4 font-mono text-sm max-h-48 overflow-y-auto", children: scaffoldLog.map((log, i) => /* @__PURE__ */ jsx("div", { className: log.startsWith("\u2713") ? "text-green-400" : log.startsWith("\u{1F389}") ? "text-yellow-400" : "text-gray-400", children: log }, i)) })
677
+ ] }),
678
+ /* @__PURE__ */ jsx("div", { className: "flex justify-center gap-4", children: scaffoldLog.length === 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
679
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setStep("modules"), children: "\u2190 Back" }),
680
+ /* @__PURE__ */ jsx(Button, { onClick: handleScaffold, loading: scaffolding, children: "Generate Scaffolding \u2192" })
681
+ ] }) : !scaffolding && /* @__PURE__ */ jsx(Button, { onClick: () => setStep("integration"), children: "Continue to Integration \u2192" }) })
682
+ ] });
683
+ }
684
+ const handleScan = useCallback(async () => {
685
+ setIsLoading(true);
686
+ setError(null);
687
+ try {
688
+ const res = await fetch("/_uptrade/api/scan", { method: "POST" });
689
+ const data = await res.json();
690
+ setScanResults({
691
+ forms: (data.forms || []).map((f) => ({ ...f, selected: true })),
692
+ widgets: (data.widgets || []).map((w) => ({ ...w, selected: true })),
693
+ metadata: (data.metadata || []).map((m) => ({ ...m, selected: true })),
694
+ analytics: (data.analytics || []).map((a) => ({ ...a, selected: false }))
695
+ });
696
+ setStep("migrate");
697
+ } catch (err) {
698
+ setError(err.message);
699
+ } finally {
700
+ setIsLoading(false);
701
+ }
702
+ }, []);
703
+ function ScanStep() {
704
+ useEffect(() => {
705
+ handleScan();
706
+ }, []);
707
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6 text-center", children: [
708
+ /* @__PURE__ */ jsx("div", { className: "text-6xl animate-pulse", children: "\u{1F50D}" }),
709
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold", children: "Scanning Your Codebase" }),
710
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Looking for forms, widgets, and metadata to migrate..." }),
711
+ /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-8 h-8 border-2 border-green-500 border-t-transparent rounded-full animate-spin" }) })
712
+ ] });
713
+ }
714
+ function MigrateStep() {
715
+ if (!scanResults) return null;
716
+ const allItems = [...scanResults.forms, ...scanResults.widgets, ...scanResults.metadata];
717
+ const selectedItems = allItems.filter((i) => i.selected);
718
+ function toggleItem(type, index) {
719
+ setScanResults((prev) => {
720
+ if (!prev) return prev;
721
+ const updated = { ...prev };
722
+ updated[type] = [...prev[type]];
723
+ updated[type][index] = { ...updated[type][index], selected: !updated[type][index].selected };
724
+ return updated;
725
+ });
726
+ }
727
+ async function handleMigrate() {
728
+ setIsLoading(true);
729
+ setMigrationLog([]);
730
+ setMigrationProgress(0);
731
+ for (let i = 0; i < selectedItems.length; i++) {
732
+ const item = selectedItems[i];
733
+ setMigrationLog((prev) => [...prev, `Migrating ${item.type} in ${item.file}...`]);
734
+ try {
735
+ await fetch("/_uptrade/api/migrate", {
736
+ method: "POST",
737
+ headers: { "Content-Type": "application/json" },
738
+ body: JSON.stringify({ item, projectId: selectedProject?.id })
739
+ });
740
+ setMigrationLog((prev) => [...prev, `\u2713 Migrated ${item.type}`]);
741
+ } catch {
742
+ setMigrationLog((prev) => [...prev, `\u2717 Failed to migrate ${item.type}`]);
743
+ }
744
+ setMigrationProgress(Math.round((i + 1) / selectedItems.length * 100));
745
+ }
746
+ setIsLoading(false);
747
+ setStep("integration");
748
+ }
749
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
750
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
751
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Review & Migrate" }),
752
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Select items to migrate to managed versions" })
753
+ ] }),
754
+ scanResults.forms.length > 0 && /* @__PURE__ */ jsx(Section, { title: "\u{1F4DD} Forms", count: scanResults.forms.filter((f) => f.selected).length, children: scanResults.forms.map((form, i) => /* @__PURE__ */ jsx(ItemRow, { item: form, onToggle: () => toggleItem("forms", i) }, i)) }),
755
+ scanResults.widgets.length > 0 && /* @__PURE__ */ jsx(Section, { title: "\u{1F4AC} Widgets", count: scanResults.widgets.filter((w) => w.selected).length, children: scanResults.widgets.map((widget, i) => /* @__PURE__ */ jsx(ItemRow, { item: widget, onToggle: () => toggleItem("widgets", i) }, i)) }),
756
+ scanResults.metadata.length > 0 && /* @__PURE__ */ jsx(Section, { title: "\u{1F3F7}\uFE0F Metadata/Schema", count: scanResults.metadata.filter((m) => m.selected).length, children: scanResults.metadata.map((meta, i) => /* @__PURE__ */ jsx(ItemRow, { item: meta, onToggle: () => toggleItem("metadata", i) }, i)) }),
757
+ allItems.length === 0 && /* @__PURE__ */ jsxs("div", { className: "text-center py-8 text-gray-400", children: [
758
+ /* @__PURE__ */ jsx("div", { className: "text-4xl mb-4", children: "\u2728" }),
759
+ /* @__PURE__ */ jsx("p", { children: "No existing forms or widgets detected." }),
760
+ /* @__PURE__ */ jsx("p", { className: "text-sm", children: "You're starting fresh!" })
761
+ ] }),
762
+ migrationLog.length > 0 && /* @__PURE__ */ jsx("div", { className: "bg-gray-900 rounded-lg p-4 font-mono text-sm max-h-48 overflow-y-auto", children: migrationLog.map((log, i) => /* @__PURE__ */ jsx("div", { className: log.startsWith("\u2717") ? "text-red-400" : log.startsWith("\u2713") ? "text-green-400" : "text-gray-400", children: log }, i)) }),
763
+ isLoading && /* @__PURE__ */ jsx("div", { className: "h-2 bg-gray-700 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "h-full bg-green-500 transition-all duration-300", style: { width: `${migrationProgress}%` } }) }),
764
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4", children: [
765
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setStep("integration"), children: "Skip Migration" }),
766
+ /* @__PURE__ */ jsxs(Button, { onClick: handleMigrate, loading: isLoading, children: [
767
+ "Migrate ",
768
+ selectedItems.length,
769
+ " Items \u2192"
770
+ ] })
771
+ ] })
772
+ ] });
773
+ }
774
+ function DomainStep() {
775
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
776
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
777
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Enter Existing Site Domain" }),
778
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "We'll scrape it to extract brand, routes, FAQs, and content" })
779
+ ] }),
780
+ /* @__PURE__ */ jsxs("div", { className: "max-w-lg mx-auto space-y-4", children: [
781
+ /* @__PURE__ */ jsxs("div", { children: [
782
+ /* @__PURE__ */ jsx("label", { className: "block text-sm text-gray-400 mb-2", children: "Website Domain" }),
783
+ /* @__PURE__ */ jsx(
784
+ "input",
785
+ {
786
+ type: "text",
787
+ value: scrapeDomain,
788
+ onChange: (e) => setScrapeDomain(e.target.value),
789
+ placeholder: "example.com",
790
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg focus:outline-none focus:border-purple-500"
791
+ }
792
+ ),
793
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-2", children: "Enter without https://" })
794
+ ] }),
795
+ /* @__PURE__ */ jsxs("div", { className: "bg-purple-500/10 border border-purple-500/30 rounded-lg p-4", children: [
796
+ /* @__PURE__ */ jsx("h4", { className: "font-semibold text-purple-400 mb-2", children: "What we'll extract:" }),
797
+ /* @__PURE__ */ jsxs("ul", { className: "text-sm text-gray-400 space-y-1", children: [
798
+ /* @__PURE__ */ jsx("li", { children: "\u{1F3A8} Brand colors, logos, and fonts" }),
799
+ /* @__PURE__ */ jsx("li", { children: "\u{1F5FA}\uFE0F Sitemap and all routes" }),
800
+ /* @__PURE__ */ jsx("li", { children: "\u2753 FAQ sections \u2192 Managed FAQs" }),
801
+ /* @__PURE__ */ jsx("li", { children: "\u{1F4E7} Contact info and social profiles" }),
802
+ /* @__PURE__ */ jsx("li", { children: "\u{1F500} Route mappings for redirects" })
803
+ ] })
804
+ ] })
805
+ ] }),
806
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4", children: [
807
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setStep("setup-type"), children: "\u2190 Back" }),
808
+ /* @__PURE__ */ jsx(Button, { onClick: () => setStep("scrape"), disabled: !scrapeDomain.trim(), children: "Start Scrape \u2192" })
809
+ ] })
810
+ ] });
811
+ }
812
+ function ScrapeStep() {
813
+ const [pollInterval, setPollInterval] = useState(null);
814
+ useEffect(() => {
815
+ startScrape();
816
+ return () => {
817
+ if (pollInterval) clearInterval(pollInterval);
818
+ };
819
+ }, []);
820
+ async function startScrape() {
821
+ try {
822
+ const res = await callPortalApi("/site-scrape", {
823
+ method: "POST",
824
+ body: JSON.stringify({ project_id: selectedProject?.id, domain: scrapeDomain.replace(/^https?:\/\//, "") })
825
+ });
826
+ if (!res.ok) throw new Error("Failed to start scrape");
827
+ const data = await res.json();
828
+ setScrapeStatus(data);
829
+ const interval = setInterval(async () => {
830
+ try {
831
+ const statusRes = await callPortalApi(`/site-scrape/${data.id}/status`);
832
+ const status = await statusRes.json();
833
+ setScrapeStatus(status);
834
+ if (status.status === "completed") {
835
+ clearInterval(interval);
836
+ setPollInterval(null);
837
+ if (status.routes) {
838
+ setRedirectMappings(status.routes.map((r) => ({ from: r.path, to: r.path, enabled: true })));
839
+ }
840
+ setTimeout(() => setStep("review"), 1e3);
841
+ } else if (status.status === "failed") {
842
+ clearInterval(interval);
843
+ setPollInterval(null);
844
+ setError(status.error || "Scrape failed");
845
+ }
846
+ } catch (err) {
847
+ console.error("Poll error:", err);
848
+ }
849
+ }, 2e3);
850
+ setPollInterval(interval);
851
+ } catch (err) {
852
+ setError(err.message);
853
+ }
854
+ }
855
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
856
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
857
+ /* @__PURE__ */ jsx("div", { className: "text-6xl animate-pulse mb-4", children: "\u{1F50D}" }),
858
+ /* @__PURE__ */ jsxs("h2", { className: "text-2xl font-bold mb-2", children: [
859
+ "Scraping ",
860
+ scrapeDomain
861
+ ] }),
862
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: scrapeStatus?.current_step || "Starting..." })
863
+ ] }),
864
+ /* @__PURE__ */ jsxs("div", { className: "max-w-lg mx-auto", children: [
865
+ /* @__PURE__ */ jsx("div", { className: "h-2 bg-gray-700 rounded-full overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "h-full bg-gradient-to-r from-purple-500 to-pink-500 transition-all duration-500", style: { width: `${scrapeStatus?.progress || 0}%` } }) }),
866
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between text-sm text-gray-500 mt-2", children: [
867
+ /* @__PURE__ */ jsxs("span", { children: [
868
+ scrapeStatus?.progress || 0,
869
+ "%"
870
+ ] }),
871
+ /* @__PURE__ */ jsxs("span", { children: [
872
+ scrapeStatus?.pages_found || 0,
873
+ " pages"
874
+ ] })
875
+ ] })
876
+ ] }),
877
+ scrapeStatus && /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-4 max-w-lg mx-auto", children: [
878
+ /* @__PURE__ */ jsx(StatCard, { value: scrapeStatus.pages_found || 0, label: "Pages", color: "purple" }),
879
+ /* @__PURE__ */ jsx(StatCard, { value: scrapeStatus.routes_planned || 0, label: "Routes", color: "pink" }),
880
+ /* @__PURE__ */ jsx(StatCard, { value: scrapeStatus.faqs_imported || 0, label: "FAQs", color: "blue" })
881
+ ] }),
882
+ error && /* @__PURE__ */ jsxs("div", { className: "bg-red-500/10 border border-red-500/30 text-red-400 px-4 py-3 rounded-lg text-center max-w-lg mx-auto", children: [
883
+ error,
884
+ /* @__PURE__ */ jsx("button", { onClick: () => {
885
+ setError(null);
886
+ startScrape();
887
+ }, className: "block mx-auto mt-2 text-sm underline", children: "Try again" })
888
+ ] })
889
+ ] });
890
+ }
891
+ function ReviewStep() {
892
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
893
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
894
+ /* @__PURE__ */ jsx("div", { className: "text-5xl mb-4", children: "\u2705" }),
895
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Scrape Complete!" }),
896
+ /* @__PURE__ */ jsxs("p", { className: "text-gray-400", children: [
897
+ "Here's what we found on ",
898
+ scrapeDomain
899
+ ] })
900
+ ] }),
901
+ /* @__PURE__ */ jsxs("div", { className: "max-w-2xl mx-auto space-y-4", children: [
902
+ scrapeStatus?.brand && /* @__PURE__ */ jsxs("div", { className: "bg-gray-800/50 rounded-lg border border-gray-700 p-4", children: [
903
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold mb-3", children: "\u{1F3A8} Brand" }),
904
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
905
+ /* @__PURE__ */ jsxs("div", { children: [
906
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-400 mb-1", children: "Business Name" }),
907
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: scrapeStatus.brand.business_name || "Not found" })
908
+ ] }),
909
+ /* @__PURE__ */ jsxs("div", { children: [
910
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-400 mb-1", children: "Colors" }),
911
+ /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: scrapeStatus.brand.primary_colors?.slice(0, 4).map((c, i) => /* @__PURE__ */ jsx("div", { className: "w-8 h-8 rounded border border-gray-600", style: { backgroundColor: c.hex }, title: c.hex }, i)) || /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: "None" }) })
912
+ ] })
913
+ ] })
914
+ ] }),
915
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-4", children: [
916
+ /* @__PURE__ */ jsx(StatCard, { value: scrapeStatus?.pages_found || 0, label: "Pages Crawled", color: "purple", large: true }),
917
+ /* @__PURE__ */ jsx(StatCard, { value: scrapeStatus?.routes_planned || 0, label: "Routes Mapped", color: "pink", large: true }),
918
+ /* @__PURE__ */ jsx(StatCard, { value: scrapeStatus?.faqs_imported || 0, label: "FAQs Imported", color: "blue", large: true })
919
+ ] }),
920
+ /* @__PURE__ */ jsx("div", { className: "bg-blue-500/10 border border-blue-500/30 rounded-lg p-4", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-blue-400", children: "\u{1F4A1} All data saved to your project. FAQs are ready in Portal. Next: set up redirects for SEO." }) })
921
+ ] }),
922
+ /* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx(Button, { onClick: () => setStep("redirects"), children: "Configure Redirects \u2192" }) })
923
+ ] });
924
+ }
925
+ function RedirectsStep() {
926
+ function updateRedirect(index, field, value) {
927
+ setRedirectMappings((prev) => {
928
+ const updated = [...prev];
929
+ updated[index] = { ...updated[index], [field]: value };
930
+ return updated;
931
+ });
932
+ }
933
+ async function handleSaveRedirects() {
934
+ try {
935
+ await callPortalApi(`/site-scrape/${scrapeStatus?.id}/redirects`, {
936
+ method: "POST",
937
+ body: JSON.stringify({ redirects: redirectMappings.filter((r) => r.enabled && r.from !== r.to) })
938
+ });
939
+ setStep("integration");
940
+ } catch (err) {
941
+ setError(err.message);
942
+ }
943
+ }
944
+ const changedRedirects = redirectMappings.filter((r) => r.enabled && r.from !== r.to);
945
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
946
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
947
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Configure Redirects" }),
948
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Map old URLs to new routes to preserve SEO" })
949
+ ] }),
950
+ /* @__PURE__ */ jsxs("div", { className: "max-w-3xl mx-auto", children: [
951
+ /* @__PURE__ */ jsxs("div", { className: "bg-gray-800/50 rounded-lg border border-gray-700 overflow-hidden", children: [
952
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 bg-gray-800 flex justify-between items-center border-b border-gray-700", children: [
953
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: "Route Mappings" }),
954
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-400", children: [
955
+ changedRedirects.length,
956
+ " redirects"
957
+ ] })
958
+ ] }),
959
+ /* @__PURE__ */ jsx("div", { className: "max-h-80 overflow-y-auto divide-y divide-gray-700", children: redirectMappings.map((redirect, i) => /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-4 px-4 py-3 ${!redirect.enabled ? "opacity-50" : ""}`, children: [
960
+ /* @__PURE__ */ jsx(
961
+ "input",
962
+ {
963
+ type: "checkbox",
964
+ checked: redirect.enabled,
965
+ onChange: (e) => updateRedirect(i, "enabled", e.target.checked),
966
+ className: "w-5 h-5 rounded border-gray-600 bg-gray-700"
967
+ }
968
+ ),
969
+ /* @__PURE__ */ jsx(
970
+ "input",
971
+ {
972
+ type: "text",
973
+ value: redirect.from,
974
+ onChange: (e) => updateRedirect(i, "from", e.target.value),
975
+ className: "flex-1 px-3 py-2 bg-gray-800 border border-gray-600 rounded text-sm font-mono",
976
+ placeholder: "/old-path"
977
+ }
978
+ ),
979
+ /* @__PURE__ */ jsx("span", { className: "text-gray-500", children: "\u2192" }),
980
+ /* @__PURE__ */ jsx(
981
+ "input",
982
+ {
983
+ type: "text",
984
+ value: redirect.to,
985
+ onChange: (e) => updateRedirect(i, "to", e.target.value),
986
+ className: "flex-1 px-3 py-2 bg-gray-800 border border-gray-600 rounded text-sm font-mono",
987
+ placeholder: "/new-path"
988
+ }
989
+ )
990
+ ] }, i)) })
991
+ ] }),
992
+ /* @__PURE__ */ jsx("div", { className: "mt-4 bg-yellow-500/10 border border-yellow-500/30 rounded-lg p-4", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-yellow-400", children: '\u26A0\uFE0F Only routes where "from" differs from "to" will create redirects. Same paths = no redirect needed.' }) })
993
+ ] }),
994
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4", children: [
995
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setStep("review"), children: "\u2190 Back" }),
996
+ /* @__PURE__ */ jsx(Button, { onClick: handleSaveRedirects, children: changedRedirects.length > 0 ? `Save ${changedRedirects.length} Redirects \u2192` : "Skip & Continue \u2192" })
997
+ ] })
998
+ ] });
999
+ }
1000
+ function IntegrationStep() {
1001
+ const envVars = `NEXT_PUBLIC_UPTRADE_PROJECT_ID=${selectedProject?.id || "xxx"}
1002
+ NEXT_PUBLIC_SUPABASE_URL=${config?.url || "https://xxx.supabase.co"}
1003
+ NEXT_PUBLIC_SUPABASE_ANON_KEY=${config?.anonKey || "xxx"}`;
1004
+ const providerCode = `import { SiteKitProvider } from '@sonordev/site-kit'
1005
+ import { ManagedFavicon } from '@sonordev/site-kit/images'
1006
+
1007
+ export default function RootLayout({ children }) {
1008
+ return (
1009
+ <html>
1010
+ <head>
1011
+ <ManagedFavicon />
1012
+ </head>
1013
+ <body>
1014
+ <SiteKitProvider
1015
+ projectId={process.env.NEXT_PUBLIC_UPTRADE_PROJECT_ID!}
1016
+ supabaseUrl={process.env.NEXT_PUBLIC_SUPABASE_URL!}
1017
+ supabaseAnonKey={process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!}
1018
+ >
1019
+ {children}
1020
+ </SiteKitProvider>
1021
+ </body>
1022
+ </html>
1023
+ )
1024
+ }`;
1025
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
1026
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1027
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Integration Code" }),
1028
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Add these to connect your project to Uptrade" })
1029
+ ] }),
1030
+ /* @__PURE__ */ jsxs("div", { className: "max-w-2xl mx-auto space-y-4", children: [
1031
+ /* @__PURE__ */ jsx(ConfigPreview, { title: "Environment Variables", description: ".env.local", content: envVars }),
1032
+ /* @__PURE__ */ jsx(ConfigPreview, { title: "Layout Provider", description: "app/layout.tsx", content: providerCode }),
1033
+ /* @__PURE__ */ jsx("div", { className: "text-center text-gray-500 text-sm", children: /* @__PURE__ */ jsxs("p", { children: [
1034
+ "Install: ",
1035
+ /* @__PURE__ */ jsx("code", { className: "bg-gray-800 px-2 py-1 rounded", children: "pnpm add @sonordev/site-kit" })
1036
+ ] }) })
1037
+ ] }),
1038
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4", children: [
1039
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => {
1040
+ if (setupType === "new") setStep("scaffold");
1041
+ else if (setupType === "existing") setStep("migrate");
1042
+ else setStep("redirects");
1043
+ }, children: "\u2190 Back" }),
1044
+ /* @__PURE__ */ jsx(Button, { onClick: () => setStep("copilot"), children: "Continue to Copilot \u2192" })
1045
+ ] })
1046
+ ] });
1047
+ }
1048
+ function CopilotStep() {
1049
+ useEffect(() => {
1050
+ generateCopilotInstructions();
1051
+ }, []);
1052
+ async function generateCopilotInstructions() {
1053
+ setGeneratingCopilot(true);
1054
+ try {
1055
+ const res = await callPortalApi("/signal/generate-copilot-instructions", {
1056
+ method: "POST",
1057
+ body: JSON.stringify({
1058
+ projectId: selectedProject?.id,
1059
+ setupType,
1060
+ modules: selectedModules,
1061
+ domain: scrapeDomain || selectedProject?.domain,
1062
+ brand: setupType === "new" ? brandConfig : scrapeStatus?.brand,
1063
+ routes: scrapeStatus?.routes
1064
+ })
1065
+ });
1066
+ if (res.ok) {
1067
+ const data = await res.json();
1068
+ setCopilotInstructions(data.instructions || data.content || "");
1069
+ } else {
1070
+ setCopilotInstructions(generateFallbackTemplate());
1071
+ }
1072
+ } catch {
1073
+ setCopilotInstructions(generateFallbackTemplate());
1074
+ } finally {
1075
+ setGeneratingCopilot(false);
1076
+ }
1077
+ }
1078
+ function generateFallbackTemplate() {
1079
+ const brand = setupType === "new" ? brandConfig : scrapeStatus?.brand;
1080
+ const brandName = brand?.businessName || brand?.business_name || "TBD";
1081
+ return `# ${selectedProject?.name} - Copilot Instructions
1082
+
1083
+ **Project:** ${selectedProject?.name}
1084
+ **Domain:** ${scrapeDomain || selectedProject?.domain}
1085
+ **Stack:** Next.js + @sonordev/site-kit
1086
+ **Setup Type:** ${setupType}
1087
+
1088
+ ## Brand
1089
+ - **Name:** ${brandName}
1090
+ - **Primary Color:** ${brandConfig?.primaryColor || "TBD"}
1091
+ - **Secondary Color:** ${brandConfig?.secondaryColor || "TBD"}
1092
+
1093
+ ## Enabled Modules
1094
+ ${selectedModules.map((m) => `- ${m}`).join("\n")}
1095
+
1096
+ ## Development Notes
1097
+ - This project uses @sonordev/site-kit for managed content
1098
+ - Forms, FAQs, and metadata are managed via Sonor
1099
+ - Analytics tracked via SiteKitProvider
1100
+ ${setupType === "rebuild" ? "- This is a rebuild of an existing site - check redirects for SEO" : ""}
1101
+ `;
1102
+ }
1103
+ async function copyToClipboard() {
1104
+ await navigator.clipboard.writeText(copilotInstructions);
1105
+ alert("Copied!");
1106
+ }
1107
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
1108
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1109
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Copilot Instructions" }),
1110
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Add this to your repo for better AI assistance" })
1111
+ ] }),
1112
+ /* @__PURE__ */ jsxs("div", { className: "max-w-2xl mx-auto", children: [
1113
+ generatingCopilot ? /* @__PURE__ */ jsxs("div", { className: "bg-gray-800/50 rounded-lg border border-gray-700 p-8 text-center", children: [
1114
+ /* @__PURE__ */ jsx("div", { className: "w-8 h-8 border-2 border-blue-500 border-t-transparent rounded-full animate-spin mx-auto mb-4" }),
1115
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Generating with AI..." })
1116
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "bg-gray-800/50 rounded-lg border border-gray-700 overflow-hidden", children: [
1117
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-2 bg-gray-800 flex justify-between items-center", children: [
1118
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: ".github/copilot-instructions.md" }),
1119
+ /* @__PURE__ */ jsx("button", { onClick: copyToClipboard, className: "text-sm text-blue-400 hover:underline", children: "Copy" })
1120
+ ] }),
1121
+ /* @__PURE__ */ jsx("pre", { className: "p-4 text-sm overflow-x-auto max-h-80 overflow-y-auto", children: /* @__PURE__ */ jsx("code", { className: "text-gray-300 whitespace-pre-wrap", children: copilotInstructions }) })
1122
+ ] }),
1123
+ /* @__PURE__ */ jsx("div", { className: "mt-4 bg-green-500/10 border border-green-500/30 rounded-lg p-4", children: /* @__PURE__ */ jsxs("p", { className: "text-sm text-green-400", children: [
1124
+ "\u{1F4A1} Save as ",
1125
+ /* @__PURE__ */ jsx("code", { className: "bg-gray-800 px-1 rounded", children: ".github/copilot-instructions.md" }),
1126
+ " for GitHub Copilot context."
1127
+ ] }) })
1128
+ ] }),
1129
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4", children: [
1130
+ /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: () => setStep("integration"), children: "\u2190 Back" }),
1131
+ /* @__PURE__ */ jsx(Button, { onClick: () => setStep("complete"), children: "Finish Setup \u2192" })
1132
+ ] })
1133
+ ] });
1134
+ }
1135
+ function CompleteStep() {
1136
+ const [removing, setRemoving] = useState(false);
1137
+ async function handleRemoveSetup() {
1138
+ setRemoving(true);
1139
+ try {
1140
+ await fetch("/_uptrade/api/self-destruct", { method: "POST" });
1141
+ window.location.href = "/";
1142
+ } catch (err) {
1143
+ setError(err.message);
1144
+ setRemoving(false);
1145
+ }
1146
+ }
1147
+ function handleReset() {
1148
+ localStorage.removeItem("uptrade_access_token");
1149
+ setStep("welcome");
1150
+ setIsAuthenticated(false);
1151
+ setAccessToken(null);
1152
+ setUserEmail(null);
1153
+ setSelectedOrg(null);
1154
+ setSelectedProject(null);
1155
+ setSetupType(null);
1156
+ }
1157
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6 text-center", children: [
1158
+ /* @__PURE__ */ jsx("div", { className: "text-6xl", children: "\u{1F389}" }),
1159
+ /* @__PURE__ */ jsx("h2", { className: "text-3xl font-bold", children: "You're All Set!" }),
1160
+ /* @__PURE__ */ jsxs("p", { className: "text-gray-400 text-lg", children: [
1161
+ "Site-Kit is configured for ",
1162
+ selectedProject?.name
1163
+ ] }),
1164
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4 max-w-lg mx-auto my-8", children: [
1165
+ /* @__PURE__ */ jsx(QuickLink, { icon: "\u{1F4CA}", title: "Project Dashboard", href: `https://portal.uptrademedia.com/projects/${selectedProject?.id}` }),
1166
+ /* @__PURE__ */ jsx(QuickLink, { icon: "\u{1F4DD}", title: "Manage Forms", href: `https://portal.uptrademedia.com/projects/${selectedProject?.id}/forms` }),
1167
+ /* @__PURE__ */ jsx(QuickLink, { icon: "\u{1F4D6}", title: "Documentation", href: "https://docs.uptrademedia.com/site-kit" }),
1168
+ /* @__PURE__ */ jsx(QuickLink, { icon: "\u{1F4AC}", title: "Get Help", href: "https://portal.uptrademedia.com/messages" })
1169
+ ] }),
1170
+ /* @__PURE__ */ jsx("div", { className: "flex gap-4 justify-center", children: /* @__PURE__ */ jsx(Button, { variant: "secondary", onClick: handleReset, children: "Restart Setup" }) }),
1171
+ /* @__PURE__ */ jsxs("div", { className: "pt-8 border-t border-gray-700", children: [
1172
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400 mb-4", children: "Remove this setup wizard from your project?" }),
1173
+ /* @__PURE__ */ jsx(Button, { variant: "danger", onClick: handleRemoveSetup, loading: removing, children: "Remove Setup Wizard" }),
1174
+ /* @__PURE__ */ jsx("p", { className: "text-gray-500 text-sm mt-2", children: "This will delete the /_uptrade route" })
1175
+ ] })
1176
+ ] });
1177
+ }
1178
+ const renderStep = () => {
1179
+ switch (step) {
1180
+ case "welcome":
1181
+ return /* @__PURE__ */ jsx(WelcomeStep, {});
1182
+ case "auth":
1183
+ return /* @__PURE__ */ jsx(AuthStep, {});
1184
+ case "project":
1185
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
1186
+ /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
1187
+ /* @__PURE__ */ jsx("h2", { className: "text-2xl font-bold mb-2", children: "Select Your Project" }),
1188
+ /* @__PURE__ */ jsx("p", { className: "text-gray-400", children: "Choose an existing project or create a new one" })
1189
+ ] }),
1190
+ /* @__PURE__ */ jsxs("div", { className: "max-w-lg mx-auto", children: [
1191
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center mb-2", children: [
1192
+ /* @__PURE__ */ jsx("label", { className: "text-sm text-gray-400", children: "Organization" }),
1193
+ /* @__PURE__ */ jsx("button", { type: "button", className: "text-sm text-blue-400 hover:underline", onClick: () => setShowNewOrg(!showNewOrg), children: showNewOrg ? "Select existing" : "+ New organization" })
1194
+ ] }),
1195
+ showNewOrg ? /* @__PURE__ */ jsxs("div", { className: "space-y-3 p-4 bg-gray-800/50 rounded-lg border border-gray-700", children: [
1196
+ /* @__PURE__ */ jsx(
1197
+ "input",
1198
+ {
1199
+ id: "new-org-name",
1200
+ type: "text",
1201
+ value: newOrgName,
1202
+ onChange: (e) => setNewOrgName(e.target.value),
1203
+ placeholder: "Organization name",
1204
+ autoComplete: "off",
1205
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg focus:outline-none focus:border-blue-500"
1206
+ },
1207
+ "new-org-name"
1208
+ ),
1209
+ /* @__PURE__ */ jsx(Button, { onClick: handleCreateOrg, loading: creatingOrg, disabled: !newOrgName.trim(), children: "Create Organization" })
1210
+ ] }) : /* @__PURE__ */ jsxs(
1211
+ "select",
1212
+ {
1213
+ value: selectedOrg?.id || "",
1214
+ onChange: (e) => setSelectedOrg(organizations.find((o) => o.id === e.target.value) || null),
1215
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg",
1216
+ children: [
1217
+ /* @__PURE__ */ jsx("option", { value: "", children: "Select organization..." }),
1218
+ organizations.map((org) => /* @__PURE__ */ jsx("option", { value: org.id, children: org.name }, org.id))
1219
+ ]
1220
+ }
1221
+ )
1222
+ ] }),
1223
+ selectedOrg && /* @__PURE__ */ jsxs("div", { className: "max-w-lg mx-auto space-y-4", children: [
1224
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
1225
+ /* @__PURE__ */ jsx("label", { className: "text-sm text-gray-400", children: "Projects" }),
1226
+ /* @__PURE__ */ jsx("button", { type: "button", className: "text-sm text-blue-400 hover:underline", onClick: () => setCreateNewProject(!createNewProject), children: createNewProject ? "Select existing" : "+ Create new" })
1227
+ ] }),
1228
+ createNewProject ? /* @__PURE__ */ jsxs("div", { className: "space-y-4 p-4 bg-gray-800/50 rounded-lg border border-gray-700", children: [
1229
+ /* @__PURE__ */ jsx(
1230
+ "input",
1231
+ {
1232
+ id: "new-project-name",
1233
+ type: "text",
1234
+ value: newProjectName,
1235
+ onChange: (e) => setNewProjectName(e.target.value),
1236
+ placeholder: "Project name",
1237
+ autoComplete: "off",
1238
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg"
1239
+ },
1240
+ "new-project-name"
1241
+ ),
1242
+ /* @__PURE__ */ jsx(
1243
+ "input",
1244
+ {
1245
+ id: "new-project-domain",
1246
+ type: "text",
1247
+ value: newProjectDomain,
1248
+ onChange: (e) => setNewProjectDomain(e.target.value),
1249
+ placeholder: "localhost",
1250
+ autoComplete: "off",
1251
+ className: "w-full px-4 py-3 bg-gray-800 border border-gray-700 rounded-lg"
1252
+ },
1253
+ "new-project-domain"
1254
+ ),
1255
+ /* @__PURE__ */ jsx(Button, { onClick: handleCreateProject, loading: creatingProject, disabled: !newProjectName.trim(), children: "Create Project" })
1256
+ ] }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: selectedOrg.projects.length === 0 ? /* @__PURE__ */ jsxs("p", { className: "text-gray-500 text-center py-8", children: [
1257
+ "No projects yet. ",
1258
+ /* @__PURE__ */ jsx("button", { type: "button", className: "text-blue-400 hover:underline", onClick: () => setCreateNewProject(true), children: "Create one" })
1259
+ ] }) : selectedOrg.projects.map((project) => /* @__PURE__ */ jsxs(
1260
+ "button",
1261
+ {
1262
+ type: "button",
1263
+ onClick: () => handleSelectProject(project),
1264
+ className: "w-full text-left px-4 py-3 bg-gray-800/50 hover:bg-gray-800 border border-gray-700 rounded-lg transition-colors",
1265
+ children: [
1266
+ /* @__PURE__ */ jsx("div", { className: "font-medium", children: project.name }),
1267
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-400", children: project.domain })
1268
+ ]
1269
+ },
1270
+ project.id
1271
+ )) })
1272
+ ] })
1273
+ ] }, "project-step");
1274
+ case "setup-type":
1275
+ return /* @__PURE__ */ jsx(SetupTypeStep, {});
1276
+ case "brand":
1277
+ return /* @__PURE__ */ jsx(BrandStep, {});
1278
+ case "modules":
1279
+ return /* @__PURE__ */ jsx(ModulesStep, {});
1280
+ case "scaffold":
1281
+ return /* @__PURE__ */ jsx(ScaffoldStep, {});
1282
+ case "scan":
1283
+ return /* @__PURE__ */ jsx(ScanStep, {});
1284
+ case "migrate":
1285
+ return /* @__PURE__ */ jsx(MigrateStep, {});
1286
+ case "domain":
1287
+ return /* @__PURE__ */ jsx(DomainStep, {});
1288
+ case "scrape":
1289
+ return /* @__PURE__ */ jsx(ScrapeStep, {});
1290
+ case "review":
1291
+ return /* @__PURE__ */ jsx(ReviewStep, {});
1292
+ case "redirects":
1293
+ return /* @__PURE__ */ jsx(RedirectsStep, {});
1294
+ case "integration":
1295
+ return /* @__PURE__ */ jsx(IntegrationStep, {});
1296
+ case "copilot":
1297
+ return /* @__PURE__ */ jsx(CopilotStep, {});
1298
+ case "complete":
1299
+ return /* @__PURE__ */ jsx(CompleteStep, {});
1300
+ default:
1301
+ return /* @__PURE__ */ jsx(WelcomeStep, {});
1302
+ }
1303
+ };
1304
+ const getProgress = () => {
1305
+ const common = ["welcome", "auth", "project", "setup-type"];
1306
+ const newFlow = ["brand", "modules", "scaffold"];
1307
+ const existingFlow = ["modules", "scan", "migrate"];
1308
+ const rebuildFlow = ["domain", "scrape", "review", "redirects"];
1309
+ const finish = ["integration", "copilot", "complete"];
1310
+ const flow = setupType === "new" ? [...common, ...newFlow, ...finish] : setupType === "existing" ? [...common, ...existingFlow, ...finish] : setupType === "rebuild" ? [...common, ...rebuildFlow, ...finish] : [...common, ...finish];
1311
+ const idx = flow.indexOf(step);
1312
+ return idx >= 0 ? idx / (flow.length - 1) * 100 : 0;
1313
+ };
1314
+ const setupLabels = { new: "\u{1F195} New Site", existing: "\u{1F527} Existing", rebuild: "\u{1F504} Rebuild" };
1315
+ return /* @__PURE__ */ jsxs("div", { style: {
1316
+ position: "fixed",
1317
+ top: 0,
1318
+ left: 0,
1319
+ right: 0,
1320
+ bottom: 0,
1321
+ zIndex: 99999,
1322
+ minHeight: "100vh",
1323
+ backgroundColor: "#0f172a",
1324
+ color: "#ffffff",
1325
+ fontFamily: "system-ui, -apple-system, sans-serif",
1326
+ overflow: "auto"
1327
+ }, className: "min-h-screen bg-gradient-to-br from-gray-900 via-gray-900 to-gray-800 text-white", children: [
1328
+ /* @__PURE__ */ jsx("div", { style: { position: "fixed", top: 0, left: 0, right: 0, height: "4px", backgroundColor: "#1e293b", zIndex: 1e5 }, children: /* @__PURE__ */ jsx("div", { style: { height: "100%", background: "linear-gradient(to right, #3b82f6, #8b5cf6)", transition: "width 0.5s", width: `${getProgress()}%` } }) }),
1329
+ /* @__PURE__ */ jsxs("header", { style: { padding: "1.5rem 2rem", display: "flex", justifyContent: "space-between", alignItems: "center" }, children: [
1330
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1331
+ /* @__PURE__ */ jsx("div", { className: "w-8 h-8 bg-gradient-to-br from-blue-500 to-purple-600 rounded-lg" }),
1332
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: "Uptrade Site-Kit" }),
1333
+ setupType && /* @__PURE__ */ jsx("span", { className: `text-xs px-2 py-1 rounded ${setupType === "new" ? "bg-blue-500/20 text-blue-400" : setupType === "existing" ? "bg-green-500/20 text-green-400" : "bg-purple-500/20 text-purple-400"}`, children: setupLabels[setupType] })
1334
+ ] }),
1335
+ userEmail && /* @__PURE__ */ jsx("div", { className: "text-gray-400 text-sm", children: userEmail })
1336
+ ] }),
1337
+ /* @__PURE__ */ jsx("main", { className: "max-w-4xl mx-auto px-8 py-12", children: renderStep() }),
1338
+ /* @__PURE__ */ jsxs("footer", { className: "fixed bottom-0 left-0 right-0 px-8 py-4 text-center text-gray-500 text-sm", children: [
1339
+ /* @__PURE__ */ jsx("a", { href: "https://uptrademedia.com", target: "_blank", className: "hover:text-gray-300", children: "Uptrade Media" }),
1340
+ " \xB7 ",
1341
+ /* @__PURE__ */ jsx("a", { href: "https://docs.uptrademedia.com", target: "_blank", className: "hover:text-gray-300", children: "Docs" })
1342
+ ] })
1343
+ ] });
1344
+ }
1345
+ function Button({ children, onClick, loading, disabled, variant = "primary" }) {
1346
+ const variants = {
1347
+ primary: "bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700",
1348
+ secondary: "bg-gray-700 hover:bg-gray-600",
1349
+ danger: "bg-red-600/20 border border-red-500/30 text-red-400 hover:bg-red-600/30"
1350
+ };
1351
+ return /* @__PURE__ */ jsx(
1352
+ "button",
1353
+ {
1354
+ onClick,
1355
+ disabled: loading || disabled,
1356
+ className: `px-6 py-3 rounded-lg font-medium transition-all disabled:opacity-50 disabled:cursor-not-allowed ${variants[variant]}`,
1357
+ children: loading ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
1358
+ /* @__PURE__ */ jsx("span", { className: "w-4 h-4 border-2 border-current border-t-transparent rounded-full animate-spin" }),
1359
+ "Loading..."
1360
+ ] }) : children
1361
+ }
1362
+ );
1363
+ }
1364
+ function FeatureCard({ icon, title, description }) {
1365
+ return /* @__PURE__ */ jsxs("div", { className: "p-6 bg-gray-800/50 rounded-xl border border-gray-700 text-center", children: [
1366
+ /* @__PURE__ */ jsx("div", { className: "text-3xl mb-3", children: icon }),
1367
+ /* @__PURE__ */ jsx("h3", { className: "font-semibold mb-1", children: title }),
1368
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-400", children: description })
1369
+ ] });
1370
+ }
1371
+ function StatCard({ value, label, color, large }) {
1372
+ const colors = { purple: "text-purple-400", pink: "text-pink-400", blue: "text-blue-400" };
1373
+ return /* @__PURE__ */ jsxs("div", { className: "bg-gray-800/50 rounded-lg p-4 text-center border border-gray-700", children: [
1374
+ /* @__PURE__ */ jsx("div", { className: `${large ? "text-3xl" : "text-2xl"} font-bold ${colors[color]}`, children: value }),
1375
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-400", children: label })
1376
+ ] });
1377
+ }
1378
+ function Section({ title, count, children }) {
1379
+ return /* @__PURE__ */ jsxs("div", { className: "bg-gray-800/30 rounded-xl border border-gray-700 overflow-hidden", children: [
1380
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 bg-gray-800/50 flex justify-between items-center", children: [
1381
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: title }),
1382
+ /* @__PURE__ */ jsxs("span", { className: "text-sm text-gray-400", children: [
1383
+ count,
1384
+ " selected"
1385
+ ] })
1386
+ ] }),
1387
+ /* @__PURE__ */ jsx("div", { className: "divide-y divide-gray-700", children })
1388
+ ] });
1389
+ }
1390
+ function ItemRow({ item, onToggle }) {
1391
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 px-4 py-3 hover:bg-gray-800/30 transition-colors", children: [
1392
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: item.selected, onChange: onToggle, className: "w-5 h-5 rounded border-gray-600 bg-gray-700 text-blue-500" }),
1393
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
1394
+ /* @__PURE__ */ jsx("div", { className: "font-medium truncate", children: item.type }),
1395
+ /* @__PURE__ */ jsxs("div", { className: "text-sm text-gray-400 truncate", children: [
1396
+ item.file,
1397
+ ":",
1398
+ item.line
1399
+ ] })
1400
+ ] })
1401
+ ] });
1402
+ }
1403
+ function ConfigPreview({ title, description, content }) {
1404
+ async function copy() {
1405
+ await navigator.clipboard.writeText(content);
1406
+ }
1407
+ return /* @__PURE__ */ jsxs("div", { className: "bg-gray-800/50 rounded-lg border border-gray-700 overflow-hidden", children: [
1408
+ /* @__PURE__ */ jsxs("div", { className: "px-4 py-2 bg-gray-800 flex justify-between items-center", children: [
1409
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: title }),
1410
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1411
+ /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-400", children: description }),
1412
+ /* @__PURE__ */ jsx("button", { onClick: copy, className: "text-sm text-blue-400 hover:underline", children: "Copy" })
1413
+ ] })
1414
+ ] }),
1415
+ /* @__PURE__ */ jsx("pre", { className: "p-4 text-sm overflow-x-auto", children: /* @__PURE__ */ jsx("code", { className: "text-green-400", children: content }) })
1416
+ ] });
1417
+ }
1418
+ function QuickLink({ icon, title, href }) {
1419
+ return /* @__PURE__ */ jsxs("a", { href, target: "_blank", className: "flex items-center gap-3 p-4 bg-gray-800/50 rounded-lg border border-gray-700 hover:bg-gray-800 transition-colors", children: [
1420
+ /* @__PURE__ */ jsx("span", { className: "text-2xl", children: icon }),
1421
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: title })
1422
+ ] });
1423
+ }
1424
+
1425
+ export { SetupWizard };
1426
+ //# sourceMappingURL=chunk-P3UWIUJS.mjs.map
1427
+ //# sourceMappingURL=chunk-P3UWIUJS.mjs.map