Add delete house
This commit is contained in:
@@ -147,9 +147,8 @@
|
||||
"users_page_ui_select_placeholder_role": "Select role",
|
||||
"users_page_ui_select_placeholder_ban_exp": "Select time",
|
||||
"users_page_ui_dialog_alert_title": "Unban this user?",
|
||||
"users_page_ui_dialog_alert_ban_title": "",
|
||||
"users_page_ui_dialog_alert_description": "Detail: \nName: {name}. \nEmail: {email}",
|
||||
"users_page_ui_dialog_alert_description_2": "Reason: {reason}. \nExpiration: {exp}",
|
||||
"users_page_ui_dialog_alert_ban_title": "Lock this user?",
|
||||
"users_page_ui_dialog_alert_description_title": "Detail",
|
||||
"houses_page_ui_title": "Houses",
|
||||
"houses_page_ui_table_header_name": "Name",
|
||||
"houses_page_ui_table_header_members": "Members",
|
||||
@@ -161,9 +160,12 @@
|
||||
"houses_page_form_user": "User",
|
||||
"houses_page_form_create_for": "Create for",
|
||||
"houses_page_form_color": "Color",
|
||||
"houses_page_ui_dialog_alert_delete_title": "Delete house: {name}?",
|
||||
"houses_page_ui_dialog_alert_delete_description": "This action cannot be undone! It will delete all related data like: <b>Box</b>, <b>Item</b>. Please think carefully!",
|
||||
"houses_page_message_create_house_success": "Created house successfully!",
|
||||
"houses_page_message_house_not_found": "House not found!",
|
||||
"houses_page_message_update_house_success": "Updated house successfully!",
|
||||
"houses_page_message_delete_house_success": "Delete house successfully!",
|
||||
"backend_message": [
|
||||
{
|
||||
"match": {
|
||||
|
||||
@@ -149,8 +149,7 @@
|
||||
"users_page_ui_select_placeholder_ban_exp": "Hãy chọn thời gian cấm",
|
||||
"users_page_ui_dialog_alert_title": "Bạn muốn mở khóa người dùng này?",
|
||||
"users_page_ui_dialog_alert_ban_title": "Bạn muốn khóa người dùng này?",
|
||||
"users_page_ui_dialog_alert_description": "Chi tiết: \nTên: {name}. \nEmail: {email}",
|
||||
"users_page_ui_dialog_alert_description_2": "\nLý do: {reason}. \nHiệu lực: {exp}",
|
||||
"users_page_ui_dialog_alert_description_title": "Chi tiết",
|
||||
"houses_page_ui_title": "Nhà",
|
||||
"houses_page_ui_table_header_name": "Tên",
|
||||
"houses_page_ui_table_header_members": "Thành viên",
|
||||
@@ -162,9 +161,12 @@
|
||||
"houses_page_form_user": "Người dùng",
|
||||
"houses_page_form_create_for": "Tạo cho",
|
||||
"houses_page_form_color": "Màu sắc",
|
||||
"houses_page_ui_dialog_alert_delete_title": "Bạn muốn xóa nhà này: {name}?",
|
||||
"houses_page_ui_dialog_alert_delete_description": "Thao tác này không thể hoàn tác! Nó sẽ xóa hết mọi dữ liệu liên quan như: <b>Hộp chứa</b>, <b>Vật Phẩm</b>. Xin suy tính kỹ lưỡng!",
|
||||
"houses_page_message_create_house_success": "Tạo nhà thành công!",
|
||||
"houses_page_message_house_not_found": "Không tìm thấy nhà này!",
|
||||
"houses_page_message_update_house_success": "Cập nhật nhà thành công!",
|
||||
"houses_page_message_delete_house_success": "Xóa nhà thành công!",
|
||||
"backend_message": [
|
||||
{
|
||||
"match": {
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"better-auth": "^1.4.10",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"html-react-parser": "^5.2.16",
|
||||
"next-themes": "^0.4.6",
|
||||
"prisma": "^7.1.0",
|
||||
"radix-ui": "^1.4.3",
|
||||
|
||||
58
pnpm-lock.yaml
generated
58
pnpm-lock.yaml
generated
@@ -9,7 +9,7 @@ importers:
|
||||
.:
|
||||
dependencies:
|
||||
'@base-ui/react':
|
||||
specifier: ^1.1.0
|
||||
specifier: ^1.0.0
|
||||
version: 1.1.0(@types/react@19.2.10)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
'@fontsource-variable/inter':
|
||||
specifier: ^5.2.8
|
||||
@@ -65,6 +65,9 @@ importers:
|
||||
clsx:
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
html-react-parser:
|
||||
specifier: ^5.2.16
|
||||
version: 5.2.16(@types/react@19.2.10)(react@19.2.4)
|
||||
next-themes:
|
||||
specifier: ^0.4.6
|
||||
version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
||||
@@ -81,7 +84,7 @@ importers:
|
||||
specifier: ^19.2.4
|
||||
version: 19.2.4(react@19.2.4)
|
||||
shadcn:
|
||||
specifier: 3.8.2
|
||||
specifier: ^3.6.1
|
||||
version: 3.8.2(@types/node@25.2.0)(hono@4.11.4)(typescript@5.9.3)
|
||||
sonner:
|
||||
specifier: ^2.0.7
|
||||
@@ -3299,10 +3302,22 @@ packages:
|
||||
resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==}
|
||||
engines: {node: '>=16.9.0'}
|
||||
|
||||
html-dom-parser@5.1.7:
|
||||
resolution: {integrity: sha512-Sn+6S3Z8P3P12qqUm4+9wnchC3Bjc4DHp60fgnUdgeiy6e3EbECFWdrmyTBuphxJA5Is7V400+v7ct/Ix2pJFw==}
|
||||
|
||||
html-encoding-sniffer@6.0.0:
|
||||
resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==}
|
||||
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
||||
|
||||
html-react-parser@5.2.16:
|
||||
resolution: {integrity: sha512-1S6KLse1hKWOXYL/PSnZhsARJBE6eIO93CjPlDKMneO0wz8YTnzTfc9Yw4mWsCk2kcB9IrU+R0W6Rdi4N7YfJw==}
|
||||
peerDependencies:
|
||||
'@types/react': 0.14 || 15 || 16 || 17 || 18 || 19
|
||||
react: 0.14 || 15 || 16 || 17 || 18 || 19
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
htmlparser2@10.1.0:
|
||||
resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
|
||||
|
||||
@@ -3360,6 +3375,9 @@ packages:
|
||||
inherits@2.0.4:
|
||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||
|
||||
inline-style-parser@0.2.7:
|
||||
resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
||||
engines: {node: '>= 0.10'}
|
||||
@@ -4087,6 +4105,9 @@ packages:
|
||||
react-is@17.0.2:
|
||||
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
|
||||
|
||||
react-property@2.0.2:
|
||||
resolution: {integrity: sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==}
|
||||
|
||||
react-refresh@0.18.0:
|
||||
resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -4382,6 +4403,12 @@ packages:
|
||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
style-to-js@1.1.21:
|
||||
resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==}
|
||||
|
||||
style-to-object@1.0.14:
|
||||
resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==}
|
||||
|
||||
supports-color@7.2.0:
|
||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -8159,12 +8186,27 @@ snapshots:
|
||||
|
||||
hono@4.11.4: {}
|
||||
|
||||
html-dom-parser@5.1.7:
|
||||
dependencies:
|
||||
domhandler: 5.0.3
|
||||
htmlparser2: 10.1.0
|
||||
|
||||
html-encoding-sniffer@6.0.0(@noble/hashes@2.0.1):
|
||||
dependencies:
|
||||
'@exodus/bytes': 1.11.0(@noble/hashes@2.0.1)
|
||||
transitivePeerDependencies:
|
||||
- '@noble/hashes'
|
||||
|
||||
html-react-parser@5.2.16(@types/react@19.2.10)(react@19.2.4):
|
||||
dependencies:
|
||||
domhandler: 5.0.3
|
||||
html-dom-parser: 5.1.7
|
||||
react: 19.2.4
|
||||
react-property: 2.0.2
|
||||
style-to-js: 1.1.21
|
||||
optionalDependencies:
|
||||
'@types/react': 19.2.10
|
||||
|
||||
htmlparser2@10.1.0:
|
||||
dependencies:
|
||||
domelementtype: 2.3.0
|
||||
@@ -8223,6 +8265,8 @@ snapshots:
|
||||
|
||||
inherits@2.0.4: {}
|
||||
|
||||
inline-style-parser@0.2.7: {}
|
||||
|
||||
ipaddr.js@1.9.1: {}
|
||||
|
||||
is-arrayish@0.2.1: {}
|
||||
@@ -8913,6 +8957,8 @@ snapshots:
|
||||
|
||||
react-is@17.0.2: {}
|
||||
|
||||
react-property@2.0.2: {}
|
||||
|
||||
react-refresh@0.18.0: {}
|
||||
|
||||
react-remove-scroll-bar@2.3.8(@types/react@19.2.10)(react@19.2.4):
|
||||
@@ -9243,6 +9289,14 @@ snapshots:
|
||||
|
||||
strip-json-comments@3.1.1: {}
|
||||
|
||||
style-to-js@1.1.21:
|
||||
dependencies:
|
||||
style-to-object: 1.0.14
|
||||
|
||||
style-to-object@1.0.14:
|
||||
dependencies:
|
||||
inline-style-parser: 0.2.7
|
||||
|
||||
supports-color@7.2.0:
|
||||
dependencies:
|
||||
has-flag: 4.0.0
|
||||
|
||||
@@ -5,7 +5,7 @@ import { formatters } from '@utils/formatters';
|
||||
|
||||
import { LOG_ACTION } from '@/types/enum';
|
||||
import ActionBadge from './action-badge';
|
||||
import ViewDetailAudit from './view-detail-dialog';
|
||||
import ViewDetailAudit from './view-log-detail-dialog';
|
||||
|
||||
export const logColumns: ColumnDef<AuditWithUser>[] = [
|
||||
{
|
||||
|
||||
155
src/components/house/delete-house-dialog.tsx
Normal file
155
src/components/house/delete-house-dialog.tsx
Normal file
@@ -0,0 +1,155 @@
|
||||
import { m } from '@/paraglide/messages';
|
||||
import { deleteHouse } from '@/service/house.api';
|
||||
import { housesQueries } from '@/service/queries';
|
||||
import { ReturnError } from '@/types/common';
|
||||
import useHasPermission from '@hooks/use-has-permission';
|
||||
import usePreventAutoFocus from '@hooks/use-prevent-auto-focus';
|
||||
import { ShieldWarningIcon, TrashIcon } from '@phosphor-icons/react';
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { Button } from '@ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@ui/dialog';
|
||||
import { Label } from '@ui/label';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '@ui/table';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@ui/tooltip';
|
||||
import parse from 'html-react-parser';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import RoleBadge from '../avatar/role-badge';
|
||||
|
||||
type DeleteHouseProps = {
|
||||
data: OrganizationWithMembers;
|
||||
};
|
||||
|
||||
const DeleteHouseAction = ({ data }: DeleteHouseProps) => {
|
||||
const [_open, _setOpen] = useState(false);
|
||||
const prevent = usePreventAutoFocus();
|
||||
const { hasPermission, isLoading } = useHasPermission('house', 'delete');
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { mutate: deleteHouseMutation } = useMutation({
|
||||
mutationFn: deleteHouse,
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: [...housesQueries.all, 'list'],
|
||||
});
|
||||
_setOpen(false);
|
||||
toast.success(m.houses_page_message_delete_house_success(), {
|
||||
richColors: true,
|
||||
});
|
||||
},
|
||||
onError: (error: ReturnError) => {
|
||||
console.error(error);
|
||||
const code = error.code as Parameters<
|
||||
typeof m.backend_message
|
||||
>[0]['code'];
|
||||
toast.error(m.backend_message({ code }), {
|
||||
richColors: true,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const onConfirm = () => {
|
||||
deleteHouseMutation({ data });
|
||||
};
|
||||
|
||||
if (isLoading) return null;
|
||||
|
||||
if (hasPermission) {
|
||||
return (
|
||||
<Dialog open={_open} onOpenChange={_setOpen}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<DialogTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="rounded-full cursor-pointer text-red-500 hover:bg-red-100 hover:text-red-600"
|
||||
>
|
||||
<TrashIcon size={16} />
|
||||
<span className="sr-only">{m.ui_delete_btn()}</span>
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="bg-red-500 [&_svg]:bg-red-500 [&_svg]:fill-red-500 text-white">
|
||||
<Label>{m.ui_delete_btn()}</Label>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<DialogContent
|
||||
className="max-w-100 xl:max-w-xl"
|
||||
showCloseButton={false}
|
||||
{...prevent}
|
||||
onPointerDownOutside={(e) => e.preventDefault()}
|
||||
onEscapeKeyDown={(e) => e.preventDefault()}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-3 text-lg font-bold text-red-500">
|
||||
<div className="rounded-full bg-red-100 p-3">
|
||||
<ShieldWarningIcon size={30} />
|
||||
</div>
|
||||
{m.houses_page_ui_dialog_alert_delete_title({ name: data.name })}
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-red-500">
|
||||
{parse(m.houses_page_ui_dialog_alert_delete_description())}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<div className="overflow-hidden rounded-md border">
|
||||
<Table className="bg-white">
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead className="px-2 h-7 bg-primary text-white text-xs w-1/2">
|
||||
{m.houses_page_ui_view_table_header_email()}
|
||||
</TableHead>
|
||||
<TableHead className="px-2 h-7 bg-primary text-white text-xs w-1/2">
|
||||
{m.houses_page_ui_view_table_header_role()}
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{data.members.map((member) => (
|
||||
<TableRow key={member.user.email}>
|
||||
<TableCell>{member.user.email}</TableCell>
|
||||
<TableCell>
|
||||
<RoleBadge type={member.role} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<DialogFooter className="bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4">
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" type="button">
|
||||
{m.ui_cancel_btn()}
|
||||
</Button>
|
||||
</DialogClose>
|
||||
<Button variant="destructive" type="button" onClick={onConfirm}>
|
||||
{m.ui_confirm_btn()}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default DeleteHouseAction;
|
||||
@@ -1,8 +1,9 @@
|
||||
import { m } from '@paraglide/messages';
|
||||
import { ColumnDef } from '@tanstack/react-table';
|
||||
import { formatters } from '@utils/formatters';
|
||||
import DeleteHouseAction from './delete-house-dialog';
|
||||
import EditHouseAction from './edit-house-dialog';
|
||||
import ViewDetailHouse from './view-detail-dialog';
|
||||
import ViewDetailHouse from './view-house-detail-dialog';
|
||||
|
||||
export const houseColumns: ColumnDef<OrganizationWithMembers>[] = [
|
||||
{
|
||||
@@ -42,6 +43,7 @@ export const houseColumns: ColumnDef<OrganizationWithMembers>[] = [
|
||||
<div className="flex justify-end gap-2">
|
||||
<ViewDetailHouse data={row.original} />
|
||||
<EditHouseAction data={row.original} />
|
||||
<DeleteHouseAction data={row.original} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
@@ -17,7 +17,14 @@ import {
|
||||
} from '@ui/dialog';
|
||||
import { UserWithRole } from 'better-auth/plugins';
|
||||
import { toast } from 'sonner';
|
||||
import DisplayBreakLineMessage from '../DisplayBreakLineMessage';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from '../ui/table';
|
||||
import { useBanContext } from './ban-user-dialog';
|
||||
|
||||
type BanConfirmProps = {
|
||||
@@ -74,20 +81,49 @@ const BanUserConfirm = ({ data }: BanConfirmProps) => {
|
||||
{m.users_page_ui_dialog_alert_ban_title()}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<DisplayBreakLineMessage>
|
||||
{m.users_page_ui_dialog_alert_description({
|
||||
name: data.name,
|
||||
email: data.email,
|
||||
})}
|
||||
{m.users_page_ui_dialog_alert_description_2({
|
||||
reason: submitData.banReason,
|
||||
exp: m.exp_time({
|
||||
time: submitData.banExp.toString() as Parameters<
|
||||
typeof m.exp_time
|
||||
>[0]['time'],
|
||||
}),
|
||||
})}
|
||||
</DisplayBreakLineMessage>
|
||||
<div className="overflow-hidden rounded-md border">
|
||||
<Table className="bg-white">
|
||||
<TableHeader>
|
||||
<TableRow className="bg-primary">
|
||||
<TableHead className="px-2 h-7 text-white text-xs" colSpan={2}>
|
||||
{m.users_page_ui_dialog_alert_description_title()}
|
||||
</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell className="font-bold">
|
||||
{m.users_page_ui_table_header_name()}:
|
||||
</TableCell>
|
||||
<TableCell>{data.name}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="font-bold">
|
||||
{m.users_page_ui_table_header_email()}:
|
||||
</TableCell>
|
||||
<TableCell>{data.email}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="font-bold">
|
||||
{m.users_page_ui_form_ban_reason()}:
|
||||
</TableCell>
|
||||
<TableCell>{submitData.banReason}</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell className="font-bold">
|
||||
{m.users_page_ui_form_ban_exp()}:
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
{m.exp_time({
|
||||
time: submitData.banExp.toString() as Parameters<
|
||||
typeof m.exp_time
|
||||
>[0]['time'],
|
||||
})}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
<DialogFooter className="bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4">
|
||||
<DialogClose asChild>
|
||||
<Button variant="outline" type="button">
|
||||
|
||||
@@ -6,6 +6,7 @@ import { authMiddleware } from '@lib/middleware';
|
||||
import { createServerFn } from '@tanstack/react-start';
|
||||
import { parseError } from '@utils/helper';
|
||||
import {
|
||||
baseHouse,
|
||||
houseCreateBESchema,
|
||||
houseEditBESchema,
|
||||
houseListSchema,
|
||||
@@ -137,3 +138,42 @@ export const updateHouse = createServerFn({ method: 'POST' })
|
||||
throw { message, code };
|
||||
}
|
||||
});
|
||||
|
||||
export const deleteHouse = createServerFn({ method: 'POST' })
|
||||
.middleware([authMiddleware])
|
||||
.inputValidator(baseHouse)
|
||||
.handler(async ({ data, context: { user } }) => {
|
||||
try {
|
||||
const currentHouse = await prisma.organization.findUnique({
|
||||
where: { id: data.id },
|
||||
});
|
||||
if (!currentHouse) throw Error('House not found');
|
||||
|
||||
const result = await Promise.all([
|
||||
prisma.organization.delete({
|
||||
where: { id: data.id },
|
||||
}),
|
||||
prisma.member.deleteMany({
|
||||
where: { organizationId: data.id },
|
||||
}),
|
||||
prisma.invitation.deleteMany({
|
||||
where: { organizationId: data.id },
|
||||
}),
|
||||
]);
|
||||
|
||||
await createAuditLog({
|
||||
action: LOG_ACTION.DELETE,
|
||||
tableName: DB_TABLE.ORGANIZATION,
|
||||
recordId: result[0]?.id,
|
||||
oldValue: JSON.stringify(currentHouse),
|
||||
newValue: '',
|
||||
userId: user.id,
|
||||
});
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
const { message, code } = parseError(error);
|
||||
throw { message, code };
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user