From 18271a7d69b8b6c1f6e33ec2c8ee168506d45abb Mon Sep 17 00:00:00 2001 From: sk1982 Date: Tue, 2 Apr 2024 01:50:39 -0400 Subject: [PATCH] add card deletion --- src/actions/card.ts | 21 ++++++++++++++++--- .../admin/users/admin-user-list.tsx | 12 +++++++++-- src/app/(with-header)/settings/cards.tsx | 11 ++++++---- src/app/(with-header)/settings/page.tsx | 2 +- src/components/aime-card.tsx | 18 +++++++++++++--- src/data/user.ts | 3 ++- 6 files changed, 53 insertions(+), 14 deletions(-) diff --git a/src/actions/card.ts b/src/actions/card.ts index 9396a05..348c930 100644 --- a/src/actions/card.ts +++ b/src/actions/card.ts @@ -12,9 +12,9 @@ import { getGlobalConfig } from '@/config'; import { UserPayload } from '@/types/user'; import { DB } from '@/types/db'; -export const getCards = async (user: UserPayload) => { +export const getCards = async (user: number) => { return db.selectFrom('aime_card') - .where('user', '=', user.id) + .where('user', '=', user) .selectAll() .execute(); }; @@ -65,11 +65,26 @@ export const adminAddCardToUser = async (user: number, code: string): Promise { + const requestingUser = await requireUser(); + + if (requestingUser.id !== user) + requirePermission(requestingUser.permissions, UserPermissions.USERMOD); + + await db.deleteFrom('aime_card') + .where('id', '=', id) + .where('user', '=', user) + .executeTakeFirst(); + + revalidatePath('/settings', 'page'); + revalidatePath('/admin/users', 'page'); +}; + export const userAddCard = async (code: string): Promise> => { const user = await requireUser(); if (!hasPermission(user.permissions, UserPermissions.USERMOD)) { - const cards = await getCards(user); + const cards = await getCards(user.id); if (!getGlobalConfig('allow_user_add_card')) return { error: true, message: 'You do not have permissions to add a card' }; diff --git a/src/app/(with-header)/admin/users/admin-user-list.tsx b/src/app/(with-header)/admin/users/admin-user-list.tsx index cf9afc4..3b2134e 100644 --- a/src/app/(with-header)/admin/users/admin-user-list.tsx +++ b/src/app/(with-header)/admin/users/admin-user-list.tsx @@ -12,7 +12,7 @@ import { hasPermission } from '@/helpers/permissions'; import { AimeCard } from '@/components/aime-card'; import { useErrorModal } from '@/components/error-modal'; import { AdminUser } from '@/data/user'; -import { adminAddCardToUser } from '@/actions/card'; +import { adminAddCardToUser, deleteCard } from '@/actions/card'; import { TrashIcon } from '@heroicons/react/24/outline'; import { useConfirmModal } from '@/components/confirm-modal'; import Link from 'next/link'; @@ -75,7 +75,7 @@ export const AdminUserList = ({ users: initialUsers }: { users: AdminUser[]; }) onSelectionChange={s => typeof s !== 'string' && setOpenUsers(s)} className="my-1 border-b sm:border-b-0 border-divider sm:bg-content1 sm:rounded-lg sm:px-4 overflow-hidden"> - {users.map(userEntry => ( (
@@ -142,6 +142,14 @@ export const AdminUserList = ({ users: initialUsers }: { users: AdminUser[]; })
{userEntry.cards.map(c => { + deleteCard(c.user!, c.id!); + setUsers(u => u.map(u => u.id === userEntry.id ? { + ...u, + cards: u.cards.filter(card => card.id !== c.id) + } : u)); + }} card={{ ...c, created_date: new Date(c.created_date!), diff --git a/src/app/(with-header)/settings/cards.tsx b/src/app/(with-header)/settings/cards.tsx index 26f9502..e22a446 100644 --- a/src/app/(with-header)/settings/cards.tsx +++ b/src/app/(with-header)/settings/cards.tsx @@ -11,7 +11,7 @@ import { UserPermissions } from '@/types/permissions'; import { hasPermission } from '@/helpers/permissions'; import { useErrorModal } from '@/components/error-modal'; import { useState } from 'react'; -import { userAddCard } from '@/actions/card'; +import { deleteCard, userAddCard } from '@/actions/card'; export type CardsProps = { cards: DB['aime_card'][], @@ -21,7 +21,7 @@ export type CardsProps = { export const Cards = ({ cards: initialCards, canAddCard, maxCard }: CardsProps) => { const prompt = usePromptModal(); - const user = useUser(); + const user = useUser({ required: true }); const setError = useErrorModal(); const [cards, setCards] = useState(initialCards); @@ -29,7 +29,7 @@ export const Cards = ({ cards: initialCards, canAddCard, maxCard }: CardsProps)
Cards - {(hasPermission(user?.permissions, UserPermissions.USERMOD) || + {(hasPermission(user.permissions, UserPermissions.USERMOD) || (canAddCard && cards.length < (maxCard ?? Infinity))) &&
- {cards.map(c => )} + {cards.map(c => { + deleteCard(user.id, c.id); + setCards(cards => cards.filter(card => card.id !== c.id)); + }} />)}
); }; diff --git a/src/app/(with-header)/settings/page.tsx b/src/app/(with-header)/settings/page.tsx index 291d93e..6f29a1e 100644 --- a/src/app/(with-header)/settings/page.tsx +++ b/src/app/(with-header)/settings/page.tsx @@ -7,7 +7,7 @@ import { getGlobalConfig } from '@/config'; export default async function SettingsPage() { const user = await requireUser(); - const cards = await getCards(user); + const cards = await getCards(user.id); return (
diff --git a/src/components/aime-card.tsx b/src/components/aime-card.tsx index 4060d3b..57758a1 100644 --- a/src/components/aime-card.tsx +++ b/src/components/aime-card.tsx @@ -5,22 +5,27 @@ import { useState } from 'react'; import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline'; import { Button, Tooltip } from '@nextui-org/react'; import { useUser } from '@/helpers/use-user'; -import { TbHammer, TbHammerOff, TbLock, TbLockOpen } from 'react-icons/tb'; +import { TbHammer, TbHammerOff, TbLock, TbLockOpen, TbTrashX } from 'react-icons/tb'; import { hasPermission } from '@/helpers/permissions'; import { UserPermissions } from '@/types/permissions'; import { banUnbanCard, lockUnlockCard } from '@/actions/card'; +import { useConfirmModal } from './confirm-modal'; type AimeCardProps = { card: DB['aime_card'], className?: string, + canDelete?: boolean, + onDelete?: () => void }; -export const AimeCard = ({ className, card }: AimeCardProps) => { +export const AimeCard = ({ className, card, canDelete, onDelete }: AimeCardProps) => { const [showCode, setShowCode] = useState(false); const user = useUser(); const canBan = hasPermission(user?.permissions, UserPermissions.USERMOD); const [locked, setLocked] = useState(!!card.is_locked ?? false); const [banned, setBanned] = useState(!!card.is_banned ?? true); + const confirm = useConfirmModal(); + const formatOptions = { year: '2-digit', month: 'numeric', @@ -73,9 +78,16 @@ export const AimeCard = ({ className, card }: AimeCardProps) => { }
-
+
{card.last_login_date ? `Last Used ${card.last_login_date.toLocaleTimeString(undefined, formatOptions)}` : 'Never Used'} + + {canDelete && Delete this card}> + + }
{(locked || banned) &&
diff --git a/src/data/user.ts b/src/data/user.ts index 1180c26..1feae0d 100644 --- a/src/data/user.ts +++ b/src/data/user.ts @@ -88,7 +88,8 @@ export const getUsers = async () => { ] as const) .execute(); - return parseJsonResult(res, ['cards']); + const data = parseJsonResult(res, ['cards']); + return data.map(d => ({ ...d, cards: d.cards.filter(c => c.id !== null) })); }; export type AdminUser = Awaited>[number];