braid-ui 1.0.98 → 1.0.99
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/README.md +44 -327
- package/components.json +20 -0
- package/eslint.config.js +29 -0
- package/index.html +24 -0
- package/package.json +55 -115
- package/postcss.config.js +6 -0
- package/public/favicon.ico +0 -0
- package/public/placeholder.svg +1 -0
- package/public/robots.txt +14 -0
- package/src/App.css +42 -0
- package/src/App.tsx +94 -0
- package/src/components/MainLayout.tsx +15 -0
- package/src/components/alerts/AlertDocuments.tsx +320 -0
- package/src/components/alerts/AlertNotes.tsx +185 -0
- package/src/components/alerts/AlertTimeline.tsx +79 -0
- package/src/components/alerts/ContextSection.tsx +155 -0
- package/src/components/app-sidebar.tsx +341 -0
- package/src/components/form-sections/ACHBankCard.tsx +78 -0
- package/src/components/form-sections/ACHBasicInfoCard.tsx +100 -0
- package/src/components/form-sections/ACHTransferSection.tsx +64 -0
- package/src/components/form-sections/AddressForm.tsx +94 -0
- package/src/components/form-sections/BankAddressCard.tsx +95 -0
- package/src/components/form-sections/BankingDetailsCard.tsx +46 -0
- package/src/components/form-sections/BasicInfoCard.tsx +103 -0
- package/src/components/form-sections/BasicInfoSection.tsx +34 -0
- package/src/components/form-sections/BeneficiaryAddress.tsx +19 -0
- package/src/components/form-sections/BeneficiaryCard.tsx +41 -0
- package/src/components/form-sections/BeneficiaryDomesticWire.tsx +23 -0
- package/src/components/form-sections/BusinessProfileCard.tsx +131 -0
- package/src/components/form-sections/BusinessStatusCard.tsx +53 -0
- package/src/components/form-sections/ContactInfoCard.tsx +63 -0
- package/src/components/form-sections/CounterpartyBasicInfo.tsx +101 -0
- package/src/components/form-sections/CounterpartyProfileCard.tsx +104 -0
- package/src/components/form-sections/CounterpartyRecordsCard.tsx +41 -0
- package/src/components/form-sections/IntermediaryCard.tsx +77 -0
- package/src/components/form-sections/IntermediaryFI.tsx +41 -0
- package/src/components/form-sections/IntermediaryFIAddress.tsx +14 -0
- package/src/components/form-sections/OriginatorCard.tsx +49 -0
- package/src/components/form-sections/OriginatorFI.tsx +42 -0
- package/src/components/form-sections/OriginatorFIAddress.tsx +14 -0
- package/src/components/form-sections/PaymentInformationSection.tsx +163 -0
- package/src/components/form-sections/ReceiverCard.tsx +94 -0
- package/src/components/form-sections/WireTransferSection.tsx +75 -0
- package/src/components/layouts/list-page.tsx +103 -0
- package/src/components/transaction/ACHDetailsSection.tsx +95 -0
- package/src/components/transaction/WireDetailsSection.tsx +112 -0
- package/src/components/ui/account-card.tsx +94 -0
- package/src/components/ui/badge.tsx +75 -0
- package/src/components/ui/breadcrumb.tsx +78 -0
- package/src/components/ui/business-type-badge.tsx +42 -0
- package/src/components/ui/button.tsx +56 -0
- package/src/components/ui/calendar.tsx +49 -0
- package/src/components/ui/card.tsx +223 -0
- package/src/components/ui/container.tsx +45 -0
- package/src/components/ui/counterparty-type-badge.tsx +53 -0
- package/src/components/ui/data-grid.tsx +99 -0
- package/src/components/ui/data-table.tsx +152 -0
- package/src/components/ui/detail-page-layout.tsx +83 -0
- package/src/components/ui/dialog.tsx +120 -0
- package/src/components/ui/dropdown-menu.tsx +82 -0
- package/src/components/ui/editable-form-card.tsx +106 -0
- package/src/components/ui/editable-info-field.tsx +67 -0
- package/src/components/ui/enhanced-input.tsx +78 -0
- package/src/components/ui/enhanced-select.tsx +101 -0
- package/src/components/ui/enhanced-textarea.tsx +64 -0
- package/src/components/ui/entity-card.tsx +140 -0
- package/src/components/ui/form-card.tsx +40 -0
- package/src/components/ui/form-field.tsx +50 -0
- package/src/components/ui/form-input.tsx +29 -0
- package/src/components/ui/form-provider.tsx +18 -0
- package/src/components/ui/form-section.tsx +66 -0
- package/src/components/ui/form-select.tsx +35 -0
- package/src/components/ui/info-field.tsx +36 -0
- package/src/components/ui/json-viewer.tsx +146 -0
- package/src/components/ui/label.tsx +24 -0
- package/src/components/ui/metric-card.tsx +80 -0
- package/src/components/ui/page-layout.tsx +183 -0
- package/src/components/ui/popover.tsx +29 -0
- package/src/components/ui/responsive-grid.tsx +46 -0
- package/src/components/ui/separator.tsx +31 -0
- package/src/components/ui/sheet.tsx +140 -0
- package/src/components/ui/sidebar.tsx +775 -0
- package/src/components/ui/sonner.tsx +29 -0
- package/src/components/ui/stack.tsx +77 -0
- package/src/components/ui/status-badge.tsx +68 -0
- package/src/components/ui/tabs.tsx +52 -0
- package/src/components/ui/toast.tsx +127 -0
- package/src/components/ui/toaster.tsx +33 -0
- package/src/components/ui/tooltip.tsx +28 -0
- package/src/components/ui/use-toast.ts +3 -0
- package/src/components/ui-kit/dashboard-demo.tsx +156 -0
- package/src/components/ui-kit/pattern-library.tsx +248 -0
- package/src/components/ui-kit/showcase.tsx +211 -0
- package/src/hooks/use-mobile.tsx +19 -0
- package/src/hooks/use-toast.ts +191 -0
- package/src/hooks/useEditState.ts +70 -0
- package/src/hooks/useFormWithEditState.ts +115 -0
- package/src/{styles.css → index.css} +10 -4
- package/src/lib/constants.ts +25 -0
- package/src/lib/mock-data/alert-data.ts +275 -0
- package/src/lib/mock-data/banking-data.ts +72 -0
- package/src/lib/mock-data/business-data.ts +71 -0
- package/src/lib/mock-data/counterparty-data.ts +70 -0
- package/src/lib/mock-data/index.ts +5 -0
- package/src/lib/mock-data/transaction-data.ts +283 -0
- package/src/lib/mock-data/wire-data.ts +103 -0
- package/src/lib/mock-data.tsx +180 -0
- package/src/lib/schemas/banking-schemas.ts +30 -0
- package/src/lib/schemas/business-schemas.ts +36 -0
- package/src/lib/schemas/counterparty-schemas.ts +43 -0
- package/src/lib/schemas/index.ts +5 -0
- package/src/lib/schemas/wire-schemas.ts +44 -0
- package/src/lib/utils.ts +6 -0
- package/src/main.tsx +10 -0
- package/src/pages/Cases.tsx +16 -0
- package/src/pages/Dashboard.tsx +16 -0
- package/src/pages/NotFound.tsx +27 -0
- package/src/pages/TransactionHistory.tsx +532 -0
- package/src/pages/UIKit.tsx +51 -0
- package/src/pages/alerts/AlertDetail.tsx +193 -0
- package/src/pages/alerts/Alerts.tsx +373 -0
- package/src/pages/business/Business.tsx +48 -0
- package/src/pages/business/Create.tsx +173 -0
- package/src/pages/counterparty/Create.tsx +48 -0
- package/src/pages/counterparty/DomesticWire.tsx +78 -0
- package/src/pages/counterparty/Manage.tsx +79 -0
- package/src/pages/transactions/NewTransaction.tsx +527 -0
- package/src/pages/transactions/TransactionDetail.tsx +192 -0
- package/src/vite-env.d.ts +1 -0
- package/tailwind.config.ts +124 -0
- package/tsconfig.app.json +30 -0
- package/tsconfig.json +19 -0
- package/tsconfig.node.json +22 -0
- package/vite.config.ts +22 -0
- package/dist/css/braid-ui-variables.css +0 -88
- package/dist/css/braid-ui.css +0 -4484
- package/dist/css/braid-ui.min.css +0 -1
- package/dist/index.cjs +0 -4
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -2429
- package/dist/index.d.ts +0 -2429
- package/dist/index.js +0 -4
- package/dist/index.js.map +0 -1
- package/src/styles-only.css +0 -121
- /package/{dist/braid-logo-343BOQZ2.png → src/assets/braid-logo.png} +0 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { EditableFormCard } from "@/components/ui/editable-form-card"
|
|
2
|
+
import { InfoField } from "@/components/ui/info-field"
|
|
3
|
+
import { FormProvider } from "@/components/ui/form-provider"
|
|
4
|
+
import { FormInput } from "@/components/ui/form-input"
|
|
5
|
+
import { FormSelect } from "@/components/ui/form-select"
|
|
6
|
+
import { useFormWithEditState } from "@/hooks/useFormWithEditState"
|
|
7
|
+
import { businessProfileSchema, type BusinessProfile } from "@/lib/schemas"
|
|
8
|
+
import { defaultBusinessProfile } from "@/lib/mock-data/business-data"
|
|
9
|
+
|
|
10
|
+
interface BusinessProfileCardProps {
|
|
11
|
+
data?: Partial<BusinessProfile>
|
|
12
|
+
onDataChange?: (data: BusinessProfile) => void
|
|
13
|
+
isEditing?: boolean
|
|
14
|
+
onToggleEdit?: () => void
|
|
15
|
+
className?: string
|
|
16
|
+
hideActions?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const BusinessProfileCard = ({
|
|
20
|
+
data,
|
|
21
|
+
onDataChange,
|
|
22
|
+
isEditing,
|
|
23
|
+
onToggleEdit,
|
|
24
|
+
className,
|
|
25
|
+
hideActions
|
|
26
|
+
}: BusinessProfileCardProps) => {
|
|
27
|
+
const form = useFormWithEditState<BusinessProfile>({
|
|
28
|
+
schema: businessProfileSchema,
|
|
29
|
+
defaultValues: { ...defaultBusinessProfile, ...data },
|
|
30
|
+
initialEditing: isEditing,
|
|
31
|
+
onToggleEdit,
|
|
32
|
+
onSave: onDataChange,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const editContent = (
|
|
36
|
+
<FormProvider form={form}>
|
|
37
|
+
<div className="space-y-6">
|
|
38
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
39
|
+
<FormInput
|
|
40
|
+
name="legalName"
|
|
41
|
+
label="Legal Name"
|
|
42
|
+
placeholder="Enter legal business name"
|
|
43
|
+
required
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
<FormInput
|
|
47
|
+
name="dbaName"
|
|
48
|
+
label="DBA Name"
|
|
49
|
+
placeholder="Enter doing business as name"
|
|
50
|
+
/>
|
|
51
|
+
|
|
52
|
+
<FormSelect
|
|
53
|
+
name="businessType"
|
|
54
|
+
label="Business Type"
|
|
55
|
+
placeholder="Select business type"
|
|
56
|
+
options={[
|
|
57
|
+
{ value: "corporation", label: "Corporation" },
|
|
58
|
+
{ value: "llc", label: "LLC" },
|
|
59
|
+
{ value: "partnership", label: "Partnership" },
|
|
60
|
+
{ value: "sole_proprietorship", label: "Sole Proprietorship" }
|
|
61
|
+
]}
|
|
62
|
+
/>
|
|
63
|
+
|
|
64
|
+
<FormInput
|
|
65
|
+
name="taxId"
|
|
66
|
+
label="Tax ID"
|
|
67
|
+
placeholder="Enter tax identification number"
|
|
68
|
+
required
|
|
69
|
+
/>
|
|
70
|
+
|
|
71
|
+
<FormInput
|
|
72
|
+
name="businessPhone"
|
|
73
|
+
label="Business Phone"
|
|
74
|
+
placeholder="Enter business phone number"
|
|
75
|
+
required
|
|
76
|
+
/>
|
|
77
|
+
|
|
78
|
+
<FormInput
|
|
79
|
+
name="businessEmail"
|
|
80
|
+
label="Business Email"
|
|
81
|
+
type="email"
|
|
82
|
+
placeholder="Enter business email"
|
|
83
|
+
required
|
|
84
|
+
/>
|
|
85
|
+
|
|
86
|
+
<FormInput
|
|
87
|
+
name="website"
|
|
88
|
+
label="Website"
|
|
89
|
+
placeholder="Enter website URL"
|
|
90
|
+
/>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
</FormProvider>
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
const formValues = form.watch()
|
|
97
|
+
const viewContent = (
|
|
98
|
+
<div className="space-y-4">
|
|
99
|
+
<div className="grid grid-cols-2 gap-4">
|
|
100
|
+
<InfoField label="Legal Name" value={formValues?.legalName} layout="horizontal" />
|
|
101
|
+
<InfoField label="DBA Name" value={formValues?.dbaName} layout="horizontal" />
|
|
102
|
+
</div>
|
|
103
|
+
<div className="grid grid-cols-2 gap-4">
|
|
104
|
+
<InfoField label="Business Type" value={formValues?.businessType} layout="horizontal" />
|
|
105
|
+
<InfoField label="Tax ID" value={formValues?.taxId} layout="horizontal" />
|
|
106
|
+
</div>
|
|
107
|
+
<div className="grid grid-cols-2 gap-4">
|
|
108
|
+
<InfoField label="Business Phone" value={formValues?.businessPhone} layout="horizontal" />
|
|
109
|
+
<InfoField label="Business Email" value={formValues?.businessEmail} layout="horizontal" />
|
|
110
|
+
</div>
|
|
111
|
+
<div className="grid grid-cols-2 gap-4">
|
|
112
|
+
<InfoField label="Website" value={formValues?.website} layout="horizontal" />
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<EditableFormCard
|
|
119
|
+
title="Business Profile"
|
|
120
|
+
variant="subtle"
|
|
121
|
+
className={className}
|
|
122
|
+
isEditing={form.isEditing}
|
|
123
|
+
onToggleEdit={form.handleToggleEdit}
|
|
124
|
+
onSave={form.handleSave}
|
|
125
|
+
onCancel={form.handleCancel}
|
|
126
|
+
hideActions={hideActions}
|
|
127
|
+
editContent={editContent}
|
|
128
|
+
viewContent={viewContent}
|
|
129
|
+
/>
|
|
130
|
+
)
|
|
131
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { FormCard } from "@/components/ui/form-card"
|
|
2
|
+
import { InfoField } from "@/components/ui/info-field"
|
|
3
|
+
import { Button } from "@/components/ui/button"
|
|
4
|
+
import { StatusBadge } from "@/components/ui/status-badge"
|
|
5
|
+
import { Edit } from "lucide-react"
|
|
6
|
+
|
|
7
|
+
interface BusinessStatusCardProps {
|
|
8
|
+
isEditing?: boolean
|
|
9
|
+
onToggleEdit?: () => void
|
|
10
|
+
className?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const BusinessStatusCard = ({ isEditing, onToggleEdit, className }: BusinessStatusCardProps) => {
|
|
14
|
+
return (
|
|
15
|
+
<FormCard
|
|
16
|
+
title="Business Status & Records"
|
|
17
|
+
className={className}
|
|
18
|
+
headerActions={
|
|
19
|
+
<div className="flex items-center gap-2">
|
|
20
|
+
{isEditing ? (
|
|
21
|
+
<>
|
|
22
|
+
<Button variant="outline" size="sm" onClick={onToggleEdit}>
|
|
23
|
+
Cancel
|
|
24
|
+
</Button>
|
|
25
|
+
<Button size="sm" onClick={onToggleEdit}>
|
|
26
|
+
Save
|
|
27
|
+
</Button>
|
|
28
|
+
</>
|
|
29
|
+
) : (
|
|
30
|
+
<Button variant="ghost" size="icon" onClick={onToggleEdit} className="text-primary hover:text-primary/80 hover:bg-primary/10">
|
|
31
|
+
<Edit className="h-4 w-4" />
|
|
32
|
+
</Button>
|
|
33
|
+
)}
|
|
34
|
+
</div>
|
|
35
|
+
}
|
|
36
|
+
>
|
|
37
|
+
<div className="space-y-4">
|
|
38
|
+
<div className="grid grid-cols-2 gap-4">
|
|
39
|
+
<InfoField label="Status" value={<StatusBadge status="ACTIVE" />} layout="horizontal" />
|
|
40
|
+
<InfoField label="CIP Status" value="NOT_START" layout="horizontal" />
|
|
41
|
+
</div>
|
|
42
|
+
<div className="grid grid-cols-2 gap-4">
|
|
43
|
+
<InfoField label="Created Date" value="2025-08-03" layout="horizontal" />
|
|
44
|
+
<InfoField label="Updated Date" value="2025-09-05" layout="horizontal" />
|
|
45
|
+
</div>
|
|
46
|
+
<div className="grid grid-cols-2 gap-4">
|
|
47
|
+
<InfoField label="Last OFAC Date" value="2025-09-05" layout="horizontal" />
|
|
48
|
+
<InfoField label="Last OFAC Status" value="View Status" layout="horizontal" className="text-primary cursor-pointer" />
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</FormCard>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { FormCard } from "@/components/ui/form-card"
|
|
2
|
+
import { InfoField } from "@/components/ui/info-field"
|
|
3
|
+
import { Button } from "@/components/ui/button"
|
|
4
|
+
import { Edit } from "lucide-react"
|
|
5
|
+
|
|
6
|
+
interface ContactInfoCardProps {
|
|
7
|
+
isEditing?: boolean
|
|
8
|
+
onToggleEdit?: () => void
|
|
9
|
+
className?: string
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const ContactInfoCard = ({ isEditing, onToggleEdit, className }: ContactInfoCardProps) => {
|
|
13
|
+
return (
|
|
14
|
+
<FormCard
|
|
15
|
+
title="Contact Information"
|
|
16
|
+
className={className}
|
|
17
|
+
headerActions={
|
|
18
|
+
<div className="flex items-center gap-2">
|
|
19
|
+
{isEditing ? (
|
|
20
|
+
<>
|
|
21
|
+
<Button variant="outline" size="sm" onClick={onToggleEdit}>
|
|
22
|
+
Cancel
|
|
23
|
+
</Button>
|
|
24
|
+
<Button size="sm" onClick={onToggleEdit}>
|
|
25
|
+
Save
|
|
26
|
+
</Button>
|
|
27
|
+
</>
|
|
28
|
+
) : (
|
|
29
|
+
<Button variant="ghost" size="icon" onClick={onToggleEdit} className="text-primary hover:text-primary/80 hover:bg-primary/10">
|
|
30
|
+
<Edit className="h-4 w-4" />
|
|
31
|
+
</Button>
|
|
32
|
+
)}
|
|
33
|
+
</div>
|
|
34
|
+
}
|
|
35
|
+
>
|
|
36
|
+
<div className="space-y-4">
|
|
37
|
+
<h4 className="text-sm font-medium text-muted-foreground">Contact Person</h4>
|
|
38
|
+
<div className="grid grid-cols-2 gap-4">
|
|
39
|
+
<InfoField label="First Name" value="" layout="horizontal" />
|
|
40
|
+
<InfoField label="Last Name" value="" layout="horizontal" />
|
|
41
|
+
</div>
|
|
42
|
+
<div className="grid grid-cols-2 gap-4">
|
|
43
|
+
<InfoField label="Email" value="" layout="horizontal" />
|
|
44
|
+
<InfoField label="Phone Number" value="" layout="horizontal" />
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<h4 className="text-sm font-medium text-muted-foreground mt-6">Mailing Address</h4>
|
|
48
|
+
<div className="grid grid-cols-1 gap-3">
|
|
49
|
+
<InfoField label="Street Address" value="" layout="horizontal" />
|
|
50
|
+
<InfoField label="Apartment, suite, or floor" value="" layout="horizontal" />
|
|
51
|
+
</div>
|
|
52
|
+
<div className="grid grid-cols-2 gap-4">
|
|
53
|
+
<InfoField label="City" value="" layout="horizontal" />
|
|
54
|
+
<InfoField label="State" value="Alabama" layout="horizontal" />
|
|
55
|
+
</div>
|
|
56
|
+
<div className="grid grid-cols-2 gap-4">
|
|
57
|
+
<InfoField label="Postal Code" value="" layout="horizontal" />
|
|
58
|
+
<InfoField label="Country Code" value="US" layout="horizontal" />
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</FormCard>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { EnhancedInput } from "@/components/ui/enhanced-input"
|
|
2
|
+
import { Label } from "@/components/ui/label"
|
|
3
|
+
import { useState } from "react"
|
|
4
|
+
|
|
5
|
+
interface CounterpartyBasicInfoProps {
|
|
6
|
+
onDataChange?: (data: any) => void
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const CounterpartyBasicInfo = ({ onDataChange }: CounterpartyBasicInfoProps) => {
|
|
10
|
+
const [formData, setFormData] = useState({
|
|
11
|
+
name: "",
|
|
12
|
+
type: "business",
|
|
13
|
+
email: "",
|
|
14
|
+
phone: "",
|
|
15
|
+
productId: "167990"
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
const handleInputChange = (field: string, value: string) => {
|
|
19
|
+
const updatedData = { ...formData, [field]: value }
|
|
20
|
+
setFormData(updatedData)
|
|
21
|
+
onDataChange?.(updatedData)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const handleTypeChange = (type: string) => {
|
|
25
|
+
handleInputChange("type", type)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className="space-y-6">
|
|
30
|
+
<div className="border-b border-border pb-4">
|
|
31
|
+
<h2 className="text-lg font-semibold text-foreground">Basic Information</h2>
|
|
32
|
+
<p className="text-sm text-muted-foreground">Enter the basic details for the counterparty</p>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div className="space-y-6">
|
|
36
|
+
<EnhancedInput
|
|
37
|
+
label="Counterparty Name"
|
|
38
|
+
value={formData.name}
|
|
39
|
+
onChange={(e) => handleInputChange("name", e.target.value)}
|
|
40
|
+
placeholder="Enter counterparty name"
|
|
41
|
+
required
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
<div className="space-y-3">
|
|
45
|
+
<Label className="text-sm font-medium">Counterparty Type</Label>
|
|
46
|
+
<div className="flex gap-6">
|
|
47
|
+
<label className="flex items-center space-x-2 cursor-pointer">
|
|
48
|
+
<input
|
|
49
|
+
type="radio"
|
|
50
|
+
name="counterpartyType"
|
|
51
|
+
value="business"
|
|
52
|
+
checked={formData.type === "business"}
|
|
53
|
+
onChange={() => handleTypeChange("business")}
|
|
54
|
+
className="w-4 h-4 text-primary border-border focus:ring-primary focus:ring-2"
|
|
55
|
+
/>
|
|
56
|
+
<span className="text-sm text-foreground">Business</span>
|
|
57
|
+
</label>
|
|
58
|
+
<label className="flex items-center space-x-2 cursor-pointer">
|
|
59
|
+
<input
|
|
60
|
+
type="radio"
|
|
61
|
+
name="counterpartyType"
|
|
62
|
+
value="individual"
|
|
63
|
+
checked={formData.type === "individual"}
|
|
64
|
+
onChange={() => handleTypeChange("individual")}
|
|
65
|
+
className="w-4 h-4 text-primary border-border focus:ring-primary focus:ring-2"
|
|
66
|
+
/>
|
|
67
|
+
<span className="text-sm text-foreground">Individual</span>
|
|
68
|
+
</label>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
73
|
+
<EnhancedInput
|
|
74
|
+
label="Email"
|
|
75
|
+
type="email"
|
|
76
|
+
value={formData.email}
|
|
77
|
+
onChange={(e) => handleInputChange("email", e.target.value)}
|
|
78
|
+
placeholder="Enter email address"
|
|
79
|
+
required
|
|
80
|
+
/>
|
|
81
|
+
|
|
82
|
+
<EnhancedInput
|
|
83
|
+
label="Phone Number"
|
|
84
|
+
type="tel"
|
|
85
|
+
value={formData.phone}
|
|
86
|
+
onChange={(e) => handleInputChange("phone", e.target.value)}
|
|
87
|
+
placeholder="Enter phone number"
|
|
88
|
+
required
|
|
89
|
+
/>
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
<EnhancedInput
|
|
93
|
+
label="Product ID"
|
|
94
|
+
value={formData.productId}
|
|
95
|
+
readOnly
|
|
96
|
+
className="bg-muted"
|
|
97
|
+
/>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { EditableFormCard } from "@/components/ui/editable-form-card"
|
|
2
|
+
import { InfoField } from "@/components/ui/info-field"
|
|
3
|
+
import { FormProvider } from "@/components/ui/form-provider"
|
|
4
|
+
import { FormInput } from "@/components/ui/form-input"
|
|
5
|
+
import { FormSelect } from "@/components/ui/form-select"
|
|
6
|
+
import { CounterpartyTypeBadge } from "@/components/ui/counterparty-type-badge"
|
|
7
|
+
import { StatusBadge } from "@/components/ui/status-badge"
|
|
8
|
+
import { useFormWithEditState } from "@/hooks/useFormWithEditState"
|
|
9
|
+
import { counterpartyBasicInfoSchema, type CounterpartyBasicInfo } from "@/lib/schemas"
|
|
10
|
+
import { defaultCounterpartyBasicInfo } from "@/lib/mock-data/counterparty-data"
|
|
11
|
+
|
|
12
|
+
interface CounterpartyProfileCardProps {
|
|
13
|
+
data?: Partial<CounterpartyBasicInfo>
|
|
14
|
+
onDataChange?: (data: CounterpartyBasicInfo) => void
|
|
15
|
+
isEditing?: boolean
|
|
16
|
+
onToggleEdit?: () => void
|
|
17
|
+
hideActions?: boolean
|
|
18
|
+
className?: string
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const CounterpartyProfileCard = ({
|
|
22
|
+
data,
|
|
23
|
+
onDataChange,
|
|
24
|
+
isEditing = false,
|
|
25
|
+
onToggleEdit,
|
|
26
|
+
hideActions = false,
|
|
27
|
+
className
|
|
28
|
+
}: CounterpartyProfileCardProps) => {
|
|
29
|
+
const form = useFormWithEditState<CounterpartyBasicInfo>({
|
|
30
|
+
schema: counterpartyBasicInfoSchema,
|
|
31
|
+
defaultValues: { ...defaultCounterpartyBasicInfo, ...data },
|
|
32
|
+
initialEditing: isEditing,
|
|
33
|
+
onToggleEdit,
|
|
34
|
+
onSave: onDataChange,
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
const editContent = (
|
|
38
|
+
<FormProvider form={form}>
|
|
39
|
+
<div className="space-y-6">
|
|
40
|
+
<FormInput
|
|
41
|
+
name="name"
|
|
42
|
+
label="Name"
|
|
43
|
+
placeholder="Enter counterparty name"
|
|
44
|
+
required
|
|
45
|
+
/>
|
|
46
|
+
|
|
47
|
+
<FormSelect
|
|
48
|
+
name="type"
|
|
49
|
+
label="Counterparty Type"
|
|
50
|
+
placeholder="Select counterparty type"
|
|
51
|
+
options={[
|
|
52
|
+
{ value: "BUSINESS", label: "Business" },
|
|
53
|
+
{ value: "INDIVIDUAL", label: "Individual" },
|
|
54
|
+
{ value: "GOVERNMENT", label: "Government" },
|
|
55
|
+
{ value: "NONPROFIT", label: "Non-Profit" }
|
|
56
|
+
]}
|
|
57
|
+
/>
|
|
58
|
+
|
|
59
|
+
<FormSelect
|
|
60
|
+
name="status"
|
|
61
|
+
label="Status"
|
|
62
|
+
placeholder="Select status"
|
|
63
|
+
options={[
|
|
64
|
+
{ value: "ACTIVE", label: "Active" },
|
|
65
|
+
{ value: "INACTIVE", label: "Inactive" },
|
|
66
|
+
{ value: "PENDING", label: "Pending" },
|
|
67
|
+
{ value: "SUSPENDED", label: "Suspended" }
|
|
68
|
+
]}
|
|
69
|
+
/>
|
|
70
|
+
|
|
71
|
+
<FormInput
|
|
72
|
+
name="description"
|
|
73
|
+
label="Description"
|
|
74
|
+
placeholder="Enter description"
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
</FormProvider>
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
const formValues = form.watch()
|
|
81
|
+
const viewContent = (
|
|
82
|
+
<div className="space-y-3">
|
|
83
|
+
<InfoField label="Name" value={formValues?.name} layout="horizontal" />
|
|
84
|
+
<InfoField label="Counterparty Type" value={<CounterpartyTypeBadge type={formValues?.type as "BUSINESS" | "INDIVIDUAL" | "GOVERNMENT" | "NONPROFIT"} />} layout="horizontal" />
|
|
85
|
+
<InfoField label="Status" value={<StatusBadge status={formValues?.status as "ACTIVE" | "INACTIVE" | "PENDING" | "SUSPENDED"} />} layout="horizontal" />
|
|
86
|
+
<InfoField label="Description" value={formValues?.description} layout="horizontal" />
|
|
87
|
+
</div>
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<EditableFormCard
|
|
92
|
+
title="Profile Information"
|
|
93
|
+
variant="subtle"
|
|
94
|
+
className={className}
|
|
95
|
+
isEditing={form.isEditing}
|
|
96
|
+
onToggleEdit={form.handleToggleEdit}
|
|
97
|
+
onSave={form.handleSave}
|
|
98
|
+
onCancel={form.handleCancel}
|
|
99
|
+
hideActions={hideActions}
|
|
100
|
+
editContent={editContent}
|
|
101
|
+
viewContent={viewContent}
|
|
102
|
+
/>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
|
2
|
+
import { InfoField } from "@/components/ui/info-field"
|
|
3
|
+
|
|
4
|
+
interface CounterpartyRecordsCardProps {
|
|
5
|
+
isEditing?: boolean
|
|
6
|
+
hideActions?: boolean
|
|
7
|
+
className?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const CounterpartyRecordsCard = ({
|
|
11
|
+
isEditing = false,
|
|
12
|
+
hideActions = false,
|
|
13
|
+
className
|
|
14
|
+
}: CounterpartyRecordsCardProps) => {
|
|
15
|
+
return (
|
|
16
|
+
<Card variant="subtle" className={className}>
|
|
17
|
+
<CardHeader size="lg">
|
|
18
|
+
<CardTitle size="lg">System Records</CardTitle>
|
|
19
|
+
</CardHeader>
|
|
20
|
+
<CardContent size="lg">
|
|
21
|
+
<div className="space-y-4">
|
|
22
|
+
<div className="space-y-3">
|
|
23
|
+
<InfoField label="ID" value="5000541" layout="horizontal" />
|
|
24
|
+
<InfoField label="Created By" value="admin" layout="horizontal" />
|
|
25
|
+
<InfoField label="Created At" value="2025-07-14" layout="horizontal" />
|
|
26
|
+
<InfoField label="Updated By" value="admin" layout="horizontal" />
|
|
27
|
+
<InfoField label="Updated At" value="2025-07-14" layout="horizontal" />
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div className="pt-3 border-t border-border">
|
|
31
|
+
<h4 className="text-sm font-medium text-foreground mb-2">OFAC Details</h4>
|
|
32
|
+
<div className="space-y-3">
|
|
33
|
+
<InfoField label="Last OFAC date" value="2025-07-14" layout="horizontal" />
|
|
34
|
+
<InfoField label="Last OFAC status" value="Verified" layout="horizontal" />
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</CardContent>
|
|
39
|
+
</Card>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { EditableFormCard } from "@/components/ui/editable-form-card"
|
|
2
|
+
import { InfoField } from "@/components/ui/info-field"
|
|
3
|
+
import { FormProvider } from "@/components/ui/form-provider"
|
|
4
|
+
import { FormSection } from "@/components/ui/form-section"
|
|
5
|
+
import { IntermediaryFI } from "@/components/form-sections/IntermediaryFI"
|
|
6
|
+
import { IntermediaryFIAddress } from "@/components/form-sections/IntermediaryFIAddress"
|
|
7
|
+
import { useFormWithEditState } from "@/hooks/useFormWithEditState"
|
|
8
|
+
import { intermediaryFISchema, type IntermediaryFI as IntermediaryFIType } from "@/lib/schemas"
|
|
9
|
+
import { defaultIntermediaryFIInfo } from "@/lib/mock-data/wire-data"
|
|
10
|
+
|
|
11
|
+
interface IntermediaryCardProps {
|
|
12
|
+
data?: Partial<IntermediaryFIType>
|
|
13
|
+
onDataChange?: (data: IntermediaryFIType) => void
|
|
14
|
+
isEditing?: boolean
|
|
15
|
+
onToggleEdit?: () => void
|
|
16
|
+
className?: string
|
|
17
|
+
hideActions?: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const IntermediaryCard = ({
|
|
21
|
+
data,
|
|
22
|
+
onDataChange,
|
|
23
|
+
isEditing,
|
|
24
|
+
onToggleEdit,
|
|
25
|
+
className,
|
|
26
|
+
hideActions
|
|
27
|
+
}: IntermediaryCardProps) => {
|
|
28
|
+
const form = useFormWithEditState<IntermediaryFIType>({
|
|
29
|
+
schema: intermediaryFISchema,
|
|
30
|
+
defaultValues: { ...defaultIntermediaryFIInfo, ...data },
|
|
31
|
+
initialEditing: isEditing,
|
|
32
|
+
onToggleEdit,
|
|
33
|
+
onSave: onDataChange,
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const editContent = (
|
|
37
|
+
<FormProvider form={form}>
|
|
38
|
+
<FormSection spacing="lg">
|
|
39
|
+
<IntermediaryFI />
|
|
40
|
+
<IntermediaryFIAddress />
|
|
41
|
+
</FormSection>
|
|
42
|
+
</FormProvider>
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
const formValues = form.watch()
|
|
46
|
+
const viewContent = (
|
|
47
|
+
<div className="space-y-3">
|
|
48
|
+
<div>
|
|
49
|
+
<h4 className="text-sm font-medium text-foreground mb-2">Financial Institution</h4>
|
|
50
|
+
<div className="space-y-1.5">
|
|
51
|
+
<InfoField label="Institution" value={`${formValues?.name} (${formValues?.accountNumber})`} layout="horizontal" />
|
|
52
|
+
<InfoField label="Identifier" value={`${formValues?.idType?.toUpperCase()} - ${formValues?.idNumber}`} layout="horizontal" />
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<div className="pt-3 border-t border-border">
|
|
57
|
+
<h4 className="text-sm font-medium text-foreground mb-2">FI Address</h4>
|
|
58
|
+
<InfoField value={formValues?.address ? `${formValues.address.streetAddress}, ${formValues.address.city}, ${formValues.address.postalCode}, ${formValues.address.country}` : ""} />
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<EditableFormCard
|
|
65
|
+
title="Intermediary"
|
|
66
|
+
variant="subtle"
|
|
67
|
+
className={className}
|
|
68
|
+
isEditing={form.isEditing}
|
|
69
|
+
onToggleEdit={form.handleToggleEdit}
|
|
70
|
+
onSave={form.handleSave}
|
|
71
|
+
onCancel={form.handleCancel}
|
|
72
|
+
hideActions={hideActions}
|
|
73
|
+
editContent={editContent}
|
|
74
|
+
viewContent={viewContent}
|
|
75
|
+
/>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { EnhancedInput } from "@/components/ui/enhanced-input"
|
|
2
|
+
import { EnhancedSelect } from "@/components/ui/enhanced-select"
|
|
3
|
+
import { FI_ID_TYPE_OPTIONS } from "@/lib/constants"
|
|
4
|
+
|
|
5
|
+
export const IntermediaryFI = () => {
|
|
6
|
+
return (
|
|
7
|
+
<div className="space-y-6">
|
|
8
|
+
<div className="border-b border-border pb-4">
|
|
9
|
+
<h2 className="text-lg font-semibold text-foreground">Intermediary FI Details</h2>
|
|
10
|
+
<p className="text-sm text-muted-foreground">Financial institution details for the intermediary</p>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<div className="space-y-6">
|
|
14
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
15
|
+
<EnhancedInput
|
|
16
|
+
label="Intermediary FI Account Number"
|
|
17
|
+
placeholder="Enter account number"
|
|
18
|
+
/>
|
|
19
|
+
|
|
20
|
+
<EnhancedInput
|
|
21
|
+
label="Intermediary FI Name"
|
|
22
|
+
placeholder="Enter FI name"
|
|
23
|
+
hint="Full name of the intermediary financial institution"
|
|
24
|
+
/>
|
|
25
|
+
|
|
26
|
+
<EnhancedSelect
|
|
27
|
+
label="Intermediary FI ID Type"
|
|
28
|
+
placeholder="Select ID type"
|
|
29
|
+
options={FI_ID_TYPE_OPTIONS}
|
|
30
|
+
/>
|
|
31
|
+
|
|
32
|
+
<EnhancedInput
|
|
33
|
+
label="Intermediary FI ID Number"
|
|
34
|
+
placeholder="Enter ID number"
|
|
35
|
+
hint="Financial institution identification number"
|
|
36
|
+
/>
|
|
37
|
+
</div>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { AddressForm } from "./AddressForm"
|
|
2
|
+
|
|
3
|
+
export const IntermediaryFIAddress = () => {
|
|
4
|
+
return (
|
|
5
|
+
<AddressForm
|
|
6
|
+
title="Intermediary FI Address"
|
|
7
|
+
description="Address of the intermediary financial institution"
|
|
8
|
+
fieldPrefix="Intermediary FI"
|
|
9
|
+
fieldOverrides={{
|
|
10
|
+
streetAddress: { hint: "Intermediary financial institution street address" }
|
|
11
|
+
}}
|
|
12
|
+
/>
|
|
13
|
+
)
|
|
14
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EditableFormCard } from "@/components/ui/editable-form-card"
|
|
2
|
+
import { DataGrid } from "@/components/ui/data-grid"
|
|
3
|
+
import { FormSection } from "@/components/ui/form-section"
|
|
4
|
+
import { OriginatorFI } from "@/components/form-sections/OriginatorFI"
|
|
5
|
+
import { OriginatorFIAddress } from "@/components/form-sections/OriginatorFIAddress"
|
|
6
|
+
|
|
7
|
+
interface OriginatorCardProps {
|
|
8
|
+
isEditing?: boolean
|
|
9
|
+
onToggleEdit?: () => void
|
|
10
|
+
className?: string
|
|
11
|
+
hideActions?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const OriginatorCard = ({ isEditing, onToggleEdit, className, hideActions }: OriginatorCardProps) => {
|
|
15
|
+
const viewData = [
|
|
16
|
+
{
|
|
17
|
+
title: "Financial Institution",
|
|
18
|
+
items: [
|
|
19
|
+
{ label: "Institution", value: "JPMorgan Chase Bank (1234567890)" },
|
|
20
|
+
{ label: "Identifier", value: "ABA - 021000021" }
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
title: "FI Address",
|
|
25
|
+
items: [
|
|
26
|
+
{ value: "270 Park Avenue, New York, NY, 10017, United States" }
|
|
27
|
+
],
|
|
28
|
+
className: "pt-3 border-t border-border"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<EditableFormCard
|
|
34
|
+
title="Originator"
|
|
35
|
+
variant="subtle"
|
|
36
|
+
className={className}
|
|
37
|
+
isEditing={isEditing}
|
|
38
|
+
onToggleEdit={onToggleEdit}
|
|
39
|
+
hideActions={hideActions}
|
|
40
|
+
editContent={
|
|
41
|
+
<FormSection spacing="lg">
|
|
42
|
+
<OriginatorFI />
|
|
43
|
+
<OriginatorFIAddress />
|
|
44
|
+
</FormSection>
|
|
45
|
+
}
|
|
46
|
+
viewContent={<DataGrid data={viewData} columns={1} />}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
}
|