This commit is contained in:
@@ -5,24 +5,26 @@ import { folder } from "../../../../generated/prisma/client";
|
||||
import { Folder } from "lucide-react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Center } from "@/components/Center";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface FolderSelectorProps {
|
||||
folders: (folder & { total_pairs: number })[];
|
||||
}
|
||||
|
||||
const FolderSelector: React.FC<FolderSelectorProps> = ({ folders }) => {
|
||||
const t = useTranslations("memorize/folder-selector");
|
||||
const router = useRouter();
|
||||
return (
|
||||
<Center>
|
||||
<Container className="p-6 gap-4 flex flex-col">
|
||||
{(folders.length === 0 && (
|
||||
<h1 className="text-2xl text-gray-900 font-light">
|
||||
No folders found.
|
||||
{t("noFolders")}
|
||||
</h1>
|
||||
)) || (
|
||||
<>
|
||||
<h1 className="text-2xl text-gray-900 font-light">
|
||||
Select a folder:
|
||||
{t("selectFolder")}
|
||||
</h1>
|
||||
<div className="text-gray-900 border border-gray-200 rounded-2xl max-h-96 overflow-y-auto">
|
||||
{folders.map((folder) => (
|
||||
@@ -36,9 +38,12 @@ const FolderSelector: React.FC<FolderSelectorProps> = ({ folders }) => {
|
||||
<Folder />
|
||||
<div className="flex-1 flex gap-2">
|
||||
<span className="group-hover:text-blue-500">
|
||||
{folder.id}. {folder.name}
|
||||
{t("folderInfo", {
|
||||
id: folder.id,
|
||||
name: folder.name,
|
||||
count: folder.total_pairs,
|
||||
})}
|
||||
</span>
|
||||
<span>({folder.total_pairs})</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -8,12 +8,14 @@ import LightButton from "@/components/buttons/LightButton";
|
||||
import { useAudioPlayer } from "@/hooks/useAudioPlayer";
|
||||
import { getTTSAudioUrl } from "@/lib/tts";
|
||||
import { VOICES } from "@/config/locales";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface MemorizeProps {
|
||||
textPairs: text_pair[];
|
||||
}
|
||||
|
||||
const Memorize: React.FC<MemorizeProps> = ({ textPairs }) => {
|
||||
const t = useTranslations("memorize.memorize");
|
||||
const [reverse, setReverse] = useState(false);
|
||||
const [dictation, setDictation] = useState(false);
|
||||
const [index, setIndex] = useState(0);
|
||||
@@ -27,7 +29,7 @@ const Memorize: React.FC<MemorizeProps> = ({ textPairs }) => {
|
||||
<>
|
||||
<div className="h-36 flex flex-col gap-2 justify-start items-center font-serif text-3xl">
|
||||
<div className="text-sm text-gray-500">
|
||||
{index + 1}/{textPairs.length}
|
||||
{t("progress", { current: index + 1, total: textPairs.length })}
|
||||
</div>
|
||||
{dictation ? (
|
||||
show === "question" ? (
|
||||
@@ -86,7 +88,7 @@ const Memorize: React.FC<MemorizeProps> = ({ textPairs }) => {
|
||||
setShow(show === "question" ? "answer" : "question");
|
||||
}}
|
||||
>
|
||||
{show === "question" ? "Show Answer" : "Next"}
|
||||
{show === "question" ? t("showAnswer") : t("next")}
|
||||
</LightButton>
|
||||
<LightButton
|
||||
onClick={() => {
|
||||
@@ -94,7 +96,7 @@ const Memorize: React.FC<MemorizeProps> = ({ textPairs }) => {
|
||||
}}
|
||||
selected={reverse}
|
||||
>
|
||||
Reverse
|
||||
{t("reverse")}
|
||||
</LightButton>
|
||||
<LightButton
|
||||
onClick={() => {
|
||||
@@ -102,11 +104,11 @@ const Memorize: React.FC<MemorizeProps> = ({ textPairs }) => {
|
||||
}}
|
||||
selected={dictation}
|
||||
>
|
||||
Dictation
|
||||
{t("dictation")}
|
||||
</LightButton>
|
||||
</div>
|
||||
</>
|
||||
)) || <p>No text pairs available</p>}
|
||||
)) || <p>{t("noTextPairs")}</p>}
|
||||
</Container>
|
||||
</Center>
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { redirect } from "next/navigation";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import {
|
||||
getFoldersWithTotalPairsByOwner,
|
||||
getOwnerByFolderId,
|
||||
@@ -18,9 +19,14 @@ export default async function MemorizePage({
|
||||
}) {
|
||||
const session = await getServerSession();
|
||||
const username = session?.user?.name;
|
||||
const t = await getTranslations("memorize.page");
|
||||
|
||||
const t = (await searchParams).folder_id;
|
||||
const folder_id = t ? (isNonNegativeInteger(t) ? parseInt(t) : null) : null;
|
||||
const tParam = (await searchParams).folder_id;
|
||||
const folder_id = tParam
|
||||
? isNonNegativeInteger(tParam)
|
||||
? parseInt(tParam)
|
||||
: null
|
||||
: null;
|
||||
|
||||
if (!username)
|
||||
redirect(
|
||||
@@ -37,7 +43,7 @@ export default async function MemorizePage({
|
||||
|
||||
const owner = await getOwnerByFolderId(folder_id);
|
||||
if (owner !== username) {
|
||||
return <p>无权访问该文件夹</p>;
|
||||
return <p>{t("unauthorized")}</p>;
|
||||
}
|
||||
|
||||
return <Memorize textPairs={await getTextPairsByFolderId(folder_id)} />;
|
||||
|
||||
@@ -9,6 +9,7 @@ import { getFoldersByOwner } from "@/lib/services/folderService";
|
||||
import { Folder } from "lucide-react";
|
||||
import { createTextPair } from "@/lib/services/textPairService";
|
||||
import { toast } from "sonner";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface AddToFolderProps {
|
||||
item: z.infer<typeof TranslationHistorySchema>;
|
||||
@@ -18,6 +19,7 @@ interface AddToFolderProps {
|
||||
const AddToFolder: React.FC<AddToFolderProps> = ({ item, setShow }) => {
|
||||
const session = useSession();
|
||||
const [folders, setFolders] = useState<folder[]>([]);
|
||||
const t = useTranslations("translator.add-to-folder");
|
||||
|
||||
useEffect(() => {
|
||||
const username = session.data!.user!.name as string;
|
||||
@@ -28,7 +30,7 @@ const AddToFolder: React.FC<AddToFolderProps> = ({ item, setShow }) => {
|
||||
return (
|
||||
<div className="fixed left-0 top-0 z-50 w-screen h-screen bg-black/50 flex justify-center items-center">
|
||||
<Container className="p-6">
|
||||
<div>You are not authenticated</div>;
|
||||
<div>{t("notAuthenticated")}</div>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
@@ -36,7 +38,7 @@ const AddToFolder: React.FC<AddToFolderProps> = ({ item, setShow }) => {
|
||||
return (
|
||||
<div className="fixed left-0 top-0 z-50 w-screen h-screen bg-black/50 flex justify-center items-center">
|
||||
<Container className="p-6">
|
||||
<h1>Choose a Folder to Add to</h1>
|
||||
<h1>{t("chooseFolder")}</h1>
|
||||
<div className="border border-gray-200 rounded-2xl">
|
||||
{(folders.length > 0 &&
|
||||
folders.map((folder) => (
|
||||
@@ -56,20 +58,20 @@ const AddToFolder: React.FC<AddToFolderProps> = ({ item, setShow }) => {
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
toast.success("Text pair added to folder");
|
||||
toast.success(t("success"));
|
||||
setShow(false);
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error("Failed to add text pair to folder");
|
||||
toast.error(t("error"));
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Folder />
|
||||
{folder.id}. {folder.name}
|
||||
{t("folderInfo", { id: folder.id, name: folder.name })}
|
||||
</button>
|
||||
))) || <div>No folders found</div>}
|
||||
))) || <div>{t("noFolders")}</div>}
|
||||
</div>
|
||||
<LightButton onClick={() => setShow(false)}>Close</LightButton>
|
||||
<LightButton onClick={() => setShow(false)}>{t("close")}</LightButton>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -238,7 +238,7 @@ export default function TranslatorPage() {
|
||||
<LightButton
|
||||
selected={!["chinese", "english", "italian"].includes(lang)}
|
||||
onClick={() => {
|
||||
const newLang = prompt("Enter language");
|
||||
const newLang = prompt(t("enterLanguage"));
|
||||
if (newLang) {
|
||||
setLang(newLang);
|
||||
}
|
||||
@@ -261,7 +261,7 @@ export default function TranslatorPage() {
|
||||
</div>
|
||||
{history.length > 0 && (
|
||||
<div className="m-6 flex flex-col items-center">
|
||||
<h1 className="text-2xl font-light">History</h1>
|
||||
<h1 className="text-2xl font-light">{t("history")}</h1>
|
||||
<div className="border border-gray-200 rounded-2xl m-4">
|
||||
{history.map((item, index) => (
|
||||
<div key={index}>
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
deleteFolderById,
|
||||
getFoldersWithTotalPairsByOwner,
|
||||
} from "@/lib/services/folderService";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface FolderProps {
|
||||
folder: folder & { total_pairs: number };
|
||||
@@ -18,6 +19,7 @@ interface FolderProps {
|
||||
}
|
||||
|
||||
const FolderCard = ({ folder, deleteCallback, openCallback }: FolderProps) => {
|
||||
const t = useTranslations("folders");
|
||||
return (
|
||||
<div
|
||||
className="flex justify-between items-center group p-4 border-b border-gray-100 hover:bg-gray-50 cursor-pointer transition-colors"
|
||||
@@ -30,7 +32,11 @@ const FolderCard = ({ folder, deleteCallback, openCallback }: FolderProps) => {
|
||||
|
||||
<div className="flex-1">
|
||||
<h3 className="font-medium text-gray-900">
|
||||
{folder.id}. {folder.name} ({folder.total_pairs})
|
||||
{t("folderInfo", {
|
||||
id: folder.id,
|
||||
name: folder.name,
|
||||
totalPairs: folder.total_pairs,
|
||||
})}
|
||||
</h3>
|
||||
{/*<p className="text-sm text-gray-500">{} items</p>*/}
|
||||
</div>
|
||||
@@ -55,6 +61,7 @@ const FolderCard = ({ folder, deleteCallback, openCallback }: FolderProps) => {
|
||||
};
|
||||
|
||||
export default function FoldersClient({ username }: { username: string }) {
|
||||
const t = useTranslations("folders");
|
||||
const [folders, setFolders] = useState<(folder & { total_pairs: number })[]>(
|
||||
[],
|
||||
);
|
||||
@@ -80,13 +87,13 @@ export default function FoldersClient({ username }: { username: string }) {
|
||||
<Center>
|
||||
<div className="w-full max-w-2xl mx-auto bg-white border border-gray-200 rounded-2xl p-6">
|
||||
<div className="mb-6">
|
||||
<h1 className="text-2xl font-light text-gray-900">Folders</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">Manage your collections</p>
|
||||
<h1 className="text-2xl font-light text-gray-900">{t("title")}</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">{t("subtitle")}</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={async () => {
|
||||
const folderName = prompt("Enter folder name:");
|
||||
const folderName = prompt(t("enterFolderName"));
|
||||
if (!folderName) return;
|
||||
setLoading(true);
|
||||
try {
|
||||
@@ -103,7 +110,7 @@ export default function FoldersClient({ username }: { username: string }) {
|
||||
className="w-full p-3 border-2 border-dashed border-gray-300 rounded-xl text-gray-500 hover:border-gray-400 hover:text-gray-600 transition-colors flex items-center justify-center gap-2"
|
||||
>
|
||||
<FolderPlus size={18} />
|
||||
<span>{loading ? "Creating..." : "New Folder"}</span>
|
||||
<span>{loading ? t("creating") : t("newFolder")}</span>
|
||||
</button>
|
||||
|
||||
<div className="mt-4 max-h-96 overflow-y-auto">
|
||||
@@ -112,7 +119,7 @@ export default function FoldersClient({ username }: { username: string }) {
|
||||
<div className="w-16 h-16 mx-auto mb-3 rounded-lg bg-gray-100 flex items-center justify-center">
|
||||
<FolderPlus size={24} className="text-gray-400" />
|
||||
</div>
|
||||
<p className="text-sm">No folders yet</p>
|
||||
<p className="text-sm">{t("noFoldersYet")}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="rounded-xl border border-gray-200 overflow-hidden">
|
||||
@@ -121,7 +128,9 @@ export default function FoldersClient({ username }: { username: string }) {
|
||||
key={folder.id}
|
||||
folder={folder}
|
||||
deleteCallback={() => {
|
||||
const confirm = prompt(`Type "${folder.name}" to delete:`);
|
||||
const confirm = prompt(
|
||||
t("confirmDelete", { name: folder.name }),
|
||||
);
|
||||
if (confirm === folder.name) {
|
||||
deleteFolderById(folder.id).then(updateFolders);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import LightButton from "@/components/buttons/LightButton";
|
||||
import Input from "@/components/Input";
|
||||
import { X } from "lucide-react";
|
||||
import { useRef } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface AddTextPairModalProps {
|
||||
isOpen: boolean;
|
||||
@@ -19,6 +20,7 @@ export default function AddTextPairModal({
|
||||
onClose,
|
||||
onAdd,
|
||||
}: AddTextPairModalProps) {
|
||||
const t = useTranslations("folders.folder_id");
|
||||
const input1Ref = useRef<HTMLInputElement>(null);
|
||||
const input2Ref = useRef<HTMLInputElement>(null);
|
||||
const input3Ref = useRef<HTMLInputElement>(null);
|
||||
@@ -66,25 +68,29 @@ export default function AddTextPairModal({
|
||||
<div className="bg-white rounded-xl p-6 w-full max-w-md mx-4">
|
||||
<div className="flex">
|
||||
<h2 className="flex-1 text-xl font-light mb-4 text-center">
|
||||
Add New Text Pair
|
||||
{t("addNewTextPair")}
|
||||
</h2>
|
||||
<X onClick={onClose} className="hover:cursor-pointer"></X>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
text1<Input ref={input1Ref} className="w-full"></Input>
|
||||
{t("text1")}
|
||||
<Input ref={input1Ref} className="w-full"></Input>
|
||||
</div>
|
||||
<div>
|
||||
text2<Input ref={input2Ref} className="w-full"></Input>
|
||||
{t("text2")}
|
||||
<Input ref={input2Ref} className="w-full"></Input>
|
||||
</div>
|
||||
<div>
|
||||
locale1<Input ref={input3Ref} className="w-full"></Input>
|
||||
{t("locale1")}
|
||||
<Input ref={input3Ref} className="w-full"></Input>
|
||||
</div>
|
||||
<div>
|
||||
locale2<Input ref={input4Ref} className="w-full"></Input>
|
||||
{t("locale2")}
|
||||
<Input ref={input4Ref} className="w-full"></Input>
|
||||
</div>
|
||||
</div>
|
||||
<LightButton onClick={handleAdd}>Add</LightButton>
|
||||
<LightButton onClick={handleAdd}>{t("add")}</LightButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
import AddTextPairModal from "./AddTextPairModal";
|
||||
import TextPairCard from "./TextPairCard";
|
||||
import LightButton from "@/components/buttons/LightButton";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { toast } from "sonner";
|
||||
|
||||
export interface TextPair {
|
||||
id: number;
|
||||
@@ -27,6 +29,7 @@ export default function InFolder({ folderId }: { folderId: number }) {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [openAddModal, setAddModal] = useState(false);
|
||||
const router = useRouter();
|
||||
const t = useTranslations("folders.folder_id");
|
||||
|
||||
useEffect(() => {
|
||||
const fetchTextPairs = async () => {
|
||||
@@ -64,14 +67,16 @@ export default function InFolder({ folderId }: { folderId: number }) {
|
||||
className="flex items-center gap-2 text-gray-500 hover:text-gray-700 transition-colors mb-4"
|
||||
>
|
||||
<ArrowLeft size={16} />
|
||||
<span className="text-sm">Back to folders</span>
|
||||
<span className="text-sm">{t("back")}</span>
|
||||
</button>
|
||||
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<h1 className="text-2xl font-light text-gray-900">Text Pairs</h1>
|
||||
<h1 className="text-2xl font-light text-gray-900">
|
||||
{t("textPairs")}
|
||||
</h1>
|
||||
<p className="text-sm text-gray-500 mt-1">
|
||||
{textPairs.length} items
|
||||
{t("itemsCount", { count: textPairs.length })}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -81,7 +86,7 @@ export default function InFolder({ folderId }: { folderId: number }) {
|
||||
redirect(`/memorize?folder_id=${folderId}`);
|
||||
}}
|
||||
>
|
||||
Memorize
|
||||
{t("memorize")}
|
||||
</LightButton>
|
||||
<button
|
||||
className="p-2 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors"
|
||||
@@ -102,11 +107,11 @@ export default function InFolder({ folderId }: { folderId: number }) {
|
||||
{loading ? (
|
||||
<div className="p-8 text-center">
|
||||
<div className="w-8 h-8 border-2 border-gray-200 border-t-gray-400 rounded-full animate-spin mx-auto mb-3"></div>
|
||||
<p className="text-sm text-gray-500">Loading text pairs...</p>
|
||||
<p className="text-sm text-gray-500">{t("loadingTextPairs")}</p>
|
||||
</div>
|
||||
) : textPairs.length === 0 ? (
|
||||
<div className="p-12 text-center">
|
||||
<p className="text-sm text-gray-500 mb-2">No text pair items</p>
|
||||
<p className="text-sm text-gray-500 mb-2">{t("noTextPairs")}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="divide-y divide-gray-100">
|
||||
|
||||
@@ -4,6 +4,7 @@ import { updateTextPairById } from "@/lib/services/textPairService";
|
||||
import { useState } from "react";
|
||||
import { text_pairUpdateInput } from "../../../../generated/prisma/models";
|
||||
import UpdateTextPairModal from "./UpdateTextPairModal";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface TextPairCardProps {
|
||||
textPair: TextPair;
|
||||
@@ -16,6 +17,7 @@ export default function TextPairCard({
|
||||
onDel,
|
||||
refreshTextPairs,
|
||||
}: TextPairCardProps) {
|
||||
const t = useTranslations("folders.folder_id");
|
||||
const [openUpdateModal, setOpenUpdateModal] = useState(false);
|
||||
return (
|
||||
<div className="group border-b border-gray-100 hover:bg-gray-50 transition-colors">
|
||||
|
||||
@@ -4,6 +4,7 @@ import { X } from "lucide-react";
|
||||
import { useRef } from "react";
|
||||
import { text_pairUpdateInput } from "../../../../generated/prisma/models";
|
||||
import { TextPair } from "./InFolder";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
interface UpdateTextPairModalProps {
|
||||
isOpen: boolean;
|
||||
@@ -18,6 +19,7 @@ export default function UpdateTextPairModal({
|
||||
onUpdate,
|
||||
textPair,
|
||||
}: UpdateTextPairModalProps) {
|
||||
const t = useTranslations("folders.folder_id");
|
||||
const input1Ref = useRef<HTMLInputElement>(null);
|
||||
const input2Ref = useRef<HTMLInputElement>(null);
|
||||
const input3Ref = useRef<HTMLInputElement>(null);
|
||||
@@ -65,25 +67,45 @@ export default function UpdateTextPairModal({
|
||||
<div className="bg-white rounded-xl p-6 w-full max-w-md mx-4">
|
||||
<div className="flex">
|
||||
<h2 className="flex-1 text-xl font-light mb-4 text-center">
|
||||
Update Text Pair
|
||||
{t("updateTextPair")}
|
||||
</h2>
|
||||
<X onClick={onClose} className="hover:cursor-pointer"></X>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
text1<Input defaultValue={textPair.text1} ref={input1Ref} className="w-full"></Input>
|
||||
{t("text1")}
|
||||
<Input
|
||||
defaultValue={textPair.text1}
|
||||
ref={input1Ref}
|
||||
className="w-full"
|
||||
></Input>
|
||||
</div>
|
||||
<div>
|
||||
text2<Input defaultValue={textPair.text2} ref={input2Ref} className="w-full"></Input>
|
||||
{t("text2")}
|
||||
<Input
|
||||
defaultValue={textPair.text2}
|
||||
ref={input2Ref}
|
||||
className="w-full"
|
||||
></Input>
|
||||
</div>
|
||||
<div>
|
||||
locale1<Input defaultValue={textPair.locale1} ref={input3Ref} className="w-full"></Input>
|
||||
{t("locale1")}
|
||||
<Input
|
||||
defaultValue={textPair.locale1}
|
||||
ref={input3Ref}
|
||||
className="w-full"
|
||||
></Input>
|
||||
</div>
|
||||
<div>
|
||||
locale2<Input defaultValue={textPair.locale2} ref={input4Ref} className="w-full"></Input>
|
||||
{t("locale2")}
|
||||
<Input
|
||||
defaultValue={textPair.locale2}
|
||||
ref={input4Ref}
|
||||
className="w-full"
|
||||
></Input>
|
||||
</div>
|
||||
</div>
|
||||
<LightButton onClick={handleUpdate}>Update</LightButton>
|
||||
<LightButton onClick={handleUpdate}>{t("update")}</LightButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { redirect } from "next/navigation";
|
||||
import { getServerSession } from "next-auth";
|
||||
import { getTranslations } from "next-intl/server";
|
||||
import InFolder from "./InFolder";
|
||||
import { getOwnerByFolderId } from "@/lib/services/folderService";
|
||||
export default async function FoldersPage({
|
||||
@@ -10,12 +11,14 @@ export default async function FoldersPage({
|
||||
const session = await getServerSession();
|
||||
const { folder_id } = await params;
|
||||
const id = Number(folder_id);
|
||||
const t = await getTranslations("folders.folder_id");
|
||||
|
||||
if (!id) {
|
||||
redirect("/folders");
|
||||
}
|
||||
if (!session?.user?.name) redirect(`/login?redirect=/folders/${id}`);
|
||||
if ((await getOwnerByFolderId(id)) !== session.user.name) {
|
||||
return "you are not the owner of this folder";
|
||||
return <p>{t("unauthorized")}</p>;
|
||||
}
|
||||
return <InFolder folderId={id} />;
|
||||
}
|
||||
|
||||
@@ -7,11 +7,13 @@ import { signIn, useSession } from "next-auth/react";
|
||||
import Image from "next/image";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useEffect } from "react";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export default function LoginPage() {
|
||||
const session = useSession();
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const t = useTranslations("login");
|
||||
|
||||
useEffect(() => {
|
||||
if (session.status === "authenticated") {
|
||||
@@ -22,7 +24,7 @@ export default function LoginPage() {
|
||||
return (
|
||||
<Center>
|
||||
{session.status === "loading" ? (
|
||||
<div>Loading...</div>
|
||||
<div>{t("loading")}</div>
|
||||
) : (
|
||||
<LightButton
|
||||
className="flex flex-row p-2 gap-2"
|
||||
@@ -34,7 +36,7 @@ export default function LoginPage() {
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
<span>GitHub Login</span>
|
||||
<span>{t("githubLogin")}</span>
|
||||
</LightButton>
|
||||
)}
|
||||
</Center>
|
||||
|
||||
@@ -7,11 +7,13 @@ import { useEffect } from "react";
|
||||
import { Center } from "@/components/Center";
|
||||
import Container from "@/components/cards/Container";
|
||||
import LightButton from "@/components/buttons/LightButton";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
export default function MePage() {
|
||||
const session = useSession();
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const t = useTranslations("profile");
|
||||
|
||||
useEffect(() => {
|
||||
if (session.status !== "authenticated") {
|
||||
@@ -22,7 +24,7 @@ export default function MePage() {
|
||||
return (
|
||||
<Center>
|
||||
<Container className="p-6">
|
||||
<h1>My Profile</h1>
|
||||
<h1>{t("myProfile")}</h1>
|
||||
{(session.data?.user?.image as string) && (
|
||||
<Image
|
||||
width={64}
|
||||
@@ -33,8 +35,8 @@ export default function MePage() {
|
||||
></Image>
|
||||
)}
|
||||
<p>{session.data?.user?.name}</p>
|
||||
<p>Email: {session.data?.user?.email}</p>
|
||||
<LightButton onClick={signOut}>Logout</LightButton>
|
||||
<p>{t("email", { email: session.data?.user?.email })}</p>
|
||||
<LightButton onClick={signOut}>{t("logout")}</LightButton>
|
||||
</Container>
|
||||
</Center>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user