This commit is contained in:
louiscklaw
2025-06-18 13:42:35 +08:00
parent 80a2636f90
commit 13c3399a6e
46 changed files with 1188 additions and 16 deletions

View File

@@ -1,5 +1,6 @@
import { useMemo } from 'react';
import { endpoints, fetcher } from 'src/lib/axios';
import { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IPostItem } from 'src/types/blog';
import type { SWRConfiguration } from 'swr';
import useSWR from 'swr';

View File

@@ -1,5 +1,6 @@
import { useMemo } from 'react';
import axios, { endpoints, fetcher } from 'src/lib/axios';
import axios, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { ICalendarEvent } from 'src/types/calendar';
import type { SWRConfiguration } from 'swr';
import useSWR, { mutate } from 'swr';

View File

@@ -1,6 +1,7 @@
import { keyBy } from 'es-toolkit';
import { useMemo } from 'react';
import axios, { endpoints, fetcher } from 'src/lib/axios';
import axios, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IChatConversation, IChatMessage, IChatParticipant } from 'src/types/chat';
import type { SWRConfiguration } from 'swr';
import useSWR, { mutate } from 'swr';

View File

@@ -1,6 +1,7 @@
// src/actions/invoice.ts
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import axiosInstance, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IInvoiceItem, SaveInvoiceData } from 'src/types/invoice';
import type { SWRConfiguration } from 'swr';
import useSWR from 'swr';

View File

@@ -1,6 +1,7 @@
import type { UniqueIdentifier } from '@dnd-kit/core';
import { startTransition, useMemo } from 'react';
import axios, { endpoints, fetcher } from 'src/lib/axios';
import axios, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IKanban, IKanbanColumn, IKanbanTask } from 'src/types/kanban';
import type { SWRConfiguration } from 'swr';
import useSWR, { mutate } from 'swr';

View File

@@ -1,6 +1,7 @@
import { keyBy } from 'es-toolkit';
import { useMemo } from 'react';
import { endpoints, fetcher } from 'src/lib/axios';
import { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IMail, IMailLabel } from 'src/types/mail';
import type { SWRConfiguration } from 'swr';
import useSWR from 'swr';

View File

@@ -1,6 +1,7 @@
// src/actions/order.ts
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import axiosInstance, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IOrderItem } from 'src/types/order';
import type { IProductItem } from 'src/types/product';
import type { SWRConfiguration } from 'swr';

View File

@@ -1,7 +1,8 @@
// src/actions/party-event.ts
//
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import axiosInstance, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IPartyEventItem } from 'src/types/party-event';
import type { SWRConfiguration } from 'swr';
import useSWR, { mutate } from 'swr';

View File

@@ -1,7 +1,8 @@
// src/actions/party-order.ts
//
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import axiosInstance, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IPartyOrderItem } from 'src/types/party-order';
import type { SWRConfiguration } from 'swr';
import useSWR, { mutate } from 'swr';

View File

@@ -1,7 +1,8 @@
// src/actions/party-user1.ts
//
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import axiosInstance, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IPartyUserItem } from 'src/types/party-user';
import type { IProductItem } from 'src/types/product';
import type { SWRConfiguration } from 'swr';

View File

@@ -1,7 +1,8 @@
// src/actions/product.ts
//
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import axiosInstance, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IProductItem } from 'src/types/product';
import type { SWRConfiguration } from 'swr';
import useSWR, { mutate } from 'swr';

View File

@@ -1,5 +1,6 @@
import { useMemo } from 'react';
import axiosInstance, { endpoints, fetcher } from 'src/lib/axios';
import axiosInstance, { fetcher } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { IProductItem } from 'src/types/product';
import { IUserItem } from 'src/types/user';
import type { SWRConfiguration } from 'swr';

View File

@@ -1,4 +1,5 @@
import axios, { endpoints } from 'src/lib/axios';
import axios from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import { JWT_STORAGE_KEY } from './constant';
import { setSession } from './utils';

View File

@@ -1,6 +1,7 @@
import { useSetState } from 'minimal-shared/hooks';
import { useCallback, useEffect, useMemo } from 'react';
import axios, { endpoints } from 'src/lib/axios';
import axios from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import type { AuthState } from '../../types';
import { AuthContext } from '../auth-context';
import { JWT_STORAGE_KEY } from './constant';

View File

@@ -0,0 +1,2 @@
export const ERR_ACCESS_TOKEN_NOT_FOUND = `Access token not found in response`;
export const ACCESS_TOKEN_NOT_FOUND_IN_RESPONSE = 'Access token not found in response';

View File

@@ -0,0 +1,85 @@
import axios from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import { JWT_STORAGE_KEY } from './constant';
import { ACCESS_TOKEN_NOT_FOUND_IN_RESPONSE, ERR_ACCESS_TOKEN_NOT_FOUND } from './ERRORS';
import { setSession } from './utils';
// ----------------------------------------------------------------------
export type SignInParams = {
email: string;
password: string;
};
export type SignUpParams = {
email: string;
password: string;
firstName: string;
lastName: string;
};
/** **************************************
* Sign in
*************************************** */
export const signInWithPassword = async ({ email, password }: SignInParams): Promise<void> => {
try {
const params = { email, password };
const res = await axios.post(endpoints.partyUserAuth.signIn, params);
const { accessToken } = res.data;
if (!accessToken) {
throw new Error(ERR_ACCESS_TOKEN_NOT_FOUND);
}
setSession(accessToken);
} catch (error) {
console.error('Error during sign in:', error);
throw error;
}
};
/** **************************************
* Sign up
*************************************** */
export const signUp = async ({
email,
password,
firstName,
lastName,
}: SignUpParams): Promise<void> => {
const params = {
email,
password,
firstName,
lastName,
};
try {
const res = await axios.post(endpoints.auth.signUp, params);
const { accessToken } = res.data;
if (!accessToken) {
throw new Error(ACCESS_TOKEN_NOT_FOUND_IN_RESPONSE);
}
sessionStorage.setItem(JWT_STORAGE_KEY, accessToken);
} catch (error) {
console.error('Error during sign up:', error);
throw error;
}
};
/** **************************************
* Sign out
*************************************** */
export const signOut = async (): Promise<void> => {
try {
await setSession(null);
} catch (error) {
console.error('Error during sign out:', error);
throw error;
}
};

View File

@@ -0,0 +1 @@
export const JWT_STORAGE_KEY = 'jwt_access_token';

View File

@@ -0,0 +1,7 @@
export * from './utils';
export * from './action';
export * from './constant';
// export * from './auth-provider';

View File

@@ -0,0 +1,94 @@
import axios from 'src/lib/axios';
import { paths } from 'src/routes/paths';
import { JWT_STORAGE_KEY } from './constant';
// ----------------------------------------------------------------------
export function jwtDecode(token: string) {
try {
if (!token) return null;
const parts = token.split('.');
if (parts.length < 2) {
throw new Error('Invalid token!');
}
const base64Url = parts[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const decoded = JSON.parse(atob(base64));
return decoded;
} catch (error) {
console.error('Error decoding token:', error);
throw error;
}
}
// ----------------------------------------------------------------------
export function isValidToken(accessToken: string) {
if (!accessToken) {
return false;
}
try {
const decoded = jwtDecode(accessToken);
if (!decoded || !('exp' in decoded)) {
return false;
}
const currentTime = Date.now() / 1000;
return decoded.exp > currentTime;
} catch (error) {
console.error('Error during token validation:', error);
return false;
}
}
// ----------------------------------------------------------------------
export function tokenExpired(exp: number) {
const currentTime = Date.now();
const timeLeft = exp * 1000 - currentTime;
setTimeout(() => {
try {
alert('Token expired!');
sessionStorage.removeItem(JWT_STORAGE_KEY);
window.location.href = paths.auth.jwt.signIn;
} catch (error) {
console.error('Error during token expiration:', error);
throw error;
}
}, timeLeft);
}
// ----------------------------------------------------------------------
const INVALID_ACCESS_TOKEN = 'Invalid access token!';
export async function setSession(accessToken: string | null) {
try {
if (accessToken) {
sessionStorage.setItem(JWT_STORAGE_KEY, accessToken);
axios.defaults.headers.common.Authorization = `Bearer ${accessToken}`;
const decodedToken = jwtDecode(accessToken); // ~3 days by minimals server
if (decodedToken && 'exp' in decodedToken) {
tokenExpired(decodedToken.exp);
} else {
throw new Error(INVALID_ACCESS_TOKEN);
}
} else {
sessionStorage.removeItem(JWT_STORAGE_KEY);
delete axios.defaults.headers.common.Authorization;
}
} catch (error) {
console.error('Error during set session:', error);
throw error;
}
}

View File

@@ -0,0 +1,3 @@
export * from './jwt-sign-in-view';
export * from './jwt-sign-up-view';

View File

@@ -0,0 +1,167 @@
import { zodResolver } from '@hookform/resolvers/zod';
import Alert from '@mui/material/Alert';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import InputAdornment from '@mui/material/InputAdornment';
import Link from '@mui/material/Link';
import { useBoolean } from 'minimal-shared/hooks';
import React, { useState } from 'react';
import { useForm } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { Field, Form } from 'src/components/hook-form';
import { Iconify } from 'src/components/iconify';
import { RouterLink } from 'src/routes/components';
import { useRouter } from 'src/routes/hooks';
import { paths } from 'src/routes/paths';
import { z as zod } from 'zod';
import { FormHead } from '../../components/form-head';
import { signInWithPassword } from '../../context/party-user-jwt';
import { useAuthContext } from '../../hooks';
import { getErrorMessage } from '../../utils';
// ----------------------------------------------------------------------
// ----------------------------------------------------------------------
export function JwtSignInView(): React.JSX.Element {
const { t } = useTranslation();
const router = useRouter();
const showPassword = useBoolean();
const { checkUserSession } = useAuthContext();
const [errorMessage, setErrorMessage] = useState<string | null>(null);
type SignInSchemaType = zod.infer<typeof SignInSchema>;
const EMAIL_IS_REQUIRED = 'Email is required!';
const EMAIL_MUST_BE_A_VALID_EMAIL_ADDRESS = 'Email must be a valid email address!';
const PASSWORD_IS_REQUIRED = 'Password is required!';
const PASSWORD_MUST_BE_AT_LEAST_6_CHARACTERS = 'Password must be at least 6 characters!';
const SignInSchema = zod.object({
email: zod
.string()
.min(1, { message: EMAIL_IS_REQUIRED })
.email({ message: EMAIL_MUST_BE_A_VALID_EMAIL_ADDRESS }),
password: zod
.string()
.min(1, { message: PASSWORD_IS_REQUIRED })
.min(6, { message: PASSWORD_MUST_BE_AT_LEAST_6_CHARACTERS }),
});
const defaultValues: SignInSchemaType = {
email: 'party_user0@prisma.io',
password: 'Aa12345678',
};
const methods = useForm<SignInSchemaType>({
resolver: zodResolver(SignInSchema),
defaultValues,
});
const {
handleSubmit,
formState: { isSubmitting },
} = methods;
const onSubmit = handleSubmit(async (data) => {
try {
await signInWithPassword({ email: data.email, password: data.password });
await checkUserSession?.();
router.refresh();
} catch (error) {
console.error(error);
const feedbackMessage = getErrorMessage(error);
setErrorMessage(feedbackMessage);
}
});
const renderForm = () => (
<Box sx={{ gap: 3, display: 'flex', flexDirection: 'column' }}>
<Field.Text name="email" label="Email address" slotProps={{ inputLabel: { shrink: true } }} />
<Box sx={{ gap: 1.5, display: 'flex', flexDirection: 'column' }}>
<Link
component={RouterLink}
href="#"
variant="body2"
color="inherit"
sx={{ alignSelf: 'flex-end' }}
>
Forgot password?
</Link>
<Field.Text
name="password"
label="Password"
placeholder="6+ characters"
type={showPassword.value ? 'text' : 'password'}
slotProps={{
inputLabel: { shrink: true },
input: {
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={showPassword.onToggle} edge="end">
<Iconify
icon={showPassword.value ? 'solar:eye-bold' : 'solar:eye-closed-bold'}
/>
</IconButton>
</InputAdornment>
),
},
}}
/>
</Box>
<Button
fullWidth
color="inherit"
size="large"
type="submit"
variant="contained"
loading={isSubmitting}
loadingIndicator="Sign in..."
>
{t('sign-in')}
</Button>
</Box>
);
return (
<>
<FormHead
title="Sign in to your account"
description={
<>
{`Dont have an account? `}
<Link component={RouterLink} href={paths.partyUserAuth.jwt.signUp} variant="subtitle2">
{t('get-started')}
</Link>
</>
}
sx={{ textAlign: { xs: 'center', md: 'left' } }}
/>
<Alert severity="info" sx={{ mb: 3 }}>
Use <strong>{defaultValues.email}</strong>
{' with password '}
<strong>{defaultValues.password}</strong>
</Alert>
{!!errorMessage && (
<Alert severity="error" sx={{ mb: 3 }}>
{errorMessage}
</Alert>
)}
<Form methods={methods} onSubmit={onSubmit}>
{renderForm()}
</Form>
</>
);
}

View File

@@ -0,0 +1,166 @@
import { zodResolver } from '@hookform/resolvers/zod';
import Alert from '@mui/material/Alert';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import InputAdornment from '@mui/material/InputAdornment';
import Link from '@mui/material/Link';
import { useBoolean } from 'minimal-shared/hooks';
import { useState } from 'react';
import { useForm } from 'react-hook-form';
import { Field, Form } from 'src/components/hook-form';
import { Iconify } from 'src/components/iconify';
import { RouterLink } from 'src/routes/components';
import { useRouter } from 'src/routes/hooks';
import { paths } from 'src/routes/paths';
import { z as zod } from 'zod';
import { FormHead } from '../../components/form-head';
import { SignUpTerms } from '../../components/sign-up-terms';
import { signUp } from '../../context/jwt';
import { useAuthContext } from '../../hooks';
import { getErrorMessage } from '../../utils';
// ----------------------------------------------------------------------
export type SignUpSchemaType = zod.infer<typeof SignUpSchema>;
export const SignUpSchema = zod.object({
firstName: zod.string().min(1, { message: 'First name is required!' }),
lastName: zod.string().min(1, { message: 'Last name is required!' }),
email: zod
.string()
.min(1, { message: 'Email is required!' })
.email({ message: 'Email must be a valid email address!' }),
password: zod
.string()
.min(1, { message: 'Password is required!' })
.min(6, { message: 'Password must be at least 6 characters!' }),
});
// ----------------------------------------------------------------------
export function JwtSignUpView() {
const router = useRouter();
const showPassword = useBoolean();
const { checkUserSession } = useAuthContext();
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const defaultValues: SignUpSchemaType = {
firstName: 'Hello',
lastName: 'Friend',
email: 'hello@gmail.com',
password: '@2Minimal',
};
const methods = useForm<SignUpSchemaType>({
resolver: zodResolver(SignUpSchema),
defaultValues,
});
const {
handleSubmit,
formState: { isSubmitting },
} = methods;
const onSubmit = handleSubmit(async (data) => {
try {
await signUp({
email: data.email,
password: data.password,
firstName: data.firstName,
lastName: data.lastName,
});
await checkUserSession?.();
router.refresh();
} catch (error) {
console.error(error);
const feedbackMessage = getErrorMessage(error);
setErrorMessage(feedbackMessage);
}
});
const renderForm = () => (
<Box sx={{ gap: 3, display: 'flex', flexDirection: 'column' }}>
<Box
sx={{ display: 'flex', gap: { xs: 3, sm: 2 }, flexDirection: { xs: 'column', sm: 'row' } }}
>
<Field.Text
name="firstName"
label="First name"
slotProps={{ inputLabel: { shrink: true } }}
/>
<Field.Text
name="lastName"
label="Last name"
slotProps={{ inputLabel: { shrink: true } }}
/>
</Box>
<Field.Text name="email" label="Email address" slotProps={{ inputLabel: { shrink: true } }} />
<Field.Text
name="password"
label="Password"
placeholder="6+ characters"
type={showPassword.value ? 'text' : 'password'}
slotProps={{
inputLabel: { shrink: true },
input: {
endAdornment: (
<InputAdornment position="end">
<IconButton onClick={showPassword.onToggle} edge="end">
<Iconify icon={showPassword.value ? 'solar:eye-bold' : 'solar:eye-closed-bold'} />
</IconButton>
</InputAdornment>
),
},
}}
/>
<Button
fullWidth
color="inherit"
size="large"
type="submit"
variant="contained"
loading={isSubmitting}
loadingIndicator="Create account..."
>
Create account
</Button>
</Box>
);
return (
<>
<FormHead
title="Hi New party user, Get started absolutely free "
description={
<>
{`Already have an account? `}
<Link component={RouterLink} href={paths.auth.jwt.signIn} variant="subtitle2">
Get started
</Link>
</>
}
sx={{ textAlign: { xs: 'center', md: 'left' } }}
/>
{!!errorMessage && (
<Alert severity="error" sx={{ mb: 3 }}>
{errorMessage}
</Alert>
)}
<Form methods={methods} onSubmit={onSubmit}>
{renderForm()}
</Form>
<SignUpTerms />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { AmplifyResetPasswordView } from 'src/auth/view/amplify';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Reset password | Amplify - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<AmplifyResetPasswordView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { AmplifySignInView } from 'src/auth/view/amplify';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Sign in | Amplify - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<AmplifySignInView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { AmplifySignUpView } from 'src/auth/view/amplify';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Sign up | Amplify - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<AmplifySignUpView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { AmplifyUpdatePasswordView } from 'src/auth/view/amplify';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Update password | Amplify - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<AmplifyUpdatePasswordView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { AmplifyVerifyView } from 'src/auth/view/amplify';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Verify | Amplify - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<AmplifyVerifyView />
</>
);
}

View File

@@ -0,0 +1,7 @@
import { SplashScreen } from 'src/components/loading-screen';
// ----------------------------------------------------------------------
export default function CallbackPage() {
return <SplashScreen />;
}

View File

@@ -0,0 +1,16 @@
import { Auth0SignInView } from 'src/auth/view/auth0';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Sign in | Auth0 - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<Auth0SignInView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { FirebaseResetPasswordView } from 'src/auth/view/firebase';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Reset password | Firebase - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<FirebaseResetPasswordView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { FirebaseSignInView } from 'src/auth/view/firebase';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Sign in | Firebase - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<FirebaseSignInView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { FirebaseSignUpView } from 'src/auth/view/firebase';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Sign up | Firebase - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<FirebaseSignUpView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { FirebaseVerifyView } from 'src/auth/view/firebase';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Verify | Firebase - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<FirebaseVerifyView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { JwtSignInView } from 'src/auth/view/party-user-jwt';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Sign in | Jwt - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<JwtSignInView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { JwtSignUpView } from 'src/auth/view/party-user-jwt';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Sign up | Jwt - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<JwtSignUpView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { SupabaseResetPasswordView } from 'src/auth/view/supabase';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Reset password | Supabase - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<SupabaseResetPasswordView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { SupabaseSignInView } from 'src/auth/view/supabase';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Sign in | Supabase - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<SupabaseSignInView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { SupabaseSignUpView } from 'src/auth/view/supabase';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Sign up | Supabase - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<SupabaseSignUpView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { SupabaseUpdatePasswordView } from 'src/auth/view/supabase';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Update password | Supabase - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<SupabaseUpdatePasswordView />
</>
);
}

View File

@@ -0,0 +1,16 @@
import { SupabaseVerifyView } from 'src/auth/view/supabase';
import { CONFIG } from 'src/global-config';
// ----------------------------------------------------------------------
const metadata = { title: `Verify | Supabase - ${CONFIG.appName}` };
export default function Page() {
return (
<>
<title>{metadata.title}</title>
<SupabaseVerifyView />
</>
);
}

View File

@@ -10,6 +10,8 @@ const ROOTS = {
AUTH: '/auth',
AUTH_DEMO: '/auth-demo',
DASHBOARD: '/dashboard',
//
PARTY_USER_AUTH: '/party-user-auth',
};
// ----------------------------------------------------------------------
@@ -207,4 +209,32 @@ export const paths = {
demo: { edit: `${ROOTS.DASHBOARD}/party-user/${MOCK_ID}/edit` },
},
},
partyUserAuth: {
jwt: {
signIn: `${ROOTS.PARTY_USER_AUTH}/jwt/sign-in`,
signUp: `${ROOTS.PARTY_USER_AUTH}/jwt/sign-up`,
},
//
// amplify: {
// signIn: `${ROOTS.PARTY_USER_AUTH}/amplify/sign-in`,
// verify: `${ROOTS.PARTY_USER_AUTH}/amplify/verify`,
// signUp: `${ROOTS.PARTY_USER_AUTH}/amplify/sign-up`,
// updatePassword: `${ROOTS.PARTY_USER_AUTH}/amplify/update-password`,
// resetPassword: `${ROOTS.PARTY_USER_AUTH}/amplify/reset-password`,
// },
// firebase: {
// signIn: `${ROOTS.PARTY_USER_AUTH}/firebase/sign-in`,
// verify: `${ROOTS.PARTY_USER_AUTH}/firebase/verify`,
// signUp: `${ROOTS.PARTY_USER_AUTH}/firebase/sign-up`,
// resetPassword: `${ROOTS.PARTY_USER_AUTH}/firebase/reset-password`,
// },
// auth0: { signIn: `${ROOTS.PARTY_USER_AUTH}/auth0/sign-in` },
// supabase: {
// signIn: `${ROOTS.PARTY_USER_AUTH}/supabase/sign-in`,
// verify: `${ROOTS.PARTY_USER_AUTH}/supabase/verify`,
// signUp: `${ROOTS.PARTY_USER_AUTH}/supabase/sign-up`,
// updatePassword: `${ROOTS.PARTY_USER_AUTH}/supabase/update-password`,
// resetPassword: `${ROOTS.PARTY_USER_AUTH}/supabase/reset-password`,
// },
},
};

View File

@@ -9,6 +9,7 @@ import { authDemoRoutes } from './auth-demo';
import { componentsRoutes } from './components';
import { dashboardRoutes } from './dashboard';
import { mainRoutes } from './main';
import { partyUserAuthRoutes } from './party-user-auth';
// ----------------------------------------------------------------------
@@ -48,6 +49,9 @@ export const routesSection: RouteObject[] = [
// Components
...componentsRoutes,
// party-user-auth
...partyUserAuthRoutes,
// No match
{ path: '*', element: <Page404 /> },
];

View File

@@ -0,0 +1,282 @@
import { lazy, Suspense } from 'react';
import type { RouteObject } from 'react-router';
import { Outlet } from 'react-router';
import { GuestGuard } from 'src/auth/guard';
import { SplashScreen } from 'src/components/loading-screen';
import { AuthSplitLayout } from 'src/layouts/auth-split';
// ----------------------------------------------------------------------
/** **************************************
* Jwt
*************************************** */
const Jwt = {
SignInPage: lazy(() => import('src/pages/party-user-auth/jwt/sign-in')),
SignUpPage: lazy(() => import('src/pages/party-user-auth/jwt/sign-up')),
};
const authJwt = {
path: 'jwt',
children: [
{
path: 'sign-in',
element: (
<GuestGuard>
<AuthSplitLayout
slotProps={{
section: { title: 'Hi, Welcome back' },
}}
>
<Jwt.SignInPage />
</AuthSplitLayout>
</GuestGuard>
),
},
{
path: 'sign-up',
element: (
<GuestGuard>
<AuthSplitLayout>
<Jwt.SignUpPage />
</AuthSplitLayout>
</GuestGuard>
),
},
],
};
/** **************************************
* Amplify
*************************************** */
const Amplify = {
SignInPage: lazy(() => import('src/pages/auth/amplify/sign-in')),
SignUpPage: lazy(() => import('src/pages/auth/amplify/sign-up')),
VerifyPage: lazy(() => import('src/pages/auth/amplify/verify')),
UpdatePasswordPage: lazy(() => import('src/pages/auth/amplify/update-password')),
ResetPasswordPage: lazy(() => import('src/pages/auth/amplify/reset-password')),
};
const authAmplify = {
path: 'amplify',
children: [
{
path: 'sign-in',
element: (
<GuestGuard>
<AuthSplitLayout
slotProps={{
section: { title: 'Hi, Welcome back' },
}}
>
<Amplify.SignInPage />
</AuthSplitLayout>
</GuestGuard>
),
},
{
path: 'sign-up',
element: (
<GuestGuard>
<AuthSplitLayout>
<Amplify.SignUpPage />
</AuthSplitLayout>
</GuestGuard>
),
},
{
path: 'verify',
element: (
<AuthSplitLayout>
<Amplify.VerifyPage />
</AuthSplitLayout>
),
},
{
path: 'reset-password',
element: (
<AuthSplitLayout>
<Amplify.ResetPasswordPage />
</AuthSplitLayout>
),
},
{
path: 'update-password',
element: (
<AuthSplitLayout>
<Amplify.UpdatePasswordPage />
</AuthSplitLayout>
),
},
],
};
/** **************************************
* Firebase
*************************************** */
const Firebase = {
SignInPage: lazy(() => import('src/pages/auth/firebase/sign-in')),
SignUpPage: lazy(() => import('src/pages/auth/firebase/sign-up')),
VerifyPage: lazy(() => import('src/pages/auth/firebase/verify')),
ResetPasswordPage: lazy(() => import('src/pages/auth/firebase/reset-password')),
};
const authFirebase = {
path: 'firebase',
children: [
{
path: 'sign-in',
element: (
<GuestGuard>
<AuthSplitLayout
slotProps={{
section: { title: 'Hi, Welcome back' },
}}
>
<Firebase.SignInPage />
</AuthSplitLayout>
</GuestGuard>
),
},
{
path: 'sign-up',
element: (
<GuestGuard>
<AuthSplitLayout>
<Firebase.SignUpPage />
</AuthSplitLayout>
</GuestGuard>
),
},
{
path: 'verify',
element: (
<AuthSplitLayout>
<Firebase.VerifyPage />
</AuthSplitLayout>
),
},
{
path: 'reset-password',
element: (
<AuthSplitLayout>
<Firebase.ResetPasswordPage />
</AuthSplitLayout>
),
},
],
};
/** **************************************
* Auth0
*************************************** */
const Auth0 = {
SignInPage: lazy(() => import('src/pages/auth/auth0/sign-in')),
CallbackPage: lazy(() => import('src/pages/auth/auth0/callback')),
};
const authAuth0 = {
path: 'auth0',
children: [
{
path: 'sign-in',
element: (
<GuestGuard>
<AuthSplitLayout
slotProps={{
section: { title: 'Hi, Welcome back' },
}}
>
<Auth0.SignInPage />
</AuthSplitLayout>
</GuestGuard>
),
},
{
path: 'callback',
element: (
<GuestGuard>
<Auth0.CallbackPage />
</GuestGuard>
),
},
],
};
/** **************************************
* Supabase
*************************************** */
const Supabase = {
SignInPage: lazy(() => import('src/pages/auth/supabase/sign-in')),
SignUpPage: lazy(() => import('src/pages/auth/supabase/sign-up')),
VerifyPage: lazy(() => import('src/pages/auth/supabase/verify')),
UpdatePasswordPage: lazy(() => import('src/pages/auth/supabase/update-password')),
ResetPasswordPage: lazy(() => import('src/pages/auth/supabase/reset-password')),
};
const authSupabase = {
path: 'supabase',
children: [
{
path: 'sign-in',
element: (
<GuestGuard>
<AuthSplitLayout
slotProps={{
section: { title: 'Hi, Welcome back' },
}}
>
<Supabase.SignInPage />
</AuthSplitLayout>
</GuestGuard>
),
},
{
path: 'sign-up',
element: (
<GuestGuard>
<AuthSplitLayout>
<Supabase.SignUpPage />
</AuthSplitLayout>
</GuestGuard>
),
},
{
path: 'verify',
element: (
<AuthSplitLayout>
<Supabase.VerifyPage />
</AuthSplitLayout>
),
},
{
path: 'reset-password',
element: (
<AuthSplitLayout>
<Supabase.ResetPasswordPage />
</AuthSplitLayout>
),
},
{
path: 'update-password',
element: (
<AuthSplitLayout>
<Supabase.UpdatePasswordPage />
</AuthSplitLayout>
),
},
],
};
// ----------------------------------------------------------------------
export const partyUserAuthRoutes: RouteObject[] = [
{
path: 'party-user-auth',
element: (
<Suspense fallback={<SplashScreen />}>
<Outlet />
</Suspense>
),
children: [authJwt, authAmplify, authFirebase, authAuth0, authSupabase],
},
];

View File

@@ -83,6 +83,44 @@ export function OverviewAppView() {
/>
</Grid>
<Grid size={{ xs: 12, md: 4 }}>
<AppWidgetSummary
title="Total party-events"
percent={-0.1}
total={4}
chart={{
colors: [theme.palette.error.main],
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
series: [],
}}
/>
</Grid>
<Grid size={{ xs: 12, md: 4 }}>
<AppWidgetSummary
title="Total party-events"
percent={-0.1}
total={5}
chart={{
colors: [theme.palette.error.main],
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
series: [],
}}
/>
</Grid>
<Grid size={{ xs: 12, md: 4 }}>
<AppWidgetSummary
title="Total party-events"
percent={-0.1}
total={6}
chart={{
colors: [theme.palette.error.main],
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'],
series: [],
}}
/>
</Grid>
<Grid size={{ xs: 12, md: 6, lg: 4 }}>
<AppCurrentDownload
title="Current download"

View File

@@ -36,7 +36,7 @@ import { EmptyContent } from 'src/components/empty-content';
import { Iconify } from 'src/components/iconify';
import { toast } from 'src/components/snackbar';
import { DashboardContent } from 'src/layouts/dashboard';
import { endpoints } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import { RouterLink } from 'src/routes/components';
import { paths } from 'src/routes/paths';
import type { IPartyEventItem, IProductTableFilters } from 'src/types/party-event';

View File

@@ -35,7 +35,7 @@ import { EmptyContent } from 'src/components/empty-content';
import { Iconify } from 'src/components/iconify';
import { toast } from 'src/components/snackbar';
import { DashboardContent } from 'src/layouts/dashboard';
import { endpoints } from 'src/lib/axios';
import { endpoints } from 'src/lib/endpoints';
import { RouterLink } from 'src/routes/components';
import { paths } from 'src/routes/paths';
import type { IProductItem, IProductTableFilters } from 'src/types/product';