@braintwopoint0/playback-commons 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/index.d.ts +85 -0
- package/dist/auth/index.js +378 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/supabase/index.d.ts +5 -0
- package/dist/supabase/index.js +14 -0
- package/dist/supabase/index.js.map +1 -0
- package/dist/ui/index.d.ts +103 -0
- package/dist/ui/index.js +728 -0
- package/dist/ui/index.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.js +44 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { User, Session, AuthError } from '@supabase/supabase-js';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
declare function validateEmail(email: string): boolean;
|
|
5
|
+
declare function validatePassword(password: string): {
|
|
6
|
+
isValid: boolean;
|
|
7
|
+
errors: string[];
|
|
8
|
+
};
|
|
9
|
+
declare function validateUsername(username: string): {
|
|
10
|
+
isValid: boolean;
|
|
11
|
+
errors: string[];
|
|
12
|
+
};
|
|
13
|
+
declare function hasRole(user: User | null, role: string): boolean;
|
|
14
|
+
declare function hasAnyRole(user: User | null, roles: string[]): boolean;
|
|
15
|
+
declare function isPlayer(user: User | null): boolean;
|
|
16
|
+
declare function isCoach(user: User | null): boolean;
|
|
17
|
+
declare function isScout(user: User | null): boolean;
|
|
18
|
+
declare function isFan(user: User | null): boolean;
|
|
19
|
+
declare function getAuthErrorMessage(error: any): string;
|
|
20
|
+
|
|
21
|
+
interface UserProfile {
|
|
22
|
+
id: string;
|
|
23
|
+
user_id: string;
|
|
24
|
+
username: string;
|
|
25
|
+
email: string | null;
|
|
26
|
+
full_name: string | null;
|
|
27
|
+
bio: string | null;
|
|
28
|
+
avatar_url: string | null;
|
|
29
|
+
cover_image_url: string | null;
|
|
30
|
+
date_of_birth: string | null;
|
|
31
|
+
height_cm: number | null;
|
|
32
|
+
weight_kg: number | null;
|
|
33
|
+
nationality: string | null;
|
|
34
|
+
location: string | null;
|
|
35
|
+
phone: string | null;
|
|
36
|
+
website: string | null;
|
|
37
|
+
social_links: any;
|
|
38
|
+
is_public: boolean | null;
|
|
39
|
+
created_at: string | null;
|
|
40
|
+
updated_at: string | null;
|
|
41
|
+
}
|
|
42
|
+
interface ProfileState {
|
|
43
|
+
data: UserProfile | null;
|
|
44
|
+
loading: boolean;
|
|
45
|
+
error: string | null;
|
|
46
|
+
lastFetched: number | null;
|
|
47
|
+
}
|
|
48
|
+
interface AuthContextType {
|
|
49
|
+
user: User | null;
|
|
50
|
+
session: Session | null;
|
|
51
|
+
loading: boolean;
|
|
52
|
+
profile: ProfileState;
|
|
53
|
+
isOnboardingComplete: boolean;
|
|
54
|
+
signUp: (email: string, password: string, metadata?: Record<string, any>) => Promise<{
|
|
55
|
+
data: any;
|
|
56
|
+
error: AuthError | null;
|
|
57
|
+
}>;
|
|
58
|
+
signIn: (email: string, password: string) => Promise<{
|
|
59
|
+
error: AuthError | null;
|
|
60
|
+
}>;
|
|
61
|
+
signOut: () => Promise<{
|
|
62
|
+
error: AuthError | null;
|
|
63
|
+
}>;
|
|
64
|
+
resetPassword: (email: string) => Promise<{
|
|
65
|
+
error: AuthError | null;
|
|
66
|
+
}>;
|
|
67
|
+
refreshProfile: (force?: boolean) => Promise<void>;
|
|
68
|
+
updateProfile: (updates: Partial<UserProfile>) => void;
|
|
69
|
+
}
|
|
70
|
+
declare function AuthProvider({ children, }: {
|
|
71
|
+
children: React.ReactNode;
|
|
72
|
+
}): react_jsx_runtime.JSX.Element;
|
|
73
|
+
declare function useAuth(): AuthContextType;
|
|
74
|
+
declare function useProfile(): {
|
|
75
|
+
profile: ProfileState;
|
|
76
|
+
refreshProfile: (force?: boolean) => Promise<void>;
|
|
77
|
+
updateProfile: (updates: Partial<UserProfile>) => void;
|
|
78
|
+
};
|
|
79
|
+
declare function useOnboardingStatus(): {
|
|
80
|
+
isComplete: boolean;
|
|
81
|
+
loading: boolean;
|
|
82
|
+
error: string | null;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export { AuthProvider, getAuthErrorMessage, hasAnyRole, hasRole, isCoach, isFan, isPlayer, isScout, useAuth, useOnboardingStatus, useProfile, validateEmail, validatePassword, validateUsername };
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/auth/shared.ts
|
|
4
|
+
function validateEmail(email) {
|
|
5
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
6
|
+
return emailRegex.test(email);
|
|
7
|
+
}
|
|
8
|
+
function validatePassword(password) {
|
|
9
|
+
const errors = [];
|
|
10
|
+
if (password.length < 8) {
|
|
11
|
+
errors.push("Password must be at least 8 characters long");
|
|
12
|
+
}
|
|
13
|
+
if (!/(?=.*[a-z])/.test(password)) {
|
|
14
|
+
errors.push("Password must contain at least one lowercase letter");
|
|
15
|
+
}
|
|
16
|
+
if (!/(?=.*[A-Z])/.test(password)) {
|
|
17
|
+
errors.push("Password must contain at least one uppercase letter");
|
|
18
|
+
}
|
|
19
|
+
if (!/(?=.*\d)/.test(password)) {
|
|
20
|
+
errors.push("Password must contain at least one number");
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
isValid: errors.length === 0,
|
|
24
|
+
errors
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function validateUsername(username) {
|
|
28
|
+
const errors = [];
|
|
29
|
+
if (username.length < 3) {
|
|
30
|
+
errors.push("Username must be at least 3 characters long");
|
|
31
|
+
}
|
|
32
|
+
if (username.length > 30) {
|
|
33
|
+
errors.push("Username cannot be longer than 30 characters");
|
|
34
|
+
}
|
|
35
|
+
if (!/^[a-zA-Z0-9_-]+$/.test(username)) {
|
|
36
|
+
errors.push(
|
|
37
|
+
"Username can only contain letters, numbers, underscores, and hyphens"
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
isValid: errors.length === 0,
|
|
42
|
+
errors
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function hasRole(user, role) {
|
|
46
|
+
if (!user) return false;
|
|
47
|
+
return user.user_metadata?.role === role;
|
|
48
|
+
}
|
|
49
|
+
function hasAnyRole(user, roles) {
|
|
50
|
+
if (!user) return false;
|
|
51
|
+
return roles.includes(user.user_metadata?.role);
|
|
52
|
+
}
|
|
53
|
+
function isPlayer(user) {
|
|
54
|
+
return hasRole(user, "player");
|
|
55
|
+
}
|
|
56
|
+
function isCoach(user) {
|
|
57
|
+
return hasRole(user, "coach");
|
|
58
|
+
}
|
|
59
|
+
function isScout(user) {
|
|
60
|
+
return hasRole(user, "scout");
|
|
61
|
+
}
|
|
62
|
+
function isFan(user) {
|
|
63
|
+
return hasRole(user, "fan");
|
|
64
|
+
}
|
|
65
|
+
function getAuthErrorMessage(error) {
|
|
66
|
+
if (!error) return "An unknown error occurred";
|
|
67
|
+
const message = error.message || error.error_description || error.toString();
|
|
68
|
+
const errorMappings = {
|
|
69
|
+
"Invalid login credentials": "Invalid email or password. Please check your credentials and try again.",
|
|
70
|
+
"Email not confirmed": "Please check your email and click the confirmation link before signing in.",
|
|
71
|
+
"User already registered": "An account with this email address already exists. Please sign in instead.",
|
|
72
|
+
"Password should be at least 6 characters": "Password must be at least 6 characters long.",
|
|
73
|
+
"Signup requires a valid password": "Please provide a valid password.",
|
|
74
|
+
"Invalid email": "Please provide a valid email address.",
|
|
75
|
+
"Email rate limit exceeded": "Too many emails sent. Please wait before requesting another.",
|
|
76
|
+
'duplicate key value violates unique constraint "profiles_username_key"': "This username is already taken. Please choose a different username."
|
|
77
|
+
};
|
|
78
|
+
return errorMappings[message] || message;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// src/auth/context.tsx
|
|
82
|
+
import {
|
|
83
|
+
createContext,
|
|
84
|
+
useContext,
|
|
85
|
+
useEffect,
|
|
86
|
+
useState,
|
|
87
|
+
useMemo,
|
|
88
|
+
useCallback
|
|
89
|
+
} from "react";
|
|
90
|
+
import { useRouter } from "next/navigation";
|
|
91
|
+
|
|
92
|
+
// src/supabase/client.ts
|
|
93
|
+
import { createBrowserClient } from "@supabase/ssr";
|
|
94
|
+
function createClient() {
|
|
95
|
+
return createBrowserClient(
|
|
96
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
97
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/auth/context.tsx
|
|
102
|
+
import { jsx } from "react/jsx-runtime";
|
|
103
|
+
var AuthContext = createContext(void 0);
|
|
104
|
+
var CACHE_TIMEOUT = 5 * 60 * 1e3;
|
|
105
|
+
function AuthProvider({
|
|
106
|
+
children
|
|
107
|
+
}) {
|
|
108
|
+
const [user, setUser] = useState(null);
|
|
109
|
+
const [session, setSession] = useState(null);
|
|
110
|
+
const [loading, setLoading] = useState(true);
|
|
111
|
+
const [profile, setProfile] = useState({
|
|
112
|
+
data: null,
|
|
113
|
+
loading: false,
|
|
114
|
+
error: null,
|
|
115
|
+
lastFetched: null
|
|
116
|
+
});
|
|
117
|
+
const router = useRouter();
|
|
118
|
+
const supabase = useMemo(() => createClient(), []);
|
|
119
|
+
const isOnboardingComplete = useMemo(() => {
|
|
120
|
+
return !!profile.data;
|
|
121
|
+
}, [profile.data]);
|
|
122
|
+
const fetchProfile = useCallback(
|
|
123
|
+
async (userId) => {
|
|
124
|
+
try {
|
|
125
|
+
const { data: profileData, error: profileError } = await supabase.from("profiles").select("*").eq("user_id", userId).single();
|
|
126
|
+
if (profileError) throw profileError;
|
|
127
|
+
return { data: profileData, error: null };
|
|
128
|
+
} catch (error) {
|
|
129
|
+
return {
|
|
130
|
+
data: null,
|
|
131
|
+
error: error instanceof Error ? error.message : "Failed to fetch profile"
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
[supabase]
|
|
136
|
+
);
|
|
137
|
+
const refreshProfile = useCallback(
|
|
138
|
+
async (force = false) => {
|
|
139
|
+
if (!user) {
|
|
140
|
+
setProfile({
|
|
141
|
+
data: null,
|
|
142
|
+
loading: false,
|
|
143
|
+
error: null,
|
|
144
|
+
lastFetched: null
|
|
145
|
+
});
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const now = Date.now();
|
|
149
|
+
const isCacheValid = profile.lastFetched && now - profile.lastFetched < CACHE_TIMEOUT;
|
|
150
|
+
if (!force && isCacheValid && profile.data) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
setProfile((prev) => ({ ...prev, loading: true, error: null }));
|
|
154
|
+
try {
|
|
155
|
+
const result = await fetchProfile(user.id);
|
|
156
|
+
setProfile({
|
|
157
|
+
data: result.data,
|
|
158
|
+
loading: false,
|
|
159
|
+
error: result.error,
|
|
160
|
+
lastFetched: now
|
|
161
|
+
});
|
|
162
|
+
} catch (error) {
|
|
163
|
+
setProfile((prev) => ({
|
|
164
|
+
...prev,
|
|
165
|
+
loading: false,
|
|
166
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
167
|
+
}));
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
[user, profile.lastFetched, profile.data, fetchProfile]
|
|
171
|
+
);
|
|
172
|
+
const updateProfile = useCallback((updates) => {
|
|
173
|
+
setProfile((prev) => ({
|
|
174
|
+
...prev,
|
|
175
|
+
data: prev.data ? { ...prev.data, ...updates } : null
|
|
176
|
+
}));
|
|
177
|
+
}, []);
|
|
178
|
+
useEffect(() => {
|
|
179
|
+
const initializeAuth = async () => {
|
|
180
|
+
try {
|
|
181
|
+
const {
|
|
182
|
+
data: { session: session2 },
|
|
183
|
+
error
|
|
184
|
+
} = await supabase.auth.getSession();
|
|
185
|
+
if (error) {
|
|
186
|
+
console.error("Error getting session:", error);
|
|
187
|
+
} else {
|
|
188
|
+
setSession(session2);
|
|
189
|
+
setUser(session2?.user ?? null);
|
|
190
|
+
if (session2?.user) {
|
|
191
|
+
setProfile({
|
|
192
|
+
data: null,
|
|
193
|
+
loading: false,
|
|
194
|
+
error: null,
|
|
195
|
+
lastFetched: null
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
} catch (error) {
|
|
200
|
+
console.error("Session initialization error:", error);
|
|
201
|
+
} finally {
|
|
202
|
+
setLoading(false);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
initializeAuth();
|
|
206
|
+
}, [supabase.auth]);
|
|
207
|
+
useEffect(() => {
|
|
208
|
+
if (!loading && user && !profile.data && !profile.loading) {
|
|
209
|
+
const loadProfile = async () => {
|
|
210
|
+
setProfile((prev) => ({ ...prev, loading: true, error: null }));
|
|
211
|
+
try {
|
|
212
|
+
const result = await fetchProfile(user.id);
|
|
213
|
+
setProfile({
|
|
214
|
+
data: result.data,
|
|
215
|
+
loading: false,
|
|
216
|
+
error: result.error,
|
|
217
|
+
lastFetched: Date.now()
|
|
218
|
+
});
|
|
219
|
+
} catch (error) {
|
|
220
|
+
setProfile((prev) => ({
|
|
221
|
+
...prev,
|
|
222
|
+
loading: false,
|
|
223
|
+
error: error instanceof Error ? error.message : "Unknown error"
|
|
224
|
+
}));
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
loadProfile();
|
|
228
|
+
}
|
|
229
|
+
}, [loading, user, profile.data, profile.loading, fetchProfile]);
|
|
230
|
+
useEffect(() => {
|
|
231
|
+
const {
|
|
232
|
+
data: { subscription }
|
|
233
|
+
} = supabase.auth.onAuthStateChange(async (event, session2) => {
|
|
234
|
+
setSession(session2);
|
|
235
|
+
setUser(session2?.user ?? null);
|
|
236
|
+
setLoading(false);
|
|
237
|
+
if (session2?.user) {
|
|
238
|
+
setProfile({
|
|
239
|
+
data: null,
|
|
240
|
+
loading: false,
|
|
241
|
+
error: null,
|
|
242
|
+
lastFetched: null
|
|
243
|
+
});
|
|
244
|
+
} else {
|
|
245
|
+
setProfile({
|
|
246
|
+
data: null,
|
|
247
|
+
loading: false,
|
|
248
|
+
error: null,
|
|
249
|
+
lastFetched: null
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
if (event === "SIGNED_IN") {
|
|
253
|
+
router.refresh();
|
|
254
|
+
} else if (event === "SIGNED_OUT") {
|
|
255
|
+
router.push("/");
|
|
256
|
+
router.refresh();
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
return () => subscription.unsubscribe();
|
|
260
|
+
}, [supabase.auth, router]);
|
|
261
|
+
const signUp = useCallback(
|
|
262
|
+
async (email, password, metadata) => {
|
|
263
|
+
setLoading(true);
|
|
264
|
+
try {
|
|
265
|
+
const { data, error } = await supabase.auth.signUp({
|
|
266
|
+
email,
|
|
267
|
+
password,
|
|
268
|
+
options: {
|
|
269
|
+
data: metadata,
|
|
270
|
+
emailRedirectTo: `${window.location.origin}/auth/callback`
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
return { data, error };
|
|
274
|
+
} finally {
|
|
275
|
+
setLoading(false);
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
[supabase.auth]
|
|
279
|
+
);
|
|
280
|
+
const signIn = useCallback(
|
|
281
|
+
async (email, password) => {
|
|
282
|
+
setLoading(true);
|
|
283
|
+
try {
|
|
284
|
+
const { error } = await supabase.auth.signInWithPassword({
|
|
285
|
+
email,
|
|
286
|
+
password
|
|
287
|
+
});
|
|
288
|
+
return { error };
|
|
289
|
+
} finally {
|
|
290
|
+
setLoading(false);
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
[supabase.auth]
|
|
294
|
+
);
|
|
295
|
+
const signOut = useCallback(async () => {
|
|
296
|
+
setLoading(true);
|
|
297
|
+
try {
|
|
298
|
+
const { error } = await supabase.auth.signOut();
|
|
299
|
+
return { error };
|
|
300
|
+
} finally {
|
|
301
|
+
setLoading(false);
|
|
302
|
+
}
|
|
303
|
+
}, [supabase.auth]);
|
|
304
|
+
const resetPassword = useCallback(
|
|
305
|
+
async (email) => {
|
|
306
|
+
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
|
307
|
+
redirectTo: `${window.location.origin}/auth/reset-password`
|
|
308
|
+
});
|
|
309
|
+
return { error };
|
|
310
|
+
},
|
|
311
|
+
[supabase.auth]
|
|
312
|
+
);
|
|
313
|
+
const value = useMemo(
|
|
314
|
+
() => ({
|
|
315
|
+
user,
|
|
316
|
+
session,
|
|
317
|
+
loading,
|
|
318
|
+
profile,
|
|
319
|
+
isOnboardingComplete,
|
|
320
|
+
signUp,
|
|
321
|
+
signIn,
|
|
322
|
+
signOut,
|
|
323
|
+
resetPassword,
|
|
324
|
+
refreshProfile,
|
|
325
|
+
updateProfile
|
|
326
|
+
}),
|
|
327
|
+
[
|
|
328
|
+
user,
|
|
329
|
+
session,
|
|
330
|
+
loading,
|
|
331
|
+
profile,
|
|
332
|
+
isOnboardingComplete,
|
|
333
|
+
refreshProfile,
|
|
334
|
+
updateProfile,
|
|
335
|
+
signIn,
|
|
336
|
+
signOut,
|
|
337
|
+
resetPassword,
|
|
338
|
+
signUp
|
|
339
|
+
]
|
|
340
|
+
);
|
|
341
|
+
return /* @__PURE__ */ jsx(AuthContext.Provider, { value, children });
|
|
342
|
+
}
|
|
343
|
+
function useAuth() {
|
|
344
|
+
const context = useContext(AuthContext);
|
|
345
|
+
if (context === void 0) {
|
|
346
|
+
throw new Error("useAuth must be used within an AuthProvider");
|
|
347
|
+
}
|
|
348
|
+
return context;
|
|
349
|
+
}
|
|
350
|
+
function useProfile() {
|
|
351
|
+
const { profile, refreshProfile, updateProfile } = useAuth();
|
|
352
|
+
return { profile, refreshProfile, updateProfile };
|
|
353
|
+
}
|
|
354
|
+
function useOnboardingStatus() {
|
|
355
|
+
const { isOnboardingComplete, profile } = useAuth();
|
|
356
|
+
return {
|
|
357
|
+
isComplete: isOnboardingComplete,
|
|
358
|
+
loading: profile.loading,
|
|
359
|
+
error: profile.error
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
export {
|
|
363
|
+
AuthProvider,
|
|
364
|
+
getAuthErrorMessage,
|
|
365
|
+
hasAnyRole,
|
|
366
|
+
hasRole,
|
|
367
|
+
isCoach,
|
|
368
|
+
isFan,
|
|
369
|
+
isPlayer,
|
|
370
|
+
isScout,
|
|
371
|
+
useAuth,
|
|
372
|
+
useOnboardingStatus,
|
|
373
|
+
useProfile,
|
|
374
|
+
validateEmail,
|
|
375
|
+
validatePassword,
|
|
376
|
+
validateUsername
|
|
377
|
+
};
|
|
378
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/auth/shared.ts","../../src/auth/context.tsx","../../src/supabase/client.ts"],"sourcesContent":["import { User } from '@supabase/supabase-js'\n\nexport function validateEmail(email: string): boolean {\n const emailRegex = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n return emailRegex.test(email)\n}\n\nexport function validatePassword(password: string): {\n isValid: boolean\n errors: string[]\n} {\n const errors: string[] = []\n\n if (password.length < 8) {\n errors.push('Password must be at least 8 characters long')\n }\n\n if (!/(?=.*[a-z])/.test(password)) {\n errors.push('Password must contain at least one lowercase letter')\n }\n\n if (!/(?=.*[A-Z])/.test(password)) {\n errors.push('Password must contain at least one uppercase letter')\n }\n\n if (!/(?=.*\\d)/.test(password)) {\n errors.push('Password must contain at least one number')\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n }\n}\n\nexport function validateUsername(username: string): {\n isValid: boolean\n errors: string[]\n} {\n const errors: string[] = []\n\n if (username.length < 3) {\n errors.push('Username must be at least 3 characters long')\n }\n\n if (username.length > 30) {\n errors.push('Username cannot be longer than 30 characters')\n }\n\n if (!/^[a-zA-Z0-9_-]+$/.test(username)) {\n errors.push(\n 'Username can only contain letters, numbers, underscores, and hyphens'\n )\n }\n\n return {\n isValid: errors.length === 0,\n errors,\n }\n}\n\nexport function hasRole(user: User | null, role: string): boolean {\n if (!user) return false\n return user.user_metadata?.role === role\n}\n\nexport function hasAnyRole(user: User | null, roles: string[]): boolean {\n if (!user) return false\n return roles.includes(user.user_metadata?.role)\n}\n\nexport function isPlayer(user: User | null): boolean {\n return hasRole(user, 'player')\n}\n\nexport function isCoach(user: User | null): boolean {\n return hasRole(user, 'coach')\n}\n\nexport function isScout(user: User | null): boolean {\n return hasRole(user, 'scout')\n}\n\nexport function isFan(user: User | null): boolean {\n return hasRole(user, 'fan')\n}\n\nexport function getAuthErrorMessage(error: any): string {\n if (!error) return 'An unknown error occurred'\n\n const message = error.message || error.error_description || error.toString()\n\n const errorMappings: Record<string, string> = {\n 'Invalid login credentials':\n 'Invalid email or password. Please check your credentials and try again.',\n 'Email not confirmed':\n 'Please check your email and click the confirmation link before signing in.',\n 'User already registered':\n 'An account with this email address already exists. Please sign in instead.',\n 'Password should be at least 6 characters':\n 'Password must be at least 6 characters long.',\n 'Signup requires a valid password': 'Please provide a valid password.',\n 'Invalid email': 'Please provide a valid email address.',\n 'Email rate limit exceeded':\n 'Too many emails sent. Please wait before requesting another.',\n 'duplicate key value violates unique constraint \"profiles_username_key\"':\n 'This username is already taken. Please choose a different username.',\n }\n\n return errorMappings[message] || message\n}\n","'use client'\n\nimport {\n createContext,\n useContext,\n useEffect,\n useState,\n useMemo,\n useCallback,\n} from 'react'\nimport { User, Session, AuthError } from '@supabase/supabase-js'\nimport { useRouter } from 'next/navigation'\nimport { createClient } from '../supabase/client'\n\ninterface UserProfile {\n id: string\n user_id: string\n username: string\n email: string | null\n full_name: string | null\n bio: string | null\n avatar_url: string | null\n cover_image_url: string | null\n date_of_birth: string | null\n height_cm: number | null\n weight_kg: number | null\n nationality: string | null\n location: string | null\n phone: string | null\n website: string | null\n social_links: any\n is_public: boolean | null\n created_at: string | null\n updated_at: string | null\n}\n\ninterface ProfileState {\n data: UserProfile | null\n loading: boolean\n error: string | null\n lastFetched: number | null\n}\n\ninterface AuthContextType {\n user: User | null\n session: Session | null\n loading: boolean\n profile: ProfileState\n isOnboardingComplete: boolean\n signUp: (\n email: string,\n password: string,\n metadata?: Record<string, any>\n ) => Promise<{ data: any; error: AuthError | null }>\n signIn: (\n email: string,\n password: string\n ) => Promise<{ error: AuthError | null }>\n signOut: () => Promise<{ error: AuthError | null }>\n resetPassword: (email: string) => Promise<{ error: AuthError | null }>\n refreshProfile: (force?: boolean) => Promise<void>\n updateProfile: (updates: Partial<UserProfile>) => void\n}\n\nconst AuthContext = createContext<AuthContextType | undefined>(undefined)\n\nconst CACHE_TIMEOUT = 5 * 60 * 1000\n\nexport function AuthProvider({\n children,\n}: {\n children: React.ReactNode\n}) {\n const [user, setUser] = useState<User | null>(null)\n const [session, setSession] = useState<Session | null>(null)\n const [loading, setLoading] = useState(true)\n const [profile, setProfile] = useState<ProfileState>({\n data: null,\n loading: false,\n error: null,\n lastFetched: null,\n })\n\n const router = useRouter()\n const supabase = useMemo(() => createClient(), [])\n\n const isOnboardingComplete = useMemo(() => {\n return !!profile.data\n }, [profile.data])\n\n const fetchProfile = useCallback(\n async (userId: string) => {\n try {\n const { data: profileData, error: profileError } = await supabase\n .from('profiles')\n .select('*')\n .eq('user_id', userId)\n .single()\n\n if (profileError) throw profileError\n\n return { data: profileData, error: null }\n } catch (error) {\n return {\n data: null,\n error:\n error instanceof Error ? error.message : 'Failed to fetch profile',\n }\n }\n },\n [supabase]\n )\n\n const refreshProfile = useCallback(\n async (force = false) => {\n if (!user) {\n setProfile({\n data: null,\n loading: false,\n error: null,\n lastFetched: null,\n })\n return\n }\n\n const now = Date.now()\n const isCacheValid =\n profile.lastFetched && now - profile.lastFetched < CACHE_TIMEOUT\n\n if (!force && isCacheValid && profile.data) {\n return\n }\n\n setProfile((prev) => ({ ...prev, loading: true, error: null }))\n\n try {\n const result = await fetchProfile(user.id)\n setProfile({\n data: result.data,\n loading: false,\n error: result.error,\n lastFetched: now,\n })\n } catch (error) {\n setProfile((prev) => ({\n ...prev,\n loading: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n }))\n }\n },\n [user, profile.lastFetched, profile.data, fetchProfile]\n )\n\n const updateProfile = useCallback((updates: Partial<UserProfile>) => {\n setProfile((prev) => ({\n ...prev,\n data: prev.data ? { ...prev.data, ...updates } : null,\n }))\n }, [])\n\n useEffect(() => {\n const initializeAuth = async () => {\n try {\n const {\n data: { session },\n error,\n } = await supabase.auth.getSession()\n\n if (error) {\n console.error('Error getting session:', error)\n } else {\n setSession(session)\n setUser(session?.user ?? null)\n\n if (session?.user) {\n setProfile({\n data: null,\n loading: false,\n error: null,\n lastFetched: null,\n })\n }\n }\n } catch (error) {\n console.error('Session initialization error:', error)\n } finally {\n setLoading(false)\n }\n }\n\n initializeAuth()\n }, [supabase.auth])\n\n useEffect(() => {\n if (!loading && user && !profile.data && !profile.loading) {\n const loadProfile = async () => {\n setProfile((prev) => ({ ...prev, loading: true, error: null }))\n try {\n const result = await fetchProfile(user.id)\n setProfile({\n data: result.data,\n loading: false,\n error: result.error,\n lastFetched: Date.now(),\n })\n } catch (error) {\n setProfile((prev) => ({\n ...prev,\n loading: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n }))\n }\n }\n loadProfile()\n }\n }, [loading, user, profile.data, profile.loading, fetchProfile])\n\n useEffect(() => {\n const {\n data: { subscription },\n } = supabase.auth.onAuthStateChange(async (event, session) => {\n setSession(session)\n setUser(session?.user ?? null)\n setLoading(false)\n\n if (session?.user) {\n setProfile({\n data: null,\n loading: false,\n error: null,\n lastFetched: null,\n })\n } else {\n setProfile({\n data: null,\n loading: false,\n error: null,\n lastFetched: null,\n })\n }\n\n if (event === 'SIGNED_IN') {\n router.refresh()\n } else if (event === 'SIGNED_OUT') {\n router.push('/')\n router.refresh()\n }\n })\n\n return () => subscription.unsubscribe()\n }, [supabase.auth, router])\n\n const signUp = useCallback(\n async (email: string, password: string, metadata?: Record<string, any>) => {\n setLoading(true)\n try {\n const { data, error } = await supabase.auth.signUp({\n email,\n password,\n options: {\n data: metadata,\n emailRedirectTo: `${window.location.origin}/auth/callback`,\n },\n })\n return { data, error }\n } finally {\n setLoading(false)\n }\n },\n [supabase.auth]\n )\n\n const signIn = useCallback(\n async (email: string, password: string) => {\n setLoading(true)\n try {\n const { error } = await supabase.auth.signInWithPassword({\n email,\n password,\n })\n return { error }\n } finally {\n setLoading(false)\n }\n },\n [supabase.auth]\n )\n\n const signOut = useCallback(async () => {\n setLoading(true)\n try {\n const { error } = await supabase.auth.signOut()\n return { error }\n } finally {\n setLoading(false)\n }\n }, [supabase.auth])\n\n const resetPassword = useCallback(\n async (email: string) => {\n const { error } = await supabase.auth.resetPasswordForEmail(email, {\n redirectTo: `${window.location.origin}/auth/reset-password`,\n })\n return { error }\n },\n [supabase.auth]\n )\n\n const value = useMemo(\n () => ({\n user,\n session,\n loading,\n profile,\n isOnboardingComplete,\n signUp,\n signIn,\n signOut,\n resetPassword,\n refreshProfile,\n updateProfile,\n }),\n [\n user,\n session,\n loading,\n profile,\n isOnboardingComplete,\n refreshProfile,\n updateProfile,\n signIn,\n signOut,\n resetPassword,\n signUp,\n ]\n )\n\n return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>\n}\n\nexport function useAuth() {\n const context = useContext(AuthContext)\n if (context === undefined) {\n throw new Error('useAuth must be used within an AuthProvider')\n }\n return context\n}\n\nexport function useProfile() {\n const { profile, refreshProfile, updateProfile } = useAuth()\n return { profile, refreshProfile, updateProfile }\n}\n\nexport function useOnboardingStatus() {\n const { isOnboardingComplete, profile } = useAuth()\n return {\n isComplete: isOnboardingComplete,\n loading: profile.loading,\n error: profile.error,\n }\n}\n","import { createBrowserClient } from '@supabase/ssr'\n\nexport function createClient() {\n return createBrowserClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!\n )\n}\n"],"mappings":"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","names":["session"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/supabase/client.ts
|
|
4
|
+
import { createBrowserClient } from "@supabase/ssr";
|
|
5
|
+
function createClient() {
|
|
6
|
+
return createBrowserClient(
|
|
7
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL,
|
|
8
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
createClient
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/supabase/client.ts"],"sourcesContent":["import { createBrowserClient } from '@supabase/ssr'\n\nexport function createClient() {\n return createBrowserClient(\n process.env.NEXT_PUBLIC_SUPABASE_URL!,\n process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!\n )\n}\n"],"mappings":";;;AAAA,SAAS,2BAA2B;AAE7B,SAAS,eAAe;AAC7B,SAAO;AAAA,IACL,QAAQ,IAAI;AAAA,IACZ,QAAQ,IAAI;AAAA,EACd;AACF;","names":[]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
2
|
+
import * as React$1 from 'react';
|
|
3
|
+
import React__default from 'react';
|
|
4
|
+
import { VariantProps } from 'class-variance-authority';
|
|
5
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
6
|
+
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
7
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
8
|
+
|
|
9
|
+
declare const buttonVariants: (props?: ({
|
|
10
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
|
|
11
|
+
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
12
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
13
|
+
interface ButtonProps extends React$1.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
14
|
+
asChild?: boolean;
|
|
15
|
+
}
|
|
16
|
+
declare const Button: React$1.ForwardRefExoticComponent<ButtonProps & React$1.RefAttributes<HTMLButtonElement>>;
|
|
17
|
+
|
|
18
|
+
declare const Card: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
|
|
19
|
+
declare const CardHeader: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
|
|
20
|
+
declare const CardTitle: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLHeadingElement> & React$1.RefAttributes<HTMLParagraphElement>>;
|
|
21
|
+
declare const CardDescription: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLParagraphElement> & React$1.RefAttributes<HTMLParagraphElement>>;
|
|
22
|
+
declare const CardContent: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
|
|
23
|
+
declare const CardFooter: React$1.ForwardRefExoticComponent<React$1.HTMLAttributes<HTMLDivElement> & React$1.RefAttributes<HTMLDivElement>>;
|
|
24
|
+
|
|
25
|
+
declare const badgeVariants: (props?: ({
|
|
26
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | null | undefined;
|
|
27
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
28
|
+
interface BadgeProps extends React$1.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
|
|
29
|
+
}
|
|
30
|
+
declare function Badge({ className, variant, ...props }: BadgeProps): react_jsx_runtime.JSX.Element;
|
|
31
|
+
|
|
32
|
+
declare const Label: React$1.ForwardRefExoticComponent<Omit<LabelPrimitive.LabelProps & React$1.RefAttributes<HTMLLabelElement>, "ref"> & VariantProps<(props?: class_variance_authority_types.ClassProp | undefined) => string> & React$1.RefAttributes<HTMLLabelElement>>;
|
|
33
|
+
|
|
34
|
+
interface InputProps extends React$1.InputHTMLAttributes<HTMLInputElement> {
|
|
35
|
+
}
|
|
36
|
+
declare const Input: React$1.ForwardRefExoticComponent<InputProps & React$1.RefAttributes<HTMLInputElement>>;
|
|
37
|
+
|
|
38
|
+
declare const Dialog: React$1.FC<DialogPrimitive.DialogProps>;
|
|
39
|
+
declare const DialogTrigger: React$1.ForwardRefExoticComponent<DialogPrimitive.DialogTriggerProps & React$1.RefAttributes<HTMLButtonElement>>;
|
|
40
|
+
declare const DialogPortal: React$1.FC<DialogPrimitive.DialogPortalProps>;
|
|
41
|
+
declare const DialogClose: React$1.ForwardRefExoticComponent<DialogPrimitive.DialogCloseProps & React$1.RefAttributes<HTMLButtonElement>>;
|
|
42
|
+
declare const DialogOverlay: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
43
|
+
declare const DialogContent: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
44
|
+
declare const DialogHeader: {
|
|
45
|
+
({ className, ...props }: React$1.HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
|
|
46
|
+
displayName: string;
|
|
47
|
+
};
|
|
48
|
+
declare const DialogFooter: {
|
|
49
|
+
({ className, ...props }: React$1.HTMLAttributes<HTMLDivElement>): react_jsx_runtime.JSX.Element;
|
|
50
|
+
displayName: string;
|
|
51
|
+
};
|
|
52
|
+
declare const DialogTitle: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React$1.RefAttributes<HTMLHeadingElement>, "ref"> & React$1.RefAttributes<HTMLHeadingElement>>;
|
|
53
|
+
declare const DialogDescription: React$1.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React$1.RefAttributes<HTMLParagraphElement>, "ref"> & React$1.RefAttributes<HTMLParagraphElement>>;
|
|
54
|
+
|
|
55
|
+
declare const AnimatedTooltip: ({ items, }: {
|
|
56
|
+
items: {
|
|
57
|
+
id: number;
|
|
58
|
+
name: string;
|
|
59
|
+
designation: string;
|
|
60
|
+
image: string;
|
|
61
|
+
}[];
|
|
62
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
63
|
+
|
|
64
|
+
declare const HoverEffect: ({ items, className, }: {
|
|
65
|
+
items: {
|
|
66
|
+
title: string;
|
|
67
|
+
description: string;
|
|
68
|
+
link: string;
|
|
69
|
+
logoUrl: string;
|
|
70
|
+
}[];
|
|
71
|
+
className?: string;
|
|
72
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
73
|
+
declare const HoverCard: ({ className, children, logoUrl, }: {
|
|
74
|
+
className?: string;
|
|
75
|
+
children: React.ReactNode;
|
|
76
|
+
logoUrl: string;
|
|
77
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
78
|
+
declare const HoverCardTitle: ({ className, children, }: {
|
|
79
|
+
className?: string;
|
|
80
|
+
children: React.ReactNode;
|
|
81
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
82
|
+
declare const HoverCardDescription: ({ className, children, }: {
|
|
83
|
+
className?: string;
|
|
84
|
+
children: React.ReactNode;
|
|
85
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
86
|
+
|
|
87
|
+
declare const FlipWords: ({ words, duration, className, }: {
|
|
88
|
+
words: string[];
|
|
89
|
+
duration?: number;
|
|
90
|
+
className?: string;
|
|
91
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
92
|
+
|
|
93
|
+
declare const HeroHighlight: ({ children, className, containerClassName, }: {
|
|
94
|
+
children: React__default.ReactNode;
|
|
95
|
+
className?: string;
|
|
96
|
+
containerClassName?: string;
|
|
97
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
98
|
+
declare const Highlight: ({ children, className, }: {
|
|
99
|
+
children: React__default.ReactNode;
|
|
100
|
+
className?: string;
|
|
101
|
+
}) => react_jsx_runtime.JSX.Element;
|
|
102
|
+
|
|
103
|
+
export { AnimatedTooltip, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, FlipWords, HeroHighlight, Highlight, HoverCard, HoverCardDescription, HoverCardTitle, HoverEffect, Input, type InputProps, Label, badgeVariants, buttonVariants };
|