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_role": "Select role",
|
||||||
"users_page_ui_select_placeholder_ban_exp": "Select time",
|
"users_page_ui_select_placeholder_ban_exp": "Select time",
|
||||||
"users_page_ui_dialog_alert_title": "Unban this user?",
|
"users_page_ui_dialog_alert_title": "Unban this user?",
|
||||||
"users_page_ui_dialog_alert_ban_title": "",
|
"users_page_ui_dialog_alert_ban_title": "Lock this user?",
|
||||||
"users_page_ui_dialog_alert_description": "Detail: \nName: {name}. \nEmail: {email}",
|
"users_page_ui_dialog_alert_description_title": "Detail",
|
||||||
"users_page_ui_dialog_alert_description_2": "Reason: {reason}. \nExpiration: {exp}",
|
|
||||||
"houses_page_ui_title": "Houses",
|
"houses_page_ui_title": "Houses",
|
||||||
"houses_page_ui_table_header_name": "Name",
|
"houses_page_ui_table_header_name": "Name",
|
||||||
"houses_page_ui_table_header_members": "Members",
|
"houses_page_ui_table_header_members": "Members",
|
||||||
@@ -161,9 +160,12 @@
|
|||||||
"houses_page_form_user": "User",
|
"houses_page_form_user": "User",
|
||||||
"houses_page_form_create_for": "Create for",
|
"houses_page_form_create_for": "Create for",
|
||||||
"houses_page_form_color": "Color",
|
"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_create_house_success": "Created house successfully!",
|
||||||
"houses_page_message_house_not_found": "House not found!",
|
"houses_page_message_house_not_found": "House not found!",
|
||||||
"houses_page_message_update_house_success": "Updated house successfully!",
|
"houses_page_message_update_house_success": "Updated house successfully!",
|
||||||
|
"houses_page_message_delete_house_success": "Delete house successfully!",
|
||||||
"backend_message": [
|
"backend_message": [
|
||||||
{
|
{
|
||||||
"match": {
|
"match": {
|
||||||
|
|||||||
@@ -149,8 +149,7 @@
|
|||||||
"users_page_ui_select_placeholder_ban_exp": "Hãy chọn thời gian cấm",
|
"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_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_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_title": "Chi tiết",
|
||||||
"users_page_ui_dialog_alert_description_2": "\nLý do: {reason}. \nHiệu lực: {exp}",
|
|
||||||
"houses_page_ui_title": "Nhà",
|
"houses_page_ui_title": "Nhà",
|
||||||
"houses_page_ui_table_header_name": "Tên",
|
"houses_page_ui_table_header_name": "Tên",
|
||||||
"houses_page_ui_table_header_members": "Thành viê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_user": "Người dùng",
|
||||||
"houses_page_form_create_for": "Tạo cho",
|
"houses_page_form_create_for": "Tạo cho",
|
||||||
"houses_page_form_color": "Màu sắc",
|
"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_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_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_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": [
|
"backend_message": [
|
||||||
{
|
{
|
||||||
"match": {
|
"match": {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"better-auth": "^1.4.10",
|
"better-auth": "^1.4.10",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
|
"html-react-parser": "^5.2.16",
|
||||||
"next-themes": "^0.4.6",
|
"next-themes": "^0.4.6",
|
||||||
"prisma": "^7.1.0",
|
"prisma": "^7.1.0",
|
||||||
"radix-ui": "^1.4.3",
|
"radix-ui": "^1.4.3",
|
||||||
|
|||||||
58
pnpm-lock.yaml
generated
58
pnpm-lock.yaml
generated
@@ -9,7 +9,7 @@ importers:
|
|||||||
.:
|
.:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@base-ui/react':
|
'@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)
|
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':
|
'@fontsource-variable/inter':
|
||||||
specifier: ^5.2.8
|
specifier: ^5.2.8
|
||||||
@@ -65,6 +65,9 @@ importers:
|
|||||||
clsx:
|
clsx:
|
||||||
specifier: ^2.1.1
|
specifier: ^2.1.1
|
||||||
version: 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:
|
next-themes:
|
||||||
specifier: ^0.4.6
|
specifier: ^0.4.6
|
||||||
version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4)
|
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
|
specifier: ^19.2.4
|
||||||
version: 19.2.4(react@19.2.4)
|
version: 19.2.4(react@19.2.4)
|
||||||
shadcn:
|
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)
|
version: 3.8.2(@types/node@25.2.0)(hono@4.11.4)(typescript@5.9.3)
|
||||||
sonner:
|
sonner:
|
||||||
specifier: ^2.0.7
|
specifier: ^2.0.7
|
||||||
@@ -3299,10 +3302,22 @@ packages:
|
|||||||
resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==}
|
resolution: {integrity: sha512-U7tt8JsyrxSRKspfhtLET79pU8K+tInj5QZXs1jSugO1Vq5dFj3kmZsRldo29mTBfcjDRVRXrEZ6LS63Cog9ZA==}
|
||||||
engines: {node: '>=16.9.0'}
|
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:
|
html-encoding-sniffer@6.0.0:
|
||||||
resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==}
|
resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==}
|
||||||
engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0}
|
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:
|
htmlparser2@10.1.0:
|
||||||
resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
|
resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
|
||||||
|
|
||||||
@@ -3360,6 +3375,9 @@ packages:
|
|||||||
inherits@2.0.4:
|
inherits@2.0.4:
|
||||||
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
|
||||||
|
|
||||||
|
inline-style-parser@0.2.7:
|
||||||
|
resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==}
|
||||||
|
|
||||||
ipaddr.js@1.9.1:
|
ipaddr.js@1.9.1:
|
||||||
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
@@ -4087,6 +4105,9 @@ packages:
|
|||||||
react-is@17.0.2:
|
react-is@17.0.2:
|
||||||
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
|
resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
|
||||||
|
|
||||||
|
react-property@2.0.2:
|
||||||
|
resolution: {integrity: sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==}
|
||||||
|
|
||||||
react-refresh@0.18.0:
|
react-refresh@0.18.0:
|
||||||
resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
|
resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -4382,6 +4403,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
|
||||||
engines: {node: '>=8'}
|
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:
|
supports-color@7.2.0:
|
||||||
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -8159,12 +8186,27 @@ snapshots:
|
|||||||
|
|
||||||
hono@4.11.4: {}
|
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):
|
html-encoding-sniffer@6.0.0(@noble/hashes@2.0.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@exodus/bytes': 1.11.0(@noble/hashes@2.0.1)
|
'@exodus/bytes': 1.11.0(@noble/hashes@2.0.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@noble/hashes'
|
- '@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:
|
htmlparser2@10.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
domelementtype: 2.3.0
|
domelementtype: 2.3.0
|
||||||
@@ -8223,6 +8265,8 @@ snapshots:
|
|||||||
|
|
||||||
inherits@2.0.4: {}
|
inherits@2.0.4: {}
|
||||||
|
|
||||||
|
inline-style-parser@0.2.7: {}
|
||||||
|
|
||||||
ipaddr.js@1.9.1: {}
|
ipaddr.js@1.9.1: {}
|
||||||
|
|
||||||
is-arrayish@0.2.1: {}
|
is-arrayish@0.2.1: {}
|
||||||
@@ -8913,6 +8957,8 @@ snapshots:
|
|||||||
|
|
||||||
react-is@17.0.2: {}
|
react-is@17.0.2: {}
|
||||||
|
|
||||||
|
react-property@2.0.2: {}
|
||||||
|
|
||||||
react-refresh@0.18.0: {}
|
react-refresh@0.18.0: {}
|
||||||
|
|
||||||
react-remove-scroll-bar@2.3.8(@types/react@19.2.10)(react@19.2.4):
|
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: {}
|
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:
|
supports-color@7.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
has-flag: 4.0.0
|
has-flag: 4.0.0
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { formatters } from '@utils/formatters';
|
|||||||
|
|
||||||
import { LOG_ACTION } from '@/types/enum';
|
import { LOG_ACTION } from '@/types/enum';
|
||||||
import ActionBadge from './action-badge';
|
import ActionBadge from './action-badge';
|
||||||
import ViewDetailAudit from './view-detail-dialog';
|
import ViewDetailAudit from './view-log-detail-dialog';
|
||||||
|
|
||||||
export const logColumns: ColumnDef<AuditWithUser>[] = [
|
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 { m } from '@paraglide/messages';
|
||||||
import { ColumnDef } from '@tanstack/react-table';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import { formatters } from '@utils/formatters';
|
import { formatters } from '@utils/formatters';
|
||||||
|
import DeleteHouseAction from './delete-house-dialog';
|
||||||
import EditHouseAction from './edit-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>[] = [
|
export const houseColumns: ColumnDef<OrganizationWithMembers>[] = [
|
||||||
{
|
{
|
||||||
@@ -42,6 +43,7 @@ export const houseColumns: ColumnDef<OrganizationWithMembers>[] = [
|
|||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
<ViewDetailHouse data={row.original} />
|
<ViewDetailHouse data={row.original} />
|
||||||
<EditHouseAction data={row.original} />
|
<EditHouseAction data={row.original} />
|
||||||
|
<DeleteHouseAction data={row.original} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -17,7 +17,14 @@ import {
|
|||||||
} from '@ui/dialog';
|
} from '@ui/dialog';
|
||||||
import { UserWithRole } from 'better-auth/plugins';
|
import { UserWithRole } from 'better-auth/plugins';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import DisplayBreakLineMessage from '../DisplayBreakLineMessage';
|
import {
|
||||||
|
Table,
|
||||||
|
TableBody,
|
||||||
|
TableCell,
|
||||||
|
TableHead,
|
||||||
|
TableHeader,
|
||||||
|
TableRow,
|
||||||
|
} from '../ui/table';
|
||||||
import { useBanContext } from './ban-user-dialog';
|
import { useBanContext } from './ban-user-dialog';
|
||||||
|
|
||||||
type BanConfirmProps = {
|
type BanConfirmProps = {
|
||||||
@@ -74,20 +81,49 @@ const BanUserConfirm = ({ data }: BanConfirmProps) => {
|
|||||||
{m.users_page_ui_dialog_alert_ban_title()}
|
{m.users_page_ui_dialog_alert_ban_title()}
|
||||||
</DialogDescription>
|
</DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<DisplayBreakLineMessage>
|
<div className="overflow-hidden rounded-md border">
|
||||||
{m.users_page_ui_dialog_alert_description({
|
<Table className="bg-white">
|
||||||
name: data.name,
|
<TableHeader>
|
||||||
email: data.email,
|
<TableRow className="bg-primary">
|
||||||
})}
|
<TableHead className="px-2 h-7 text-white text-xs" colSpan={2}>
|
||||||
{m.users_page_ui_dialog_alert_description_2({
|
{m.users_page_ui_dialog_alert_description_title()}
|
||||||
reason: submitData.banReason,
|
</TableHead>
|
||||||
exp: m.exp_time({
|
</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<
|
time: submitData.banExp.toString() as Parameters<
|
||||||
typeof m.exp_time
|
typeof m.exp_time
|
||||||
>[0]['time'],
|
>[0]['time'],
|
||||||
}),
|
|
||||||
})}
|
})}
|
||||||
</DisplayBreakLineMessage>
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
<DialogFooter className="bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4">
|
<DialogFooter className="bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4">
|
||||||
<DialogClose asChild>
|
<DialogClose asChild>
|
||||||
<Button variant="outline" type="button">
|
<Button variant="outline" type="button">
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { authMiddleware } from '@lib/middleware';
|
|||||||
import { createServerFn } from '@tanstack/react-start';
|
import { createServerFn } from '@tanstack/react-start';
|
||||||
import { parseError } from '@utils/helper';
|
import { parseError } from '@utils/helper';
|
||||||
import {
|
import {
|
||||||
|
baseHouse,
|
||||||
houseCreateBESchema,
|
houseCreateBESchema,
|
||||||
houseEditBESchema,
|
houseEditBESchema,
|
||||||
houseListSchema,
|
houseListSchema,
|
||||||
@@ -137,3 +138,42 @@ export const updateHouse = createServerFn({ method: 'POST' })
|
|||||||
throw { message, code };
|
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