Update skills: add website-creator, mql-developer, ecommerce-astro
Changes: - Add FAL_KEY and GEMINI_API_KEY to .env.example - Update picture-it to use ~/.config/opencode/.env (unified creds) - Remove shodh-memory skill (no longer used) - Remove alphaear-* skills (deprecated) - Remove thai-frontend-dev skill (replaced by website-creator) - Remove theme-factory skill - Add mql-developer skill (MQL5 trading) - Add ecommerce-astro skill (Astro e-commerce) - Add website-creator skill (Next.js + Payload CMS) - Update install script for new skills
This commit is contained in:
113
skills/ecommerce-astro/scripts/templates/src/stores/auth.ts
Normal file
113
skills/ecommerce-astro/scripts/templates/src/stores/auth.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
interface User {
|
||||
id: string;
|
||||
email: string;
|
||||
name?: string;
|
||||
role: 'customer' | 'vendor' | 'admin';
|
||||
avatar_url?: string;
|
||||
}
|
||||
|
||||
interface AuthStore {
|
||||
user: User | null;
|
||||
token: string | null;
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
|
||||
login: (email: string, password: string) => Promise<boolean>;
|
||||
register: (data: { email: string; password: string; name: string }) => Promise<boolean>;
|
||||
logout: () => Promise<void>;
|
||||
fetchUser: () => Promise<void>;
|
||||
clearError: () => void;
|
||||
}
|
||||
|
||||
export const useAuthStore = create<AuthStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
user: null,
|
||||
token: null,
|
||||
isLoading: false,
|
||||
error: null,
|
||||
|
||||
login: async (email, password) => {
|
||||
set({ isLoading: true, error: null });
|
||||
try {
|
||||
const res = await fetch('/api/auth/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, password })
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const data = await res.json();
|
||||
set({ error: data.error || 'Login failed' });
|
||||
return false;
|
||||
}
|
||||
|
||||
const { user, token } = await res.json();
|
||||
set({ user, token, isLoading: false });
|
||||
return true;
|
||||
} catch (error) {
|
||||
set({ error: 'Network error', isLoading: false });
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
register: async (data) => {
|
||||
set({ isLoading: true, error: null });
|
||||
try {
|
||||
const res = await fetch('/api/auth/register', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
const error = await res.json();
|
||||
set({ error: error.error || 'Registration failed' });
|
||||
return false;
|
||||
}
|
||||
|
||||
const { user, token } = await res.json();
|
||||
set({ user, token, isLoading: false });
|
||||
return true;
|
||||
} catch (error) {
|
||||
set({ error: 'Network error', isLoading: false });
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
logout: async () => {
|
||||
await fetch('/api/auth/logout', { method: 'POST' });
|
||||
set({ user: null, token: null });
|
||||
},
|
||||
|
||||
fetchUser: async () => {
|
||||
const token = get().token;
|
||||
if (!token) return;
|
||||
|
||||
try {
|
||||
const res = await fetch('/api/auth/me', {
|
||||
headers: { 'Authorization': `Bearer ${token}` }
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
const { user } = await res.json();
|
||||
set({ user });
|
||||
} else {
|
||||
set({ user: null, token: null });
|
||||
}
|
||||
} catch {
|
||||
set({ user: null, token: null });
|
||||
}
|
||||
},
|
||||
|
||||
clearError: () => set({ error: null })
|
||||
}),
|
||||
{
|
||||
name: 'auth-storage',
|
||||
partialize: (state) => ({ user: state.user, token: state.token })
|
||||
}
|
||||
)
|
||||
);
|
||||
Reference in New Issue
Block a user