Lianjx commited on
Commit
a122535
·
verified ·
1 Parent(s): 7a2dcba

Upload 16 files

Browse files
Files changed (4) hide show
  1. App.tsx +6 -4
  2. index.html +7 -7
  3. store.ts +15 -7
  4. types.ts +11 -2
App.tsx CHANGED
@@ -1,3 +1,4 @@
 
1
  import React, { useState, useRef, useEffect, Suspense } from 'react';
2
  import { Header } from './components/Header';
3
  import { ImageUploader } from './components/ImageUploader';
@@ -41,9 +42,9 @@ const Toast = ({ msg, onClose }: { msg: string, onClose: () => void }) => (
41
  const App: React.FC = () => {
42
  // --- ZUSTAND STORES ---
43
  const {
44
- currentUser, allUsers, leads, feedback,
45
  login, register, logout, updateUser, resetPassword, addPoints,
46
- addLead, updateLeadStatus, deleteLead, addFeedback
47
  } = useUserStore();
48
 
49
  const {
@@ -218,7 +219,7 @@ const App: React.FC = () => {
218
  updateUser(currentUser.id, { styleStats: stats });
219
 
220
  // Log generation event
221
- useUserStore.getState().addLog && useUserStore.getState().addLog({
222
  styleId,
223
  styleName: (TRANSLATIONS[language].styles as any)[styleId] || styleId,
224
  userId: currentUser.id,
@@ -617,6 +618,7 @@ const App: React.FC = () => {
617
  onUpdateUser={updateUser}
618
  showToast={showToast}
619
  onAdminLoginSuccess={handleAdminLoginSuccess}
 
620
  />
621
  </Suspense>
622
 
@@ -1059,4 +1061,4 @@ const App: React.FC = () => {
1059
  );
1060
  };
1061
 
1062
- export default App;
 
1
+
2
  import React, { useState, useRef, useEffect, Suspense } from 'react';
3
  import { Header } from './components/Header';
4
  import { ImageUploader } from './components/ImageUploader';
 
42
  const App: React.FC = () => {
43
  // --- ZUSTAND STORES ---
44
  const {
45
+ currentUser, allUsers, leads, feedback, logs,
46
  login, register, logout, updateUser, resetPassword, addPoints,
47
+ addLead, updateLeadStatus, deleteLead, addFeedback, addLog
48
  } = useUserStore();
49
 
50
  const {
 
219
  updateUser(currentUser.id, { styleStats: stats });
220
 
221
  // Log generation event
222
+ addLog({
223
  styleId,
224
  styleName: (TRANSLATIONS[language].styles as any)[styleId] || styleId,
225
  userId: currentUser.id,
 
618
  onUpdateUser={updateUser}
619
  showToast={showToast}
620
  onAdminLoginSuccess={handleAdminLoginSuccess}
621
+ logs={logs}
622
  />
623
  </Suspense>
624
 
 
1061
  );
1062
  };
1063
 
1064
+ export default App;
index.html CHANGED
@@ -15,17 +15,17 @@
15
  <script type="importmap">
16
  {
17
  "imports": {
18
- "react/": "https://aistudiocdn.com/react@^19.2.1/",
19
  "react": "https://aistudiocdn.com/react@^19.2.1",
20
- "zustand/": "https://aistudiocdn.com/zustand@^5.0.9/",
21
- "zustand": "https://aistudiocdn.com/zustand@^5.0.9",
22
- "vite": "https://aistudiocdn.com/vite@^7.2.6",
23
- "@google/genai": "https://aistudiocdn.com/@google/genai@^1.31.0",
24
- "@vitejs/plugin-react": "https://aistudiocdn.com/@vitejs/plugin-react@^5.1.1",
25
  "react-dom/": "https://aistudiocdn.com/react-dom@^19.2.1/",
 
 
26
  "lucide-react": "https://aistudiocdn.com/lucide-react@^0.556.0",
 
27
  "canvas-confetti": "https://aistudiocdn.com/canvas-confetti@^1.9.4",
28
- "jszip": "https://aistudiocdn.com/jszip@^3.10.1"
 
 
 
29
  }
30
  }
31
  </script>
 
15
  <script type="importmap">
16
  {
17
  "imports": {
 
18
  "react": "https://aistudiocdn.com/react@^19.2.1",
 
 
 
 
 
19
  "react-dom/": "https://aistudiocdn.com/react-dom@^19.2.1/",
20
+ "react/": "https://aistudiocdn.com/react@^19.2.1/",
21
+ "@google/genai": "https://aistudiocdn.com/@google/genai@^1.31.0",
22
  "lucide-react": "https://aistudiocdn.com/lucide-react@^0.556.0",
23
+ "jszip": "https://aistudiocdn.com/jszip@^3.10.1",
24
  "canvas-confetti": "https://aistudiocdn.com/canvas-confetti@^1.9.4",
25
+ "zustand": "https://aistudiocdn.com/zustand@^5.0.9",
26
+ "zustand/": "https://aistudiocdn.com/zustand@^5.0.9/",
27
+ "vite": "https://aistudiocdn.com/vite@^7.2.6",
28
+ "@vitejs/plugin-react": "https://aistudiocdn.com/@vitejs/plugin-react@^5.1.1"
29
  }
30
  }
31
  </script>
store.ts CHANGED
@@ -1,8 +1,7 @@
1
 
2
-
3
  import { create } from 'zustand';
4
  import { persist, createJSONStorage } from 'zustand/middleware';
5
- import { UserAccount, LeadData, AdminConfig, WeddingStyle, GeneratedResult, CompositionMode, Resolution, SubjectType, GenerationStatus, Language, PointHistory, FeedbackItem } from './types';
6
  import { TRANSLATIONS } from './constants/translations';
7
 
8
  // --- Default Configuration ---
@@ -36,6 +35,7 @@ interface UserState {
36
  leads: LeadData[];
37
  feedback: FeedbackItem[];
38
  guestFavorites: string[]; // NEW: Favorites for non-logged in users
 
39
 
40
  // Actions
41
  login: (phone: string, password?: string) => { success: boolean; msg: string };
@@ -44,7 +44,7 @@ interface UserState {
44
  updateUser: (id: string, updates: Partial<UserAccount>) => void;
45
  resetPassword: (phone: string, newPass: string) => boolean;
46
  addPoints: (amount: number, reason: string) => void;
47
- toggleFavorite: (styleId: string) => void; // NEW: Toggle favorite
48
 
49
  // Admin Actions
50
  addLead: (lead: LeadData) => void;
@@ -54,6 +54,9 @@ interface UserState {
54
 
55
  // Feedback Actions
56
  addFeedback: (item: FeedbackItem) => void;
 
 
 
57
  }
58
 
59
  export const useUserStore = create<UserState>()(
@@ -64,6 +67,7 @@ export const useUserStore = create<UserState>()(
64
  leads: [],
65
  feedback: [],
66
  guestFavorites: [],
 
67
 
68
  login: (phone, password) => {
69
  const { allUsers } = get();
@@ -171,7 +175,10 @@ export const useUserStore = create<UserState>()(
171
  setLeads: (leads) => set({ leads }),
172
 
173
  // Feedback Actions
174
- addFeedback: (item) => set(state => ({ feedback: [item, ...state.feedback] }))
 
 
 
175
  }),
176
  {
177
  name: 'rl_user_storage',
@@ -180,7 +187,8 @@ export const useUserStore = create<UserState>()(
180
  leads: state.leads,
181
  currentUser: state.currentUser,
182
  feedback: state.feedback,
183
- guestFavorites: state.guestFavorites // Persist guest favorites
 
184
  }),
185
  }
186
  )
@@ -289,7 +297,7 @@ interface GenerationState {
289
 
290
  setStatus: (status: GenerationStatus) => void;
291
  setProgress: (progress: GenerationState['progress']) => void;
292
- setErrorMsg: (msg: string | null) => void;
293
  addResult: (result: GeneratedResult) => void;
294
  setResults: (results: Record<string, GeneratedResult>) => void;
295
 
@@ -355,4 +363,4 @@ export const useGenerationStore = create<GenerationState>((set) => ({
355
  setScanStep: (step) => set({ scanStep: step }),
356
  setAnalysisData: (recs, result) => set({ recommendedStyleIds: recs, analysisResult: result }),
357
  stopScanning: () => set({ isScanning: false })
358
- }));
 
1
 
 
2
  import { create } from 'zustand';
3
  import { persist, createJSONStorage } from 'zustand/middleware';
4
+ import { UserAccount, LeadData, AdminConfig, WeddingStyle, GeneratedResult, CompositionMode, Resolution, SubjectType, GenerationStatus, Language, PointHistory, FeedbackItem, GenerationLog } from './types';
5
  import { TRANSLATIONS } from './constants/translations';
6
 
7
  // --- Default Configuration ---
 
35
  leads: LeadData[];
36
  feedback: FeedbackItem[];
37
  guestFavorites: string[]; // NEW: Favorites for non-logged in users
38
+ logs: GenerationLog[]; // NEW: Analytics Logs
39
 
40
  // Actions
41
  login: (phone: string, password?: string) => { success: boolean; msg: string };
 
44
  updateUser: (id: string, updates: Partial<UserAccount>) => void;
45
  resetPassword: (phone: string, newPass: string) => boolean;
46
  addPoints: (amount: number, reason: string) => void;
47
+ toggleFavorite: (styleId: string) => void;
48
 
49
  // Admin Actions
50
  addLead: (lead: LeadData) => void;
 
54
 
55
  // Feedback Actions
56
  addFeedback: (item: FeedbackItem) => void;
57
+
58
+ // Analytics Actions
59
+ addLog: (log: GenerationLog) => void;
60
  }
61
 
62
  export const useUserStore = create<UserState>()(
 
67
  leads: [],
68
  feedback: [],
69
  guestFavorites: [],
70
+ logs: [],
71
 
72
  login: (phone, password) => {
73
  const { allUsers } = get();
 
175
  setLeads: (leads) => set({ leads }),
176
 
177
  // Feedback Actions
178
+ addFeedback: (item) => set(state => ({ feedback: [item, ...state.feedback] })),
179
+
180
+ // Analytics
181
+ addLog: (log) => set(state => ({ logs: [log, ...state.logs].slice(0, 2000) })), // Keep last 2000 logs
182
  }),
183
  {
184
  name: 'rl_user_storage',
 
187
  leads: state.leads,
188
  currentUser: state.currentUser,
189
  feedback: state.feedback,
190
+ guestFavorites: state.guestFavorites,
191
+ logs: state.logs
192
  }),
193
  }
194
  )
 
297
 
298
  setStatus: (status: GenerationStatus) => void;
299
  setProgress: (progress: GenerationState['progress']) => void;
300
+ setErrorMsg: (msg) => set({ errorMsg: msg }),
301
  addResult: (result: GeneratedResult) => void;
302
  setResults: (results: Record<string, GeneratedResult>) => void;
303
 
 
363
  setScanStep: (step) => set({ scanStep: step }),
364
  setAnalysisData: (recs, result) => set({ recommendedStyleIds: recs, analysisResult: result }),
365
  stopScanning: () => set({ isScanning: false })
366
+ }));
types.ts CHANGED
@@ -1,5 +1,4 @@
1
 
2
-
3
  // Import React to support React.ReactNode type usage
4
  import React from 'react';
5
 
@@ -64,6 +63,16 @@ export interface LeadData {
64
  crmId?: string; // External ID
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
67
  export interface AdminConfig {
68
  promoText: string;
69
  promoEnds: string; // ISO Date string
@@ -148,4 +157,4 @@ export interface FeedbackItem {
148
  content: string;
149
  timestamp: number;
150
  contact?: string;
151
- }
 
1
 
 
2
  // Import React to support React.ReactNode type usage
3
  import React from 'react';
4
 
 
63
  crmId?: string; // External ID
64
  }
65
 
66
+ export interface GenerationLog {
67
+ styleId: string;
68
+ styleName: string;
69
+ userId: string;
70
+ timestamp: number;
71
+ ip: string;
72
+ location: string;
73
+ device: string;
74
+ }
75
+
76
  export interface AdminConfig {
77
  promoText: string;
78
  promoEnds: string; // ISO Date string
 
157
  content: string;
158
  timestamp: number;
159
  contact?: string;
160
+ }