property-practice-ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +3 -0
- package/.prettierrc +4 -0
- package/.storybook/main.ts +30 -0
- package/.storybook/preview.ts +32 -0
- package/.storybook/vitest.setup.ts +6 -0
- package/CHANGELOG.md +7 -0
- package/dist/index.js +10148 -0
- package/dist/index.mjs +10148 -0
- package/eslint.config.mjs +4 -0
- package/package.json +63 -0
- package/postcss.config.js +6 -0
- package/src/atoms/ArrowButton/ArrowButton.stories.tsx +52 -0
- package/src/atoms/ArrowButton/ArrowButton.tsx +71 -0
- package/src/atoms/Button/Button.stories.tsx +45 -0
- package/src/atoms/Button/Button.tsx +91 -0
- package/src/atoms/CheckboxItem/CheckboxItem.tsx +49 -0
- package/src/atoms/Description/Description.tsx +43 -0
- package/src/atoms/ExtendedButton/ExtendedButton.stories.tsx +61 -0
- package/src/atoms/ExtendedButton/ExtendedButton.tsx +40 -0
- package/src/atoms/FeatureItem/FeatureItem.stories.tsx +25 -0
- package/src/atoms/FeatureItem/FeatureItem.tsx +90 -0
- package/src/atoms/FormContainer/FormContainer.tsx +34 -0
- package/src/atoms/Header/Header.stories.tsx +22 -0
- package/src/atoms/Header/Header.tsx +53 -0
- package/src/atoms/Input/Input.stories.tsx +23 -0
- package/src/atoms/Input/Input.tsx +28 -0
- package/src/atoms/Label/Label.stories.tsx +28 -0
- package/src/atoms/Label/Label.tsx +53 -0
- package/src/atoms/Loader/Loader.tsx +49 -0
- package/src/atoms/Pill/Pill.stories.tsx +30 -0
- package/src/atoms/Pill/Pill.tsx +82 -0
- package/src/atoms/RadioItem/RadioItem.stories.tsx +25 -0
- package/src/atoms/RadioItem/RadioItem.tsx +54 -0
- package/src/atoms/SecondaryInput/SecondaryInput.stories.tsx +30 -0
- package/src/atoms/SecondaryInput/SecondaryInput.tsx +125 -0
- package/src/atoms/SocialButton/SocialButton.stories.tsx +79 -0
- package/src/atoms/SocialButton/SocialButton.tsx +90 -0
- package/src/atoms/TermsCheckbox/TermsCheckbox.stories.tsx +62 -0
- package/src/atoms/TermsCheckbox/TermsCheckbox.tsx +150 -0
- package/src/atoms/Text/Text.stories.tsx +32 -0
- package/src/atoms/Text/Text.tsx +49 -0
- package/src/atoms/TextButton/TextButton.stories.tsx +77 -0
- package/src/atoms/TextButton/TextButton.tsx +78 -0
- package/src/atoms/Textarea/Textarea.tsx +36 -0
- package/src/atoms/ToggleButton/ToggleButton.stories.tsx +32 -0
- package/src/atoms/ToggleButton/ToggleButton.tsx +106 -0
- package/src/atoms/index.ts +20 -0
- package/src/components/DynamicInput.tsx +54 -0
- package/src/components/FileUpload.tsx +123 -0
- package/src/components/Filter/Filter.tsx +33 -0
- package/src/components/ModeSwitch.tsx +66 -0
- package/src/components/NavMenu.tsx +83 -0
- package/src/components/SearchBar/Search.stories.tsx +25 -0
- package/src/components/SearchBar/Search.tsx +40 -0
- package/src/components/SortBy/SortBy.stories.tsx +27 -0
- package/src/components/SortBy/SortBy.tsx +45 -0
- package/src/components/Spinner.tsx +30 -0
- package/src/components/Table/Table.stories.tsx +56 -0
- package/src/components/Table/Table.tsx +25 -0
- package/src/components/TableInner/TableInner.tsx +27 -0
- package/src/components/TableInner/tableInner.stories.tsx +21 -0
- package/src/components/TableList.tsx +195 -0
- package/src/components/TableRow/TableRow.stories.tsx +55 -0
- package/src/components/TableRow/TableRow.tsx +343 -0
- package/src/components/Tabs/Tabs.stories.tsx +42 -0
- package/src/components/Tabs/Tabs.tsx +56 -0
- package/src/components/Toast.tsx +192 -0
- package/src/components/TopMenu.tsx +62 -0
- package/src/index.ts +20 -0
- package/src/molecules/Accordion/Accordion.stories.tsx +54 -0
- package/src/molecules/Accordion/Accordion.tsx +45 -0
- package/src/molecules/AccordionContent/AccordionContent.tsx +16 -0
- package/src/molecules/AccordionHeader/AccordionHeader.stories.tsx +31 -0
- package/src/molecules/AccordionHeader/AccordionHeader.tsx +67 -0
- package/src/molecules/Address/Address.stories.tsx +116 -0
- package/src/molecules/Address/Address.tsx +136 -0
- package/src/molecules/CTAContainer/CTAContainer.stories.tsx +67 -0
- package/src/molecules/CTAContainer/CTAContainer.tsx +98 -0
- package/src/molecules/Checkbox/Checkbox.tsx +60 -0
- package/src/molecules/ContentCard/ContentCard.stories.tsx +31 -0
- package/src/molecules/ContentCard/ContentCard.tsx +80 -0
- package/src/molecules/DocumentAccordionHeader/DocumentAccordionHeader.tsx +50 -0
- package/src/molecules/DocumentAccordionRow/DocumentAccordionRow.tsx +66 -0
- package/src/molecules/Dropdown/Dropdown.stories.tsx +39 -0
- package/src/molecules/Dropdown/Dropdown.tsx +89 -0
- package/src/molecules/EmptyState/EmptyState.stories.tsx +26 -0
- package/src/molecules/EmptyState/EmptyState.tsx +49 -0
- package/src/molecules/FAQAccordion/FAQAccordion.stories.tsx +63 -0
- package/src/molecules/FAQAccordion/FAQAccordion.tsx +98 -0
- package/src/molecules/FeatureContainer/FeatureContainer.stories.tsx +40 -0
- package/src/molecules/FeatureContainer/FeatureContainer.tsx +59 -0
- package/src/molecules/FileButton/FileButton.tsx +54 -0
- package/src/molecules/Input/Input.stories.tsx +30 -0
- package/src/molecules/Input/Input.tsx +31 -0
- package/src/molecules/InputContainer/InputContainer.tsx +60 -0
- package/src/molecules/JutaBrand/JutaBrand.stories.tsx +43 -0
- package/src/molecules/JutaBrand/JutaBrand.tsx +74 -0
- package/src/molecules/Modal/Modal.tsx +71 -0
- package/src/molecules/OverviewRowItem/OverviewRowItem.stories.tsx +23 -0
- package/src/molecules/OverviewRowItem/OverviewRowItem.tsx +39 -0
- package/src/molecules/PDFPreviewer/PDFPreviewer.tsx +42 -0
- package/src/molecules/PageLayout/PageLayout.tsx +60 -0
- package/src/molecules/ProductInfo/ProductInfo.stories.tsx +50 -0
- package/src/molecules/ProductInfo/ProductInfo.tsx +90 -0
- package/src/molecules/RadioGroup/RadioGroup.stories.tsx +47 -0
- package/src/molecules/RadioGroup/RadioGroup.tsx +55 -0
- package/src/molecules/RatesChart/RatesChart.stories.tsx +61 -0
- package/src/molecules/RatesChart/RatesChart.tsx +185 -0
- package/src/molecules/SideNav/SideNav.stories.tsx +64 -0
- package/src/molecules/SideNav/SideNav.tsx +140 -0
- package/src/molecules/SidePanel/SidePanel.stories.tsx +87 -0
- package/src/molecules/SidePanel/SidePanel.tsx +138 -0
- package/src/molecules/StepperHeaderTab/StepperHeaderTab.stories.tsx +23 -0
- package/src/molecules/StepperHeaderTab/StepperHeaderTab.tsx +43 -0
- package/src/molecules/Textarea/Textarea.tsx +29 -0
- package/src/molecules/index.ts +23 -0
- package/src/organism/ContactForm/ContactForm.stories.tsx +15 -0
- package/src/organism/ContactForm/ContactForm.tsx +54 -0
- package/src/organism/DocumentListAccordion/DocumentListAccordion.tsx +96 -0
- package/src/organism/FeatureCarousel/FeatureCarousel.stories.tsx +81 -0
- package/src/organism/FeatureCarousel/FeatureCarousel.tsx +162 -0
- package/src/organism/Footer/Footer.stories.tsx +77 -0
- package/src/organism/Footer/Footer.tsx +231 -0
- package/src/organism/Header/Header.stories.tsx +51 -0
- package/src/organism/Header/Header.tsx +76 -0
- package/src/organism/OverviewList/OverviewList.stories.tsx +43 -0
- package/src/organism/OverviewList/OverviewList.tsx +56 -0
- package/src/organism/ToastProvider/ToastProvider.tsx +40 -0
- package/src/organism/VersionLabel/VersionLabel.tsx +9 -0
- package/src/organism/index.ts +9 -0
- package/src/styles/tailwind.css +8 -0
- package/src/templates/AboutUs/AboutUs.stories.tsx +60 -0
- package/src/templates/AboutUs/AboutUs.tsx +97 -0
- package/src/templates/Contact/Contact.stories.tsx +62 -0
- package/src/templates/Contact/Contact.tsx +125 -0
- package/src/templates/FAQ/FAQ.stories.tsx +82 -0
- package/src/templates/FAQ/FAQ.tsx +91 -0
- package/src/templates/Features/Features.stories.tsx +94 -0
- package/src/templates/Features/Features.tsx +79 -0
- package/src/templates/Hero/Hero.stories.tsx +105 -0
- package/src/templates/Hero/Hero.tsx +139 -0
- package/src/templates/OtherProducts/OtherProducts.stories.tsx +77 -0
- package/src/templates/OtherProducts/OtherProducts.tsx +86 -0
- package/src/templates/index.ts +7 -0
- package/src/tokens/animations.ts +11 -0
- package/src/tokens/breakpoints.ts +7 -0
- package/src/tokens/colors.stories.tsx +77 -0
- package/src/tokens/colors.ts +59 -0
- package/src/tokens/radii.ts +6 -0
- package/src/tokens/sizes.ts +8 -0
- package/src/tokens/spaces.ts +21 -0
- package/src/types.ts +20 -0
- package/stories/Button.stories.ts +54 -0
- package/stories/Button.tsx +41 -0
- package/stories/Configure.mdx +364 -0
- package/stories/Header.stories.ts +34 -0
- package/stories/Header.tsx +71 -0
- package/stories/Page.stories.ts +33 -0
- package/stories/Page.tsx +91 -0
- package/stories/TopMenu.stories.tsx +51 -0
- package/stories/assets/accessibility.png +0 -0
- package/stories/assets/accessibility.svg +1 -0
- package/stories/assets/addon-library.png +0 -0
- package/stories/assets/assets.png +0 -0
- package/stories/assets/avif-test-image.avif +0 -0
- package/stories/assets/context.png +0 -0
- package/stories/assets/discord.svg +1 -0
- package/stories/assets/docs.png +0 -0
- package/stories/assets/figma-plugin.png +0 -0
- package/stories/assets/github.svg +1 -0
- package/stories/assets/share.png +0 -0
- package/stories/assets/styling.png +0 -0
- package/stories/assets/testing.png +0 -0
- package/stories/assets/theming.png +0 -0
- package/stories/assets/tutorials.svg +1 -0
- package/stories/assets/youtube.svg +1 -0
- package/stories/button.css +30 -0
- package/stories/header.css +32 -0
- package/stories/page.css +68 -0
- package/tailwind.config.js +34 -0
- package/tsconfig.json +8 -0
- package/types/index.ts +5 -0
- package/types/inputAttributes.ts +16 -0
- package/types/menuItem.ts +17 -0
- package/types/orderType.ts +2 -0
- package/types/tableListItem.ts +7 -0
- package/types/toast.ts +1 -0
- package/vitest.config.ts +37 -0
- package/vitest.shims.d.ts +1 -0
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import Link from 'next/link';
|
|
4
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
5
|
+
import { tv } from 'tailwind-variants';
|
|
6
|
+
import AppDialog from '../../../../../apps/admin-frontend/components/dialog';
|
|
7
|
+
import {
|
|
8
|
+
ClockIcon,
|
|
9
|
+
HomeIcon,
|
|
10
|
+
TrashIcon,
|
|
11
|
+
} from '../../../../property-practice-icons/src';
|
|
12
|
+
import { TableHeaderConfig } from '../Table/Table';
|
|
13
|
+
|
|
14
|
+
type PaginationOptionsType = {
|
|
15
|
+
perPage?: 10 | 25 | 50 | 100;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
interface TableRowItem {
|
|
19
|
+
id: string;
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface TableRowProps {
|
|
24
|
+
data: TableRowItem[];
|
|
25
|
+
headers: TableHeaderConfig[];
|
|
26
|
+
paginationOptions?: PaginationOptionsType;
|
|
27
|
+
onDelete?: (id: string) => void;
|
|
28
|
+
variant?: 'Primary' | 'Secondary';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const itemContainer = tv({
|
|
32
|
+
base: 'rounded-2xl mb-2 px-8 py-3 flex flex-wrap items-center justify-between gap-4',
|
|
33
|
+
variants: {
|
|
34
|
+
variant: {
|
|
35
|
+
Primary: 'border border-gray-200',
|
|
36
|
+
Secondary: 'border-none',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
defaultVariants: {
|
|
40
|
+
variant: 'Primary',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const formatDate = (value: string | Date) => {
|
|
45
|
+
const date = new Date(value);
|
|
46
|
+
return date.toLocaleString('default', {
|
|
47
|
+
year: 'numeric',
|
|
48
|
+
month: 'long',
|
|
49
|
+
day: 'numeric',
|
|
50
|
+
hour12: false,
|
|
51
|
+
hour: 'numeric',
|
|
52
|
+
minute: 'numeric',
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const getStatusBadge = (status: string, transactionType?: string) => {
|
|
57
|
+
const base = 'px-3 rounded-xl py-1 text-gray-400 text-xs font-bold uppercase';
|
|
58
|
+
switch (status) {
|
|
59
|
+
case 'DRAFT':
|
|
60
|
+
return <span className={`${base} bg-purple-400`}>Draft</span>;
|
|
61
|
+
case 'PENDING':
|
|
62
|
+
return (
|
|
63
|
+
<span className={`${base} bg-yellow-200`}>
|
|
64
|
+
{transactionType?.toUpperCase() === 'LEASE'
|
|
65
|
+
? 'Awaiting Lessor Information'
|
|
66
|
+
: 'Awaiting Seller Information'}
|
|
67
|
+
</span>
|
|
68
|
+
);
|
|
69
|
+
case 'ACTIVE':
|
|
70
|
+
return <span className={`${base} bg-blue-400`}>Active</span>;
|
|
71
|
+
case 'FINALISED':
|
|
72
|
+
return <span className={`${base} bg-green-400`}>Finalised</span>;
|
|
73
|
+
case 'ARCHIVED':
|
|
74
|
+
return <span className={`${base} bg-red-400`}>Archived</span>;
|
|
75
|
+
default:
|
|
76
|
+
return <span className={`${base} bg-gray-200`}>{status}</span>;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const RowCell = ({
|
|
81
|
+
header,
|
|
82
|
+
item,
|
|
83
|
+
}: {
|
|
84
|
+
header: TableHeaderConfig;
|
|
85
|
+
item: TableRowItem;
|
|
86
|
+
}) => (
|
|
87
|
+
<div className="flex-1 min-w-[120px]">
|
|
88
|
+
<p className="font-semibold text-gray-300 text-sm tracking-wide flex items-center gap-1">
|
|
89
|
+
{header.filterAccessor === 'status' && <ClockIcon />}
|
|
90
|
+
{header.heading}
|
|
91
|
+
</p>
|
|
92
|
+
<p className="text-base font-medium text-gray-400 flex items-center gap-1">
|
|
93
|
+
{header.filterAccessor === 'formattedAddress' && <HomeIcon />}
|
|
94
|
+
{header.filterAccessor === 'formattedAddress' ? (
|
|
95
|
+
<span className="truncate max-w-[200px] block">
|
|
96
|
+
{item[header.filterAccessor]}
|
|
97
|
+
</span>
|
|
98
|
+
) : header.filterAccessor === 'status' ? (
|
|
99
|
+
getStatusBadge(item[header.filterAccessor], item.transactionType)
|
|
100
|
+
) : header.filterAccessor === 'createdAt' ? (
|
|
101
|
+
formatDate(item[header.filterAccessor])
|
|
102
|
+
) : header.filterAccessor === '-' ? (
|
|
103
|
+
'-'
|
|
104
|
+
) : (
|
|
105
|
+
item[header.filterAccessor]
|
|
106
|
+
)}
|
|
107
|
+
</p>
|
|
108
|
+
</div>
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const DeleteDialog = ({
|
|
112
|
+
open,
|
|
113
|
+
onClose,
|
|
114
|
+
onConfirm,
|
|
115
|
+
isDeleting,
|
|
116
|
+
}: {
|
|
117
|
+
open: boolean;
|
|
118
|
+
onClose: () => void;
|
|
119
|
+
onConfirm: () => void;
|
|
120
|
+
isDeleting: boolean;
|
|
121
|
+
}) => (
|
|
122
|
+
<AppDialog
|
|
123
|
+
open={open}
|
|
124
|
+
onClose={onClose}
|
|
125
|
+
title="Delete Transaction"
|
|
126
|
+
buttonText={isDeleting ? 'Deleting...' : 'Confirm'}
|
|
127
|
+
buttonHandler={onConfirm}
|
|
128
|
+
secondaryText="Cancel"
|
|
129
|
+
secondaryHandler={onClose}
|
|
130
|
+
>
|
|
131
|
+
<div className="flex flex-col items-center text-center">
|
|
132
|
+
<TrashIcon />
|
|
133
|
+
<p className="text-sm text-gray-600 mb-4">
|
|
134
|
+
Are you sure you want to delete this transaction? This will remove the
|
|
135
|
+
property from the list (soft delete).
|
|
136
|
+
</p>
|
|
137
|
+
</div>
|
|
138
|
+
</AppDialog>
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
export const TableRow = ({
|
|
142
|
+
data,
|
|
143
|
+
headers,
|
|
144
|
+
paginationOptions = {},
|
|
145
|
+
onDelete,
|
|
146
|
+
variant = 'Primary',
|
|
147
|
+
}: TableRowProps) => {
|
|
148
|
+
const [perPage, setPerPage] = useState<number>(
|
|
149
|
+
paginationOptions.perPage ?? 10,
|
|
150
|
+
);
|
|
151
|
+
const [page, setPage] = useState(0);
|
|
152
|
+
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
153
|
+
const [selectedTransactionId, setSelectedTransactionId] = useState<
|
|
154
|
+
string | null
|
|
155
|
+
>(null);
|
|
156
|
+
const [isDeleting, setIsDeleting] = useState(false);
|
|
157
|
+
|
|
158
|
+
const totalPages = useMemo(
|
|
159
|
+
() => Math.ceil(data.length / perPage),
|
|
160
|
+
[data, perPage],
|
|
161
|
+
);
|
|
162
|
+
const paginatedData = useMemo(
|
|
163
|
+
() => data.slice(page * perPage, (page + 1) * perPage),
|
|
164
|
+
[data, page, perPage],
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
if (paginationOptions.perPage) {
|
|
169
|
+
setPerPage(paginationOptions.perPage);
|
|
170
|
+
}
|
|
171
|
+
setPage(0);
|
|
172
|
+
}, [paginationOptions.perPage, data]);
|
|
173
|
+
|
|
174
|
+
const confirmDelete = async () => {
|
|
175
|
+
if (!selectedTransactionId || !onDelete) return;
|
|
176
|
+
setIsDeleting(true);
|
|
177
|
+
try {
|
|
178
|
+
onDelete(selectedTransactionId);
|
|
179
|
+
setIsDialogOpen(false);
|
|
180
|
+
setSelectedTransactionId(null);
|
|
181
|
+
} catch {
|
|
182
|
+
alert('Failed to delete transaction. Please try again.');
|
|
183
|
+
} finally {
|
|
184
|
+
setIsDeleting(false);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const handlePrevPage = () => {
|
|
189
|
+
if (page > 0) setPage(page - 1);
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
const handleNextPage = () => {
|
|
193
|
+
if (page < totalPages - 1) setPage(page + 1);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const handleRowsPerPageChange = (value: number) => {
|
|
197
|
+
setPerPage(value);
|
|
198
|
+
setPage(0);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<div className="flex flex-col">
|
|
203
|
+
{paginatedData.map((item, idx) => (
|
|
204
|
+
<div
|
|
205
|
+
key={item.id}
|
|
206
|
+
className={`${itemContainer({ variant })} ${idx % 2 === 0 ? 'bg-gray-50 dark:bg-gray-600' : ''}`}
|
|
207
|
+
>
|
|
208
|
+
{headers.map((header) => (
|
|
209
|
+
<RowCell key={header.filterAccessor} header={header} item={item} />
|
|
210
|
+
))}
|
|
211
|
+
|
|
212
|
+
<div className="flex flex-col items-start gap-1">
|
|
213
|
+
<p className="font-semibold text-[#033c89] text-sm tracking-wide">
|
|
214
|
+
<Link
|
|
215
|
+
href={`${item.url}`}
|
|
216
|
+
className="text-[#033c89] hover:underline"
|
|
217
|
+
>
|
|
218
|
+
View Details
|
|
219
|
+
</Link>
|
|
220
|
+
</p>
|
|
221
|
+
{onDelete && (
|
|
222
|
+
<button
|
|
223
|
+
onClick={(e) => {
|
|
224
|
+
e.stopPropagation();
|
|
225
|
+
setSelectedTransactionId(item.id);
|
|
226
|
+
setIsDialogOpen(true);
|
|
227
|
+
}}
|
|
228
|
+
className="flex items-center gap-1 text-red-500 hover:text-red-700"
|
|
229
|
+
>
|
|
230
|
+
<TrashIcon />
|
|
231
|
+
<span className="text-sm font-medium">Delete</span>
|
|
232
|
+
</button>
|
|
233
|
+
)}
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
))}
|
|
237
|
+
|
|
238
|
+
<div className="flex flex-wrap items-center px-6 pt-8 border-t border-gray-400">
|
|
239
|
+
<div className="w-full sm:w-auto mb-4 sm:mb-0 mr-auto">
|
|
240
|
+
<div className="flex items-center gap-2">
|
|
241
|
+
<button
|
|
242
|
+
disabled
|
|
243
|
+
className="flex items-center justify-center h-6 w-11 bg-gray-100 dark:bg-gray-600 rounded-full"
|
|
244
|
+
>
|
|
245
|
+
<div className="h-5 w-5 rounded-full dark:bg-gray-400 bg-gray-50" />
|
|
246
|
+
<div className="h-5 w-5 rounded-full bg-transparent" />
|
|
247
|
+
</button>
|
|
248
|
+
<span className="text-sm text-gray-200 dark:text-gray-400 font-medium">
|
|
249
|
+
Dense
|
|
250
|
+
</span>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
<div className="w-full sm:w-auto mb-6 sm:mb-0 sm:mr-6">
|
|
254
|
+
<div className="flex items-center justify-end ml-auto">
|
|
255
|
+
<div className="sm:mr-8 flex items-center gap-2">
|
|
256
|
+
<span className="text-sm text-gray-400 font-medium">
|
|
257
|
+
Rows per page
|
|
258
|
+
</span>
|
|
259
|
+
<select
|
|
260
|
+
value={perPage}
|
|
261
|
+
onChange={(e) =>
|
|
262
|
+
handleRowsPerPageChange(Number(e.target.value))
|
|
263
|
+
}
|
|
264
|
+
className="text-sm text-gray-200 font-medium bg-transparent outline-none"
|
|
265
|
+
>
|
|
266
|
+
{[5, 10, 20].map((size) => (
|
|
267
|
+
<option key={size} value={size}>
|
|
268
|
+
{size}
|
|
269
|
+
</option>
|
|
270
|
+
))}
|
|
271
|
+
</select>
|
|
272
|
+
<span className="hidden sm:inline text-sm text-gray-400 font-medium">
|
|
273
|
+
{page * perPage + 1}-
|
|
274
|
+
{Math.min((page + 1) * perPage, data.length)} of {data.length}
|
|
275
|
+
</span>
|
|
276
|
+
</div>
|
|
277
|
+
</div>
|
|
278
|
+
</div>
|
|
279
|
+
<div className="w-full sm:w-auto mb-6 sm:mb-0">
|
|
280
|
+
<div className="flex items-center justify-end">
|
|
281
|
+
<a
|
|
282
|
+
onClick={(e) => {
|
|
283
|
+
e.preventDefault();
|
|
284
|
+
handlePrevPage();
|
|
285
|
+
}}
|
|
286
|
+
className={`inline-flex items-center justify-center h-8 w-12 p-1 mr-3 text-xs font-semibold rounded-lg transition duration-200 ${
|
|
287
|
+
page === 0
|
|
288
|
+
? 'bg-gray-600 text-gray-400 cursor-not-allowed'
|
|
289
|
+
: 'text-gray-400 bg-gray-600 hover:bg-gray-700'
|
|
290
|
+
}`}
|
|
291
|
+
href="#"
|
|
292
|
+
>
|
|
293
|
+
<svg
|
|
294
|
+
width={6}
|
|
295
|
+
height={8}
|
|
296
|
+
viewBox="0 0 6 8"
|
|
297
|
+
fill="none"
|
|
298
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
299
|
+
>
|
|
300
|
+
<path
|
|
301
|
+
d="M2.52655 3.99988L4.88655 1.63988C5.01072 1.51498 5.08041 1.34601 5.08041 1.16988C5.08041 0.993761 5.01072 0.824793 4.88655 0.699884C4.82457 0.637399 4.75084 0.587802 4.6696 0.553957C4.58836 0.520111 4.50122 0.502686 4.41321 0.502686C4.32521 0.502686 4.23807 0.520111 4.15683 0.553957C4.07559 0.587802 4.00186 0.637399 3.93988 0.699884L1.11321 3.52655C1.05073 3.58853 1.00113 3.66226 0.967287 3.7435C0.933441 3.82474 0.916016 3.91188 0.916016 3.99988C0.916016 4.08789 0.933441 4.17503 0.967287 4.25627C1.00113 4.33751 1.05073 4.41124 1.11321 4.47322L3.93988 7.33322C4.00217 7.39501 4.07605 7.44389 4.15728 7.47707C4.2385 7.51024 4.32548 7.52706 4.41321 7.52655C4.50095 7.52706 4.58793 7.51024 4.66915 7.47707C4.75038 7.44389 4.82425 7.39501 4.88655 7.33322C5.01072 7.20831 5.08041 7.03934 5.08041 6.86322C5.08041 6.68709 5.01072 6.51813 4.88655 6.39322L2.52655 3.99988Z"
|
|
302
|
+
fill="#919EB0"
|
|
303
|
+
/>
|
|
304
|
+
</svg>
|
|
305
|
+
</a>
|
|
306
|
+
|
|
307
|
+
<a
|
|
308
|
+
onClick={(e) => {
|
|
309
|
+
e.preventDefault();
|
|
310
|
+
handleNextPage();
|
|
311
|
+
}}
|
|
312
|
+
className={`inline-flex items-center justify-center h-8 w-12 p-1 text-xs font-semibold rounded-lg transition duration-200 ${
|
|
313
|
+
page >= totalPages - 1 || totalPages === 0
|
|
314
|
+
? 'bg-blue-500 text-blue-100 cursor-not-allowed'
|
|
315
|
+
: 'bg-[#033c89] text-blue-50 hover:bg-blue-600'
|
|
316
|
+
}`}
|
|
317
|
+
href="#"
|
|
318
|
+
>
|
|
319
|
+
<svg
|
|
320
|
+
width={6}
|
|
321
|
+
height={10}
|
|
322
|
+
viewBox="0 0 6 10"
|
|
323
|
+
fill="none"
|
|
324
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
325
|
+
>
|
|
326
|
+
<path
|
|
327
|
+
d="M5.36015 4.52661L1.58682 0.759943C1.52484 0.697457 1.45111 0.647861 1.36987 0.614016C1.28863 0.58017 1.20149 0.562744 1.11348 0.562744C1.02548 0.562744 0.938339 0.58017 0.8571 0.614016C0.77586 0.647861 0.702126 0.697457 0.640151 0.759943C0.515983 0.884851 0.446289 1.05382 0.446289 1.22994C0.446289 1.40607 0.515983 1.57503 0.640151 1.69994L3.94015 5.03328L0.640151 8.33328C0.515983 8.45818 0.446289 8.62715 0.446289 8.80328C0.446289 8.9794 0.515983 9.14837 0.640151 9.27328C0.701894 9.33627 0.775524 9.38638 0.856774 9.42071C0.938024 9.45504 1.02528 9.47291 1.11348 9.47328C1.20169 9.47291 1.28894 9.45504 1.37019 9.42071C1.45144 9.38638 1.52507 9.33627 1.58682 9.27328L5.36015 5.50661C5.42782 5.44418 5.48183 5.36841 5.51876 5.28408C5.5557 5.19975 5.57477 5.10868 5.57477 5.01661C5.57477 4.92454 5.5557 4.83347 5.51876 4.74914C5.48183 4.66481 5.42782 4.58904 5.36015 4.52661Z"
|
|
328
|
+
fill="#F4F6FF"
|
|
329
|
+
/>
|
|
330
|
+
</svg>
|
|
331
|
+
</a>
|
|
332
|
+
</div>
|
|
333
|
+
</div>
|
|
334
|
+
</div>
|
|
335
|
+
<DeleteDialog
|
|
336
|
+
open={isDialogOpen}
|
|
337
|
+
onClose={() => setIsDialogOpen(false)}
|
|
338
|
+
onConfirm={confirmDelete}
|
|
339
|
+
isDeleting={isDeleting}
|
|
340
|
+
/>
|
|
341
|
+
</div>
|
|
342
|
+
);
|
|
343
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { TransactionTypeEnum } from '../../../../property-practice-dtos';
|
|
3
|
+
import { Tabs } from './Tabs';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof Tabs> = {
|
|
6
|
+
title: 'Components/Tabs',
|
|
7
|
+
component: Tabs,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'centered',
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default meta;
|
|
15
|
+
type Story = StoryObj<typeof Tabs>;
|
|
16
|
+
|
|
17
|
+
const mockSaleData = [
|
|
18
|
+
{ id: '1', title: 'Luxury Apartment Sale', price: 'R1,200,000' },
|
|
19
|
+
{ id: '2', title: 'Modern Villa Sale', price: 'R2,800,000' },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const mockLeaseData = [
|
|
23
|
+
{ id: '3', title: 'Downtown Apartment Lease', price: 'R8,500/month' },
|
|
24
|
+
{ id: '4', title: 'Suburban House Lease', price: 'R12,000/month' },
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
export const Default: Story = {
|
|
28
|
+
args: {
|
|
29
|
+
saleData: mockSaleData,
|
|
30
|
+
leaseData: mockLeaseData,
|
|
31
|
+
defaultTab: TransactionTypeEnum.enum.SALE,
|
|
32
|
+
onTabChange: (tab) => console.log('Tab changed:', tab),
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const LeaseDefault: Story = {
|
|
37
|
+
args: {
|
|
38
|
+
saleData: mockSaleData,
|
|
39
|
+
leaseData: mockLeaseData,
|
|
40
|
+
defaultTab: TransactionTypeEnum.enum.LEASE,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useMemo, useState } from 'react';
|
|
4
|
+
import {
|
|
5
|
+
TransactionTypeEnum,
|
|
6
|
+
TransactionTypeEnumType,
|
|
7
|
+
} from '../../../../property-practice-dtos';
|
|
8
|
+
|
|
9
|
+
interface TabsProps {
|
|
10
|
+
saleData: any[];
|
|
11
|
+
leaseData: any[];
|
|
12
|
+
defaultTab?: TransactionTypeEnumType;
|
|
13
|
+
onTabChange?: (tab: TransactionTypeEnumType) => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const Tabs = ({
|
|
17
|
+
saleData,
|
|
18
|
+
leaseData,
|
|
19
|
+
defaultTab = TransactionTypeEnum.enum.SALE,
|
|
20
|
+
onTabChange,
|
|
21
|
+
}: TabsProps) => {
|
|
22
|
+
const [tab, setTab] = useState<TransactionTypeEnumType>(defaultTab);
|
|
23
|
+
|
|
24
|
+
const displayedData = useMemo(
|
|
25
|
+
() => (tab === TransactionTypeEnum.enum.SALE ? saleData : leaseData),
|
|
26
|
+
[tab, saleData, leaseData],
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const handleTabChange = (newTab: TransactionTypeEnumType) => {
|
|
30
|
+
setTab(newTab);
|
|
31
|
+
onTabChange?.(newTab);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<div className="flex flex-col gap-4">
|
|
36
|
+
<div className="px-4 border-b border-gray-300 bg-white">
|
|
37
|
+
<div className="flex gap-x-10 py-3">
|
|
38
|
+
{Object.values(TransactionTypeEnum.enum).map((type) => (
|
|
39
|
+
<button
|
|
40
|
+
key={type}
|
|
41
|
+
type="button"
|
|
42
|
+
onClick={() => handleTabChange(type as TransactionTypeEnumType)}
|
|
43
|
+
className={`text-base font-semibold cursor-pointer px-6 py-2 rounded-t-lg border-b-4 transition-colors duration-200 ${
|
|
44
|
+
tab === type
|
|
45
|
+
? 'border-blue-600 text-[#033c89]'
|
|
46
|
+
: 'border-transparent text-gray-400 dark:text-[#033c89]'
|
|
47
|
+
}`}
|
|
48
|
+
>
|
|
49
|
+
{type.charAt(0).toUpperCase() + type.slice(1).toLowerCase()}
|
|
50
|
+
</button>
|
|
51
|
+
))}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
import { tv } from 'tailwind-variants';
|
|
5
|
+
import { ToastType } from '../../types';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
visible?: boolean;
|
|
9
|
+
setVisible?: (visible: boolean) => void;
|
|
10
|
+
duration?: number | null;
|
|
11
|
+
type: ToastType;
|
|
12
|
+
message?: string;
|
|
13
|
+
onClear?: () => void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const toastVariants = tv({
|
|
17
|
+
base: 'z-[100] fixed left-0 bottom-0 p-4 transition-all duration-500 transform',
|
|
18
|
+
variants: {
|
|
19
|
+
show: {
|
|
20
|
+
true: 'translate-x-0',
|
|
21
|
+
false: '-translate-x-full',
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const containerVariants = tv({
|
|
27
|
+
base: 'rounded-lg shadow overflow-hidden p-2',
|
|
28
|
+
variants: {
|
|
29
|
+
type: {
|
|
30
|
+
Default: 'bg-gray-700',
|
|
31
|
+
Success: 'bg-green-700',
|
|
32
|
+
Warning: 'bg-yellow-700',
|
|
33
|
+
Error: 'bg-red-700',
|
|
34
|
+
Message: 'bg-blue-700',
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const iconVariants = tv({
|
|
40
|
+
base: 'flex-shrink-0 self-start inline-flex items-center justify-center w-10 h-10 mr-3 rounded-xl bg-opacity-20',
|
|
41
|
+
variants: {
|
|
42
|
+
type: {
|
|
43
|
+
Success: 'bg-green-500',
|
|
44
|
+
Warning: 'bg-yellow-500',
|
|
45
|
+
Error: 'bg-red-500',
|
|
46
|
+
Message: 'bg-blue-500',
|
|
47
|
+
Default: 'bg-gray-500',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export default function Toast({
|
|
53
|
+
type,
|
|
54
|
+
message,
|
|
55
|
+
visible,
|
|
56
|
+
setVisible,
|
|
57
|
+
duration = 5000,
|
|
58
|
+
onClear,
|
|
59
|
+
}: Props) {
|
|
60
|
+
//const [show, setShow] = useState(visible);console.log(visible, show)
|
|
61
|
+
|
|
62
|
+
useEffect(() => {
|
|
63
|
+
//setShow(visible)
|
|
64
|
+
if (duration && visible) {
|
|
65
|
+
const timer = setTimeout(() => {
|
|
66
|
+
setVisible && setVisible(false);
|
|
67
|
+
onClear && onClear();
|
|
68
|
+
}, duration);
|
|
69
|
+
return () => clearTimeout(timer);
|
|
70
|
+
}
|
|
71
|
+
}, [duration, visible]);
|
|
72
|
+
|
|
73
|
+
const icon = () => {
|
|
74
|
+
switch (type) {
|
|
75
|
+
case 'Success':
|
|
76
|
+
return (
|
|
77
|
+
<svg
|
|
78
|
+
width="20"
|
|
79
|
+
height="20"
|
|
80
|
+
viewBox="0 0 20 20"
|
|
81
|
+
fill="none"
|
|
82
|
+
stroke="#a1a1a1"
|
|
83
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
84
|
+
>
|
|
85
|
+
<path
|
|
86
|
+
fillRule="evenodd"
|
|
87
|
+
clipRule="evenodd"
|
|
88
|
+
d="M0 10C0 4.47715 4.47715 0 10 0C12.6522 0 15.1957 1.05357 17.0711 2.92893C18.9464 4.8043 20 7.34784 20 10C20 15.5228 15.5228 20 10 20C4.47715 20 0 15.5228 0 10ZM9.73 13.61L14.3 7.61V7.58C14.5179 7.29419 14.5668 6.91382 14.4283 6.58218C14.2897 6.25054 13.9848 6.01801 13.6283 5.97218C13.2718 5.92635 12.9179 6.07419 12.7 6.36L8.92 11.36L7.29 9.28C7.07028 8.99776 6.71668 8.85418 6.36239 8.90334C6.00811 8.9525 5.70696 9.18694 5.57239 9.51834C5.43783 9.84974 5.49028 10.2278 5.71 10.51L8.15 13.62C8.34082 13.8615 8.63222 14.0017 8.94 14C9.2495 13.9993 9.54121 13.8552 9.73 13.61Z"
|
|
89
|
+
fill="#54D62C"
|
|
90
|
+
></path>
|
|
91
|
+
</svg>
|
|
92
|
+
);
|
|
93
|
+
case 'Warning':
|
|
94
|
+
return (
|
|
95
|
+
<svg
|
|
96
|
+
width="24"
|
|
97
|
+
height="20"
|
|
98
|
+
viewBox="0 0 24 21"
|
|
99
|
+
fill="none"
|
|
100
|
+
stroke="#a1a1a1"
|
|
101
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
102
|
+
>
|
|
103
|
+
<path
|
|
104
|
+
d="M12.0005 15C11.8027 15 11.6093 15.0586 11.4449 15.1685C11.2804 15.2784 11.1523 15.4346 11.0766 15.6173C11.0009 15.8 10.9811 16.0011 11.0197 16.1951C11.0583 16.3891 11.1535 16.5673 11.2933 16.7071C11.4332 16.847 11.6114 16.9422 11.8054 16.9808C11.9993 17.0194 12.2004 16.9996 12.3831 16.9239C12.5659 16.8482 12.722 16.72 12.8319 16.5556C12.9418 16.3911 13.0005 16.1978 13.0005 16C13.0005 15.7348 12.8951 15.4804 12.7076 15.2929C12.52 15.1054 12.2657 15 12.0005 15ZM22.6705 16.47L14.6205 2.47C14.3603 2.00351 13.9802 1.61495 13.5196 1.34447C13.0591 1.07398 12.5346 0.931366 12.0005 0.931366C11.4663 0.931366 10.9419 1.07398 10.4813 1.34447C10.0207 1.61495 9.64065 2.00351 9.38046 2.47L1.38046 16.47C1.11125 16.924 0.966598 17.441 0.9611 17.9688C0.955602 18.4966 1.08945 19.0165 1.34914 19.476C1.60883 19.9356 1.98516 20.3185 2.44014 20.586C2.89512 20.8536 3.41264 20.9964 3.94046 21H20.0605C20.5925 21.0052 21.1164 20.8689 21.5784 20.6049C22.0403 20.3409 22.4238 19.9588 22.6894 19.4978C22.9551 19.0368 23.0933 18.5134 23.09 17.9813C23.0866 17.4493 22.9418 16.9277 22.6705 16.47ZM20.9405 18.47C20.8528 18.6259 20.7249 18.7555 20.5701 18.8452C20.4154 18.9349 20.2393 18.9815 20.0605 18.98H3.94046C3.76157 18.9815 3.58556 18.9349 3.43077 18.8452C3.27599 18.7555 3.14811 18.6259 3.06046 18.47C2.97269 18.318 2.92648 18.1455 2.92648 17.97C2.92648 17.7945 2.97269 17.622 3.06046 17.47L11.0605 3.47C11.1444 3.3062 11.2719 3.16873 11.4289 3.07274C11.5859 2.97675 11.7664 2.92596 11.9505 2.92596C12.1345 2.92596 12.315 2.97675 12.472 3.07274C12.629 3.16873 12.7565 3.3062 12.8405 3.47L20.8905 17.47C20.9897 17.6198 21.0467 17.7936 21.0555 17.9731C21.0643 18.1526 21.0245 18.3312 20.9405 18.49V18.47ZM12.0005 7C11.7352 7 11.4809 7.10535 11.2933 7.29289C11.1058 7.48043 11.0005 7.73478 11.0005 8V12C11.0005 12.2652 11.1058 12.5196 11.2933 12.7071C11.4809 12.8946 11.7352 13 12.0005 13C12.2657 13 12.52 12.8946 12.7076 12.7071C12.8951 12.5196 13.0005 12.2652 13.0005 12V8C13.0005 7.73478 12.8951 7.48043 12.7076 7.29289C12.52 7.10535 12.2657 7 12.0005 7Z"
|
|
105
|
+
fill="#FFC107"
|
|
106
|
+
></path>
|
|
107
|
+
</svg>
|
|
108
|
+
);
|
|
109
|
+
case 'Error':
|
|
110
|
+
return (
|
|
111
|
+
<svg
|
|
112
|
+
width="20"
|
|
113
|
+
height="20"
|
|
114
|
+
viewBox="0 0 20 20"
|
|
115
|
+
fill="none"
|
|
116
|
+
stroke="#a1a1a1"
|
|
117
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
118
|
+
>
|
|
119
|
+
<path
|
|
120
|
+
d="M10 12C9.75278 12 9.5111 12.0733 9.30554 12.2107C9.09998 12.348 8.93976 12.5432 8.84516 12.7716C8.75055 13.0001 8.72579 13.2514 8.77402 13.4939C8.82225 13.7363 8.94131 13.9591 9.11612 14.1339C9.29094 14.3087 9.51367 14.4277 9.75614 14.476C9.99862 14.5242 10.25 14.4995 10.4784 14.4049C10.7068 14.3102 10.902 14.15 11.0393 13.9445C11.1767 13.7389 11.25 13.4972 11.25 13.25C11.25 12.9185 11.1183 12.6005 10.8839 12.3661C10.6495 12.1317 10.3315 12 10 12ZM10 10.5C10.2652 10.5 10.5196 10.3946 10.7071 10.2071C10.8946 10.0196 11 9.76522 11 9.5V6.5C11 6.23478 10.8946 5.98043 10.7071 5.79289C10.5196 5.60536 10.2652 5.5 10 5.5C9.73479 5.5 9.48043 5.60536 9.2929 5.79289C9.10536 5.98043 9 6.23478 9 6.5V9.5C9 9.76522 9.10536 10.0196 9.2929 10.2071C9.48043 10.3946 9.73479 10.5 10 10.5ZM10 0C8.02219 0 6.08879 0.58649 4.4443 1.6853C2.79981 2.78412 1.51809 4.3459 0.761209 6.17317C0.00433284 8.00043 -0.193701 10.0111 0.192152 11.9509C0.578004 13.8907 1.53041 15.6725 2.92894 17.0711C4.32746 18.4696 6.10929 19.422 8.0491 19.8079C9.98891 20.1937 11.9996 19.9957 13.8268 19.2388C15.6541 18.4819 17.2159 17.2002 18.3147 15.5557C19.4135 13.9112 20 11.9778 20 10C19.9971 7.34874 18.9425 4.80691 17.0678 2.93219C15.1931 1.05746 12.6513 0.00294858 10 0ZM10 18C8.41775 18 6.87104 17.5308 5.55544 16.6518C4.23985 15.7727 3.21447 14.5233 2.60897 13.0615C2.00347 11.5997 1.84504 9.99113 2.15372 8.43928C2.4624 6.88743 3.22433 5.46197 4.34315 4.34315C5.46197 3.22433 6.88743 2.4624 8.43928 2.15372C9.99113 1.84504 11.5997 2.00346 13.0615 2.60896C14.5233 3.21447 15.7727 4.23984 16.6518 5.55544C17.5308 6.87103 18 8.41775 18 10C17.9976 12.121 17.1539 14.1544 15.6542 15.6542C14.1544 17.1539 12.121 17.9976 10 18Z"
|
|
121
|
+
fill="#FF4842"
|
|
122
|
+
></path>
|
|
123
|
+
</svg>
|
|
124
|
+
);
|
|
125
|
+
case 'Message':
|
|
126
|
+
return (
|
|
127
|
+
<svg
|
|
128
|
+
width="20"
|
|
129
|
+
height="20"
|
|
130
|
+
viewBox="0 0 20 20"
|
|
131
|
+
fill="none"
|
|
132
|
+
stroke="#a1a1a1"
|
|
133
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
134
|
+
>
|
|
135
|
+
<path
|
|
136
|
+
fillRule="evenodd"
|
|
137
|
+
clipRule="evenodd"
|
|
138
|
+
d="M10 0C4.47715 0 0 4.47715 0 10C0 15.5228 4.47715 20 10 20C15.5228 20 20 15.5228 20 10C20 7.34784 18.9464 4.8043 17.0711 2.92893C15.1957 1.05357 12.6522 0 10 0ZM11 14C11 14.5523 10.5523 15 10 15C9.44771 15 9 14.5523 9 14V9C9 8.44771 9.44771 8 10 8C10.5523 8 11 8.44771 11 9V14ZM9 6C9 6.55228 9.44771 7 10 7C10.5523 7 11 6.55228 11 6C11 5.44772 10.5523 5 10 5C9.44771 5 9 5.44772 9 6Z"
|
|
139
|
+
fill="#1890FF"
|
|
140
|
+
></path>
|
|
141
|
+
</svg>
|
|
142
|
+
);
|
|
143
|
+
default:
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const toast = () => {
|
|
149
|
+
switch (type) {
|
|
150
|
+
case 'Default':
|
|
151
|
+
return (
|
|
152
|
+
<div className="flex flex-wrap w-full h-full items-center justify-between">
|
|
153
|
+
<div className="w-full sm:w-auto px-4 py-4 sm:py-0 border-b border-gray-400 sm:border-transparent">
|
|
154
|
+
<span className="text-sm leading-5 text-gray-200 font-semibold">
|
|
155
|
+
{message}
|
|
156
|
+
</span>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
);
|
|
160
|
+
default:
|
|
161
|
+
return (
|
|
162
|
+
<div className="flex flex-wrap w-full h-full items-center justify-between">
|
|
163
|
+
<div className="w-full sm:w-auto px-4 py-4 sm:py-0">
|
|
164
|
+
<div className="flex items-center pr-6">
|
|
165
|
+
<div className={iconVariants({ type })}>{icon()}</div>
|
|
166
|
+
<span className="text-sm leading-5 text-gray-200">
|
|
167
|
+
{message}
|
|
168
|
+
</span>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
<div className="w-20 h-16 border-l border-gray-800">
|
|
172
|
+
<button
|
|
173
|
+
onClick={() => {
|
|
174
|
+
setVisible && setVisible(false);
|
|
175
|
+
onClear && onClear();
|
|
176
|
+
}}
|
|
177
|
+
className="flex w-full h-full items-center justify-center text-center text-lg px-2 text-gray-50"
|
|
178
|
+
>
|
|
179
|
+
X
|
|
180
|
+
</button>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<div className={toastVariants({ show: visible })}>
|
|
189
|
+
<div className={containerVariants({ type })}>{toast()}</div>
|
|
190
|
+
</div>
|
|
191
|
+
);
|
|
192
|
+
}
|