Implement Auth account page

This commit is contained in:
Takeshi Kimata
2024-05-19 20:25:09 +09:00
parent a5b218f55e
commit 076f7c74d4
25 changed files with 119 additions and 40 deletions

View File

@@ -2,8 +2,10 @@
import { createContext, useState, useEffect } from "react";
import { TokenType } from "@/types/user";
import { TokenProps } from "@/types/user";
import { useRouter, usePathname } from "@/src/navigation";
const LOCAL_STORAGE_KEY = "testplat-auth-token";
const privatePaths = ["/account"];
function storeTokenToLocalStorage(token: TokenType) {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(token));
@@ -16,7 +18,10 @@ function removeTokenFromLocalStorage() {
const defaultTokenContext = {};
const TokenContext = createContext(defaultTokenContext);
const TokenProvider = ({ children }: TokenProps) => {
const TokenProvider = ({ locale, children }: TokenProps) => {
const router = useRouter();
const pathname = usePathname();
const [token, setToken] = useState<TokenType>({
access_token: "",
user: null,
@@ -28,13 +33,27 @@ const TokenProvider = ({ children }: TokenProps) => {
removeTokenFromLocalStorage,
};
const restoreTokenFromLocalStorage = () => {
const tokenString = localStorage.getItem(LOCAL_STORAGE_KEY);
if (tokenString) {
const restoredToken = JSON.parse(tokenString);
setToken(restoredToken);
} else {
checkSignInPage();
}
};
const checkSignInPage = () => {
if (
privatePaths.some((path) => {
return path === pathname;
})
) {
router.push(`/account/signin`, { locale: locale });
}
};
useEffect(() => {
const restoreTokenFromLocalStorage = () => {
const tokenString = localStorage.getItem(LOCAL_STORAGE_KEY);
if (tokenString) {
setToken(JSON.parse(tokenString));
}
};
restoreTokenFromLocalStorage();
}, []);

View File

@@ -0,0 +1,46 @@
"use client";
import { useContext } from "react";
import { Avatar, Card, CardHeader, CardBody, Divider } from "@nextui-org/react";
import { TokenContext } from "../TokenProvider";
type AccountPageMessages = {
yourProjects: string;
};
type Props = {
messages: AccountPageMessages;
locale: string;
};
export default function AccountPage({ messages, locale }: Props) {
const context = useContext(TokenContext);
return (
<>
{context.token && context.token.user && (
<Card className="w-[600px] mt-16 mx-3">
<CardHeader className="flex gap-6">
<Avatar
isBordered
radius="full"
className="w-16 h-16 text-large"
src={context.token.user.avatarPath}
/>
<div className="flex flex-col">
<p className="text-2xl font-bold">
{context.token.user.username}
</p>
<p className="text-lg text-default-500">
{context.token.user.email}
</p>
</div>
</CardHeader>
<Divider />
<CardBody className="overflow-visible px-4 pb-4">
<p className="text-default-500">{messages.yourProjects}</p>
</CardBody>
</Card>
)}
</>
);
}

View File

@@ -1,4 +1,5 @@
import { UserType } from "@/types/user";
import { avatars } from "@/config/selection";
import Config from "@/config/config";
const apiServer = Config.apiServer;
@@ -50,4 +51,9 @@ async function signIn(signInUser: UserType) {
}
}
export { signUp, signIn };
function getRandomAvatarPath() {
const randomIndex = Math.floor(Math.random() * avatars.length);
return avatars[randomIndex];
}
export { signUp, signIn, getRandomAvatarPath };

View File

@@ -6,7 +6,7 @@ import { Link } from "@/src/navigation";
import { ChevronRight, Eye, EyeOff } from "lucide-react";
import { UserType, AuthMessages } from "@/types/user";
import { roles } from "@/config/selection";
import { signUp, signIn } from "./authControl";
import { signUp, signIn, getRandomAvatarPath } from "./authControl";
import { isValidEmail, isValidPassword } from "./validate";
import { TokenContext } from "../TokenProvider";
import { useRouter } from "@/src/navigation";
@@ -58,6 +58,8 @@ export default function AuthPage({ isSignup, messages, locale }: Props) {
}
}
const initialavatarPath = getRandomAvatarPath();
user.avatarPath = initialavatarPath;
await submit();
};
@@ -85,7 +87,7 @@ export default function AuthPage({ isSignup, messages, locale }: Props) {
};
return (
<Card className="border-none bg-background/60 dark:bg-default-100/50 w-[480px]">
<Card className="w-[480px] mt-16">
<CardHeader className="px-4 pt-4 pb-0 flex justify-between">
<h4 className="font-bold text-large">{messages.title}</h4>
<Link

View File

@@ -1,27 +1,10 @@
import { useTranslations } from "next-intl";
import { Input, Button, Card, CardHeader, CardBody } from "@nextui-org/react";
import { Link } from "@/src/navigation";
import AccountPage from "./AccountPage";
export default function Page(params: { locale: string }) {
const t = useTranslations("Auth");
const messages = {
yourProjects: t("your_projects"),
};
return (
<Card className="border-none bg-background/60 dark:bg-default-100/50 w-[480px]">
<CardHeader className="px-4 pt-4 pb-0 flex justify-between">
<h4 className="font-bold text-large">{t('account')}</h4>
{/* <Link href={isSignup ? "/auth/signin" : "/auth/signup"} locale={locale}>
<Button
color="primary"
variant="light"
endContent={<ChevronRight size={16} />}
>
{messages.linkTitle}
</Button>
</Link> */}
</CardHeader>
<CardBody className="overflow-visible px-4 pt-0 pb-4">
afgdsfg
</CardBody>
</Card>
);
return <AccountPage messages={messages} locale={params.locale} />;
}

View File

@@ -34,7 +34,10 @@ export default function RootLayout({
fontSans.variable
)}
>
<Providers themeProps={{ attribute: "class", defaultTheme: "light" }}>
<Providers
themeProps={{ attribute: "class", defaultTheme: "light" }}
tokenProps={{ locale: locale }}
>
<div className="relative flex flex-col min-h-screen light:bg-neutral-50 dark:bg-neutral-800">
<Header locale={locale} />
<main>{children}</main>

View File

@@ -12,16 +12,16 @@ import { TokenProps } from "@/types/user";
export interface ProvidersProps {
children: React.ReactNode;
themeProps?: ThemeProviderProps;
userProps?: TokenProps;
tokenProps?: TokenProps;
}
export function Providers({ children, themeProps, userProps }: ProvidersProps) {
export function Providers({ children, themeProps, tokenProps }: ProvidersProps) {
const router = useRouter();
return (
<NextUIProvider navigate={router.push}>
<NextThemesProvider {...themeProps}>
<TokenProvider {...userProps}>{children}</TokenProvider>
<TokenProvider {...tokenProps}>{children}</TokenProvider>
</NextThemesProvider>
</NextUIProvider>
);