property-practice-ui 0.0.2 → 0.0.3
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/CHANGELOG.md +6 -0
- package/package.json +4 -3
- package/src/components/NavMenu.tsx +1 -1
- package/src/components/SortBy/SortBy.tsx +1 -1
- package/src/components/TableList.tsx +1 -1
- package/src/components/TableRow/TableRow.tsx +1 -1
- package/src/components/Toast.tsx +1 -3
- package/src/components/TopMenu.tsx +1 -3
- package/src/index.ts +3 -1
- package/src/organism/ToastProvider/ToastProvider.tsx +1 -1
- package/src/templates/Contact/Contact.tsx +2 -1
- package/src/templates/OtherProducts/OtherProducts.tsx +2 -1
- package/src/types/index.ts +6 -0
- package/{types → src/types}/tableListItem.ts +1 -1
- package/src/components/DynamicInput.tsx +0 -54
- package/src/components/FileUpload.tsx +0 -123
- package/src/components/ModeSwitch.tsx +0 -66
- package/types/index.ts +0 -5
- /package/{types → src/types}/inputAttributes.ts +0 -0
- /package/{types → src/types}/menuItem.ts +0 -0
- /package/{types → src/types}/orderType.ts +0 -0
- /package/{types → src/types}/toast.ts +0 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "property-practice-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"private": false,
|
|
6
|
+
"type": "module",
|
|
6
7
|
"exports": {
|
|
7
8
|
".": "./src/index.ts",
|
|
8
|
-
"./types": "./types/index.ts",
|
|
9
|
+
"./types": "./src/types/index.ts",
|
|
9
10
|
"./atoms": "./src/atoms/index.ts",
|
|
10
11
|
"./molecules": "./src/molecules/index.ts"
|
|
11
12
|
},
|
|
@@ -45,7 +46,7 @@
|
|
|
45
46
|
"dependencies": {
|
|
46
47
|
"axios": "^1.12.2",
|
|
47
48
|
"framer-motion": "^12.23.2",
|
|
48
|
-
"next": "
|
|
49
|
+
"next": "16.0.10",
|
|
49
50
|
"react-hook-form": "^7.62.0",
|
|
50
51
|
"react-icons": "^5.5.0",
|
|
51
52
|
"styled-components": "^6.1.19",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { tv } from 'tailwind-variants';
|
|
2
|
-
import {
|
|
2
|
+
import type { TableListItemType } from '../types/tableListItem';
|
|
3
3
|
|
|
4
4
|
const itemContainer = tv({
|
|
5
5
|
base: 'rounded-2xl mb-2 px-8 py-3 flex flex-wrap items-center justify-between gap-4',
|
|
@@ -92,7 +92,7 @@ const RowCell = ({
|
|
|
92
92
|
<p className="text-base font-medium text-gray-400 flex items-center gap-1">
|
|
93
93
|
{header.filterAccessor === 'formattedAddress' && <HomeIcon />}
|
|
94
94
|
{header.filterAccessor === 'formattedAddress' ? (
|
|
95
|
-
<span className="
|
|
95
|
+
<span className="break-words max-w-[200px] block">
|
|
96
96
|
{item[header.filterAccessor]}
|
|
97
97
|
</span>
|
|
98
98
|
) : header.filterAccessor === 'status' ? (
|
package/src/components/Toast.tsx
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
<<<<<<< HEAD
|
|
1
2
|
export { default as FileUpload } from './components/FileUpload';
|
|
3
|
+
=======
|
|
4
|
+
>>>>>>> develop
|
|
2
5
|
export { Filter } from './components/Filter/Filter';
|
|
3
|
-
export { default as ModeSwitch } from './components/ModeSwitch';
|
|
4
6
|
export { default as NavMenu } from './components/NavMenu';
|
|
5
7
|
export { Search } from './components/SearchBar/Search';
|
|
6
8
|
export { SortBy } from './components/SortBy/SortBy';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
1
2
|
import styled from 'styled-components';
|
|
2
3
|
import { ExtendedButton, Header, TermsCheckbox } from '../../atoms';
|
|
3
4
|
import { ContactForm } from '../../organism';
|
|
@@ -75,7 +76,7 @@ interface ContactProps {
|
|
|
75
76
|
termsVariant?: 'primary' | 'secondary' | 'subtle';
|
|
76
77
|
buttonArrowVariant?: 'brand' | 'teal' | 'blue';
|
|
77
78
|
buttonTextBgVariant?: 'primary' | 'secondary' | 'tertiary' | 'subtle' | 'blue' | 'brand' | 'light' | 'transparent';
|
|
78
|
-
buttonTextVariant?:
|
|
79
|
+
buttonTextVariant?: ComponentProps<typeof ExtendedButton>['textVariant'];
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
export const Contact = ({
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ComponentProps } from 'react';
|
|
1
2
|
import styled from 'styled-components';
|
|
2
3
|
import { Header } from '../../atoms';
|
|
3
4
|
import { ProductInfo } from '../../molecules';
|
|
@@ -45,7 +46,7 @@ interface OtherProductsProps {
|
|
|
45
46
|
productTitleColor?: ComponentTextColor;
|
|
46
47
|
productButtonArrowVariant?: 'brand' | 'teal' | 'blue';
|
|
47
48
|
productButtonTextBgVariant?: 'primary' | 'secondary' | 'tertiary' | 'subtle' | 'blue' | 'brand' | 'light' | 'transparent';
|
|
48
|
-
productButtonTextVariant?:
|
|
49
|
+
productButtonTextVariant?: ComponentProps<typeof ProductInfo>['buttonTextVariant'];
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
export const OtherProducts = ({
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { InputAttributes } from '../../types/inputAttributes';
|
|
2
|
-
|
|
3
|
-
interface Props {
|
|
4
|
-
field: InputAttributes;
|
|
5
|
-
setValue: (field: string, value: string) => void;
|
|
6
|
-
}
|
|
7
|
-
export default function DynamicInput({ field, setValue }: Props) {
|
|
8
|
-
const control = () => {
|
|
9
|
-
switch (field.type) {
|
|
10
|
-
case 'Date':
|
|
11
|
-
return (
|
|
12
|
-
<>
|
|
13
|
-
<input
|
|
14
|
-
className="w-full border-0 text-sm bg-gray-50 text-gray-800 outline-none"
|
|
15
|
-
type="date"
|
|
16
|
-
placeholder={field.title}
|
|
17
|
-
required={field.required}
|
|
18
|
-
onChange={(event) => setValue(field.field, event.target.value)}
|
|
19
|
-
/>
|
|
20
|
-
<label className="mt-auto text-xs text-gray-400 pt-2">
|
|
21
|
-
{field.title}
|
|
22
|
-
</label>
|
|
23
|
-
</>
|
|
24
|
-
);
|
|
25
|
-
case 'Boolean':
|
|
26
|
-
return (
|
|
27
|
-
<p className="flex flex-row">
|
|
28
|
-
<input
|
|
29
|
-
className="border-0 text-sm bg-gray-50 text-gray-800 outline-none mr-2"
|
|
30
|
-
type="checkbox"
|
|
31
|
-
placeholder={field.title}
|
|
32
|
-
onChange={(event) =>
|
|
33
|
-
setValue(field.field, event.target.checked ? 'Yes' : 'No')
|
|
34
|
-
}
|
|
35
|
-
/>
|
|
36
|
-
<label className="mt-auto text-sm text-gray-400">
|
|
37
|
-
{field.title}
|
|
38
|
-
</label>
|
|
39
|
-
</p>
|
|
40
|
-
);
|
|
41
|
-
default:
|
|
42
|
-
return (
|
|
43
|
-
<input
|
|
44
|
-
className="w-full text-sm bg-transparent text-gray-700 dark:text-gray-300 outline-none relative py-4 px-3 rounded-lg border border-gray-400 hover:border-white focus-within:border-blue-500"
|
|
45
|
-
type={field.type?.toLowerCase() || 'text'}
|
|
46
|
-
placeholder={field.title}
|
|
47
|
-
required={field.required}
|
|
48
|
-
onChange={(event) => setValue(field.field, event.target.value)}
|
|
49
|
-
/>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
return <div className="flex flex-col p-2">{control()}</div>;
|
|
54
|
-
}
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import axios from 'axios';
|
|
5
|
-
|
|
6
|
-
interface FileUploadFormProps {
|
|
7
|
-
setFile: (file: File | null) => void;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default function FileUploadForm({ setFile }: FileUploadFormProps) {
|
|
11
|
-
const [progress, setProgress] = useState(0);
|
|
12
|
-
const [message, setMessage] = useState('');
|
|
13
|
-
const [dragOver, setDragOver] = useState(false);
|
|
14
|
-
const [file, setLocalFile] = useState<File | null>(null);
|
|
15
|
-
|
|
16
|
-
const handleFile = (selected: File) => {
|
|
17
|
-
if (selected) {
|
|
18
|
-
setLocalFile(selected);
|
|
19
|
-
setFile(selected);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
24
|
-
const selected = e.target.files?.[0];
|
|
25
|
-
if (selected) handleFile(selected);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const handleDrop = (event: React.DragEvent<HTMLDivElement>) => {
|
|
29
|
-
event.preventDefault();
|
|
30
|
-
setDragOver(false);
|
|
31
|
-
const droppedFile = event.dataTransfer.files?.[0];
|
|
32
|
-
if (droppedFile) handleFile(droppedFile);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
|
|
36
|
-
event.preventDefault();
|
|
37
|
-
setDragOver(true);
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const handleDragLeave = () => setDragOver(false);
|
|
41
|
-
|
|
42
|
-
const toBase64 = (file: File): Promise<string> =>
|
|
43
|
-
new Promise((resolve, reject) => {
|
|
44
|
-
const reader = new FileReader();
|
|
45
|
-
reader.readAsDataURL(file);
|
|
46
|
-
reader.onload = () => resolve((reader.result as string).split(',')[1]);
|
|
47
|
-
reader.onerror = reject;
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const handleSubmit = async (e: React.FormEvent) => {
|
|
51
|
-
e.preventDefault();
|
|
52
|
-
setProgress(0);
|
|
53
|
-
setMessage('');
|
|
54
|
-
if (!file) return setMessage('❌ No file selected.');
|
|
55
|
-
|
|
56
|
-
try {
|
|
57
|
-
const base64 = await toBase64(file);
|
|
58
|
-
|
|
59
|
-
await axios.post(
|
|
60
|
-
'/api/upload',
|
|
61
|
-
{
|
|
62
|
-
fileName: file.name,
|
|
63
|
-
base64File: base64,
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
onUploadProgress: (event) => {
|
|
67
|
-
const percent = event.total
|
|
68
|
-
? Math.round((event.loaded / event.total) * 100)
|
|
69
|
-
: 0;
|
|
70
|
-
setProgress(percent);
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
setMessage('✅ Submitted successfully!');
|
|
76
|
-
} catch (err) {
|
|
77
|
-
console.error(err);
|
|
78
|
-
setMessage('❌ Upload failed.');
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
return (
|
|
83
|
-
<form
|
|
84
|
-
onSubmit={handleSubmit}
|
|
85
|
-
className="max-w-xl mx-auto p-6 space-y-6 bg-white dark:bg-transparent rounded-lg shadow"
|
|
86
|
-
>
|
|
87
|
-
{/* Drag and Drop + Button + Preview */}
|
|
88
|
-
<div
|
|
89
|
-
onDragOver={handleDragOver}
|
|
90
|
-
onDragLeave={handleDragLeave}
|
|
91
|
-
onDrop={handleDrop}
|
|
92
|
-
className={`flex flex-col items-center justify-center px-4 py-10 border-gray-300 border-2 border-dashed rounded-md text-center transition ${
|
|
93
|
-
dragOver ? 'bg-blue-50' : 'bg-white dark:bg-transparent '
|
|
94
|
-
}`}
|
|
95
|
-
>
|
|
96
|
-
+
|
|
97
|
-
<p className="text-sm text-gray-300 mb-2">
|
|
98
|
-
{file ? `Selected: ${file.name}` : 'Drag & drop your file here'}
|
|
99
|
-
</p>
|
|
100
|
-
</div>
|
|
101
|
-
|
|
102
|
-
{/* Progress Bar */}
|
|
103
|
-
{progress > 0 && (
|
|
104
|
-
<div className="w-full bg-gray-200 rounded-full h-4 overflow-hidden">
|
|
105
|
-
<div
|
|
106
|
-
className="bg-blue-600 h-4 transition-all"
|
|
107
|
-
style={{ width: `${progress}%` }}
|
|
108
|
-
/>
|
|
109
|
-
</div>
|
|
110
|
-
)}
|
|
111
|
-
|
|
112
|
-
{message && (
|
|
113
|
-
<p
|
|
114
|
-
className={`text-sm ${
|
|
115
|
-
message.includes('✅') ? 'text-green-600' : 'text-red-600'
|
|
116
|
-
}`}
|
|
117
|
-
>
|
|
118
|
-
{message}
|
|
119
|
-
</p>
|
|
120
|
-
)}
|
|
121
|
-
</form>
|
|
122
|
-
);
|
|
123
|
-
}
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
const toggleMode = (mode: string) => {
|
|
4
|
-
document.cookie = `mode=${mode}; path=/; max-age=31536000`;
|
|
5
|
-
window.location.reload();
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export default function SwitchButton() {
|
|
9
|
-
return (
|
|
10
|
-
<div className="inline-flex shadow-md bg-white dark:bg-gray-500 shadow-gray-900 rounded-xl border-0">
|
|
11
|
-
<button
|
|
12
|
-
onClick={() => toggleMode('')}
|
|
13
|
-
className="p-1 border-r border-1 border-gray-800"
|
|
14
|
-
>
|
|
15
|
-
<svg
|
|
16
|
-
fill="#d0d0d0"
|
|
17
|
-
viewBox="0 0 24 24"
|
|
18
|
-
height="20px"
|
|
19
|
-
width="20px"
|
|
20
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
21
|
-
>
|
|
22
|
-
<g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
|
|
23
|
-
<g
|
|
24
|
-
id="SVGRepo_tracerCarrier"
|
|
25
|
-
strokeLinecap="round"
|
|
26
|
-
strokeLinejoin="round"
|
|
27
|
-
></g>
|
|
28
|
-
<g id="SVGRepo_iconCarrier">
|
|
29
|
-
<path
|
|
30
|
-
d="M12 3V4M12 20V21M4 12H3M6.31412 6.31412L5.5 5.5M17.6859 6.31412L18.5 5.5M6.31412 17.69L5.5 18.5001M17.6859 17.69L18.5 18.5001M21 12H20M16 12C16 14.2091 14.2091 16 12 16C9.79086 16 8 14.2091 8 12C8 9.79086 9.79086 8 12 8C14.2091 8 16 9.79086 16 12Z"
|
|
31
|
-
stroke="#d0d0d0"
|
|
32
|
-
strokeWidth="2"
|
|
33
|
-
strokeLinecap="round"
|
|
34
|
-
strokeLinejoin="round"
|
|
35
|
-
></path>
|
|
36
|
-
</g>
|
|
37
|
-
</svg>
|
|
38
|
-
</button>
|
|
39
|
-
<button onClick={() => toggleMode('dark')} className="p-1.5">
|
|
40
|
-
<svg
|
|
41
|
-
fill="#757575"
|
|
42
|
-
height="16px"
|
|
43
|
-
width="16px"
|
|
44
|
-
version="1.1"
|
|
45
|
-
id="Layer_1"
|
|
46
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
47
|
-
viewBox="0 0 472.618 472.618"
|
|
48
|
-
>
|
|
49
|
-
<g id="SVGRepo_bgCarrier" strokeWidth="0"></g>
|
|
50
|
-
<g
|
|
51
|
-
id="SVGRepo_tracerCarrier"
|
|
52
|
-
strokeLinecap="round"
|
|
53
|
-
strokeLinejoin="round"
|
|
54
|
-
></g>
|
|
55
|
-
<g id="SVGRepo_iconCarrier">
|
|
56
|
-
<g>
|
|
57
|
-
<g>
|
|
58
|
-
<path d="M380.525,337.291c-135.427,0-245.302-109.773-245.302-245.302c0-32.502,6.338-63.575,17.991-91.988 C63.372,36.286,0,124.39,0,227.315c0,135.427,109.875,245.302,245.302,245.302c102.923,0,191.029-63.472,227.316-153.315 C444.201,330.954,413.129,337.291,380.525,337.291z"></path>
|
|
59
|
-
</g>
|
|
60
|
-
</g>
|
|
61
|
-
</g>
|
|
62
|
-
</svg>
|
|
63
|
-
</button>
|
|
64
|
-
</div>
|
|
65
|
-
);
|
|
66
|
-
}
|
package/types/index.ts
DELETED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|