This commit is contained in:
2026-02-06 03:28:53 +08:00
parent 2537b9fe75
commit 8ed9b011f4
7 changed files with 141 additions and 29 deletions

View File

@@ -15,7 +15,7 @@ import { TSharedPair } from "@/shared/folder-type";
import { toast } from "sonner";
export function InFolder({ folderId }: { folderId: number; }) {
export function InFolder({ folderId, isReadOnly }: { folderId: number; isReadOnly: boolean; }) {
const [textPairs, setTextPairs] = useState<TSharedPair[]>([]);
const [loading, setLoading] = useState(true);
const [openAddModal, setAddModal] = useState(false);
@@ -81,12 +81,14 @@ export function InFolder({ folderId }: { folderId: number; }) {
>
{t("memorize")}
</GreenButton>
<IconButton
onClick={() => {
setAddModal(true);
}}
icon={<Plus size={18} className="text-gray-700" />}
/>
{!isReadOnly && (
<IconButton
onClick={() => {
setAddModal(true);
}}
icon={<Plus size={18} className="text-gray-700" />}
/>
)}
</div>
</div>
</div>
@@ -113,6 +115,7 @@ export function InFolder({ folderId }: { folderId: number; }) {
<TextPairCard
key={textPair.id}
textPair={textPair}
isReadOnly={isReadOnly}
onDel={() => {
actionDeletePairById(textPair.id)
.then(result => {

View File

@@ -9,12 +9,14 @@ import { toast } from "sonner";
interface TextPairCardProps {
textPair: TSharedPair;
isReadOnly: boolean;
onDel: () => void;
refreshTextPairs: () => void;
}
export function TextPairCard({
textPair,
isReadOnly,
onDel,
refreshTextPairs,
}: TextPairCardProps) {
@@ -35,20 +37,24 @@ export function TextPairCard({
</div>
<div className="flex items-center gap-1 opacity-50 group-hover:opacity-100 transition-opacity">
<button
className="p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-md transition-colors"
onClick={() => setOpenUpdateModal(true)}
title={t("edit")}
>
<Edit size={14} />
</button>
<button
className="p-1.5 text-gray-400 hover:text-red-500 hover:bg-red-50 rounded-md transition-colors"
onClick={onDel}
title={t("delete")}
>
<Trash2 size={14} />
</button>
{!isReadOnly && (
<>
<button
className="p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded-md transition-colors"
onClick={() => setOpenUpdateModal(true)}
title={t("edit")}
>
<Edit size={14} />
</button>
<button
className="p-1.5 text-gray-400 hover:text-red-500 hover:bg-red-50 rounded-md transition-colors"
onClick={onDel}
title={t("delete")}
>
<Trash2 size={14} />
</button>
</>
)}
</div>
</div>
<div className="text-gray-900 grid grid-cols-2 gap-4 w-3/4">

View File

@@ -4,6 +4,7 @@ import { InFolder } from "./InFolder";
import { auth } from "@/auth";
import { headers } from "next/headers";
import { actionGetUserIdByFolderId } from "@/modules/folder/folder-aciton";
export default async function FoldersPage({
params,
}: {
@@ -16,9 +17,11 @@ export default async function FoldersPage({
if (!folder_id) {
redirect("/folders");
}
if (!session) redirect(`/auth?redirect=/folders/${folder_id}`);
if ((await actionGetUserIdByFolderId(Number(folder_id))).data !== session.user.id) {
return <p>{t("unauthorized")}</p>;
}
return <InFolder folderId={Number(folder_id)} />;
// Allow non-authenticated users to view folders (read-only mode)
const folderUserId = (await actionGetUserIdByFolderId(Number(folder_id))).data;
const isOwner = session?.user?.id === folderUserId;
const isReadOnly = !isOwner;
return <InFolder folderId={Number(folder_id)} isReadOnly={isReadOnly} />;
}