braid-ui 1.0.99 → 1.0.100

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.
Files changed (145) hide show
  1. package/README.md +327 -44
  2. package/dist/css/braid-ui-variables.css +88 -0
  3. package/dist/css/braid-ui.css +4702 -0
  4. package/dist/css/braid-ui.min.css +1 -0
  5. package/dist/index.cjs +4 -0
  6. package/dist/index.cjs.map +1 -0
  7. package/dist/index.d.cts +2027 -0
  8. package/dist/index.d.ts +2027 -0
  9. package/dist/index.js +4 -0
  10. package/dist/index.js.map +1 -0
  11. package/package.json +115 -55
  12. package/src/styles-only.css +121 -0
  13. package/src/{index.css → styles.css} +4 -10
  14. package/components.json +0 -20
  15. package/eslint.config.js +0 -29
  16. package/index.html +0 -24
  17. package/postcss.config.js +0 -6
  18. package/public/favicon.ico +0 -0
  19. package/public/placeholder.svg +0 -1
  20. package/public/robots.txt +0 -14
  21. package/src/App.css +0 -42
  22. package/src/App.tsx +0 -94
  23. package/src/components/MainLayout.tsx +0 -15
  24. package/src/components/alerts/AlertDocuments.tsx +0 -320
  25. package/src/components/alerts/AlertNotes.tsx +0 -185
  26. package/src/components/alerts/AlertTimeline.tsx +0 -79
  27. package/src/components/alerts/ContextSection.tsx +0 -155
  28. package/src/components/app-sidebar.tsx +0 -341
  29. package/src/components/form-sections/ACHBankCard.tsx +0 -78
  30. package/src/components/form-sections/ACHBasicInfoCard.tsx +0 -100
  31. package/src/components/form-sections/ACHTransferSection.tsx +0 -64
  32. package/src/components/form-sections/AddressForm.tsx +0 -94
  33. package/src/components/form-sections/BankAddressCard.tsx +0 -95
  34. package/src/components/form-sections/BankingDetailsCard.tsx +0 -46
  35. package/src/components/form-sections/BasicInfoCard.tsx +0 -103
  36. package/src/components/form-sections/BasicInfoSection.tsx +0 -34
  37. package/src/components/form-sections/BeneficiaryAddress.tsx +0 -19
  38. package/src/components/form-sections/BeneficiaryCard.tsx +0 -41
  39. package/src/components/form-sections/BeneficiaryDomesticWire.tsx +0 -23
  40. package/src/components/form-sections/BusinessProfileCard.tsx +0 -131
  41. package/src/components/form-sections/BusinessStatusCard.tsx +0 -53
  42. package/src/components/form-sections/ContactInfoCard.tsx +0 -63
  43. package/src/components/form-sections/CounterpartyBasicInfo.tsx +0 -101
  44. package/src/components/form-sections/CounterpartyProfileCard.tsx +0 -104
  45. package/src/components/form-sections/CounterpartyRecordsCard.tsx +0 -41
  46. package/src/components/form-sections/IntermediaryCard.tsx +0 -77
  47. package/src/components/form-sections/IntermediaryFI.tsx +0 -41
  48. package/src/components/form-sections/IntermediaryFIAddress.tsx +0 -14
  49. package/src/components/form-sections/OriginatorCard.tsx +0 -49
  50. package/src/components/form-sections/OriginatorFI.tsx +0 -42
  51. package/src/components/form-sections/OriginatorFIAddress.tsx +0 -14
  52. package/src/components/form-sections/PaymentInformationSection.tsx +0 -163
  53. package/src/components/form-sections/ReceiverCard.tsx +0 -94
  54. package/src/components/form-sections/WireTransferSection.tsx +0 -75
  55. package/src/components/layouts/list-page.tsx +0 -103
  56. package/src/components/transaction/ACHDetailsSection.tsx +0 -95
  57. package/src/components/transaction/WireDetailsSection.tsx +0 -112
  58. package/src/components/ui/account-card.tsx +0 -94
  59. package/src/components/ui/badge.tsx +0 -75
  60. package/src/components/ui/breadcrumb.tsx +0 -78
  61. package/src/components/ui/business-type-badge.tsx +0 -42
  62. package/src/components/ui/button.tsx +0 -56
  63. package/src/components/ui/calendar.tsx +0 -49
  64. package/src/components/ui/card.tsx +0 -223
  65. package/src/components/ui/container.tsx +0 -45
  66. package/src/components/ui/counterparty-type-badge.tsx +0 -53
  67. package/src/components/ui/data-grid.tsx +0 -99
  68. package/src/components/ui/data-table.tsx +0 -152
  69. package/src/components/ui/detail-page-layout.tsx +0 -83
  70. package/src/components/ui/dialog.tsx +0 -120
  71. package/src/components/ui/dropdown-menu.tsx +0 -82
  72. package/src/components/ui/editable-form-card.tsx +0 -106
  73. package/src/components/ui/editable-info-field.tsx +0 -67
  74. package/src/components/ui/enhanced-input.tsx +0 -78
  75. package/src/components/ui/enhanced-select.tsx +0 -101
  76. package/src/components/ui/enhanced-textarea.tsx +0 -64
  77. package/src/components/ui/entity-card.tsx +0 -140
  78. package/src/components/ui/form-card.tsx +0 -40
  79. package/src/components/ui/form-field.tsx +0 -50
  80. package/src/components/ui/form-input.tsx +0 -29
  81. package/src/components/ui/form-provider.tsx +0 -18
  82. package/src/components/ui/form-section.tsx +0 -66
  83. package/src/components/ui/form-select.tsx +0 -35
  84. package/src/components/ui/info-field.tsx +0 -36
  85. package/src/components/ui/json-viewer.tsx +0 -146
  86. package/src/components/ui/label.tsx +0 -24
  87. package/src/components/ui/metric-card.tsx +0 -80
  88. package/src/components/ui/page-layout.tsx +0 -183
  89. package/src/components/ui/popover.tsx +0 -29
  90. package/src/components/ui/responsive-grid.tsx +0 -46
  91. package/src/components/ui/separator.tsx +0 -31
  92. package/src/components/ui/sheet.tsx +0 -140
  93. package/src/components/ui/sidebar.tsx +0 -775
  94. package/src/components/ui/sonner.tsx +0 -29
  95. package/src/components/ui/stack.tsx +0 -77
  96. package/src/components/ui/status-badge.tsx +0 -68
  97. package/src/components/ui/tabs.tsx +0 -52
  98. package/src/components/ui/toast.tsx +0 -127
  99. package/src/components/ui/toaster.tsx +0 -33
  100. package/src/components/ui/tooltip.tsx +0 -28
  101. package/src/components/ui/use-toast.ts +0 -3
  102. package/src/components/ui-kit/dashboard-demo.tsx +0 -156
  103. package/src/components/ui-kit/pattern-library.tsx +0 -248
  104. package/src/components/ui-kit/showcase.tsx +0 -211
  105. package/src/hooks/use-mobile.tsx +0 -19
  106. package/src/hooks/use-toast.ts +0 -191
  107. package/src/hooks/useEditState.ts +0 -70
  108. package/src/hooks/useFormWithEditState.ts +0 -115
  109. package/src/lib/constants.ts +0 -25
  110. package/src/lib/mock-data/alert-data.ts +0 -275
  111. package/src/lib/mock-data/banking-data.ts +0 -72
  112. package/src/lib/mock-data/business-data.ts +0 -71
  113. package/src/lib/mock-data/counterparty-data.ts +0 -70
  114. package/src/lib/mock-data/index.ts +0 -5
  115. package/src/lib/mock-data/transaction-data.ts +0 -283
  116. package/src/lib/mock-data/wire-data.ts +0 -103
  117. package/src/lib/mock-data.tsx +0 -180
  118. package/src/lib/schemas/banking-schemas.ts +0 -30
  119. package/src/lib/schemas/business-schemas.ts +0 -36
  120. package/src/lib/schemas/counterparty-schemas.ts +0 -43
  121. package/src/lib/schemas/index.ts +0 -5
  122. package/src/lib/schemas/wire-schemas.ts +0 -44
  123. package/src/lib/utils.ts +0 -6
  124. package/src/main.tsx +0 -10
  125. package/src/pages/Cases.tsx +0 -16
  126. package/src/pages/Dashboard.tsx +0 -16
  127. package/src/pages/NotFound.tsx +0 -27
  128. package/src/pages/TransactionHistory.tsx +0 -532
  129. package/src/pages/UIKit.tsx +0 -51
  130. package/src/pages/alerts/AlertDetail.tsx +0 -193
  131. package/src/pages/alerts/Alerts.tsx +0 -373
  132. package/src/pages/business/Business.tsx +0 -48
  133. package/src/pages/business/Create.tsx +0 -173
  134. package/src/pages/counterparty/Create.tsx +0 -48
  135. package/src/pages/counterparty/DomesticWire.tsx +0 -78
  136. package/src/pages/counterparty/Manage.tsx +0 -79
  137. package/src/pages/transactions/NewTransaction.tsx +0 -527
  138. package/src/pages/transactions/TransactionDetail.tsx +0 -192
  139. package/src/vite-env.d.ts +0 -1
  140. package/tailwind.config.ts +0 -124
  141. package/tsconfig.app.json +0 -30
  142. package/tsconfig.json +0 -19
  143. package/tsconfig.node.json +0 -22
  144. package/vite.config.ts +0 -22
  145. /package/{src/assets/braid-logo.png → dist/braid-logo-343BOQZ2.png} +0 -0
@@ -1,44 +0,0 @@
1
- import { z } from "zod"
2
- import { addressSchema } from "./counterparty-schemas"
3
-
4
- export const wireBasicInfoSchema = z.object({
5
- counterpartyName: z.string().min(1, "Counterparty name is required"),
6
- shortName: z.string().min(1, "Short name is required"),
7
- type: z.string().min(1, "Type is required"),
8
- description: z.string().optional(),
9
- })
10
-
11
- export const beneficiarySchema = z.object({
12
- name: z.string().min(1, "Beneficiary name is required"),
13
- accountNumber: z.string().min(1, "Account number is required"),
14
- address: addressSchema,
15
- })
16
-
17
- export const originatorFISchema = z.object({
18
- accountNumber: z.string().min(1, "Account number is required"),
19
- name: z.string().min(1, "FI name is required"),
20
- idType: z.string().min(1, "ID type is required"),
21
- idNumber: z.string().min(1, "ID number is required"),
22
- address: addressSchema,
23
- })
24
-
25
- export const intermediaryFISchema = z.object({
26
- accountNumber: z.string().optional(),
27
- name: z.string().optional(),
28
- idType: z.string().optional(),
29
- idNumber: z.string().optional(),
30
- address: addressSchema.optional(),
31
- })
32
-
33
- export const wireTransferSchema = z.object({
34
- basicInfo: wireBasicInfoSchema,
35
- beneficiary: beneficiarySchema,
36
- originatorFI: originatorFISchema,
37
- intermediaryFI: intermediaryFISchema.optional(),
38
- })
39
-
40
- export type WireBasicInfo = z.infer<typeof wireBasicInfoSchema>
41
- export type Beneficiary = z.infer<typeof beneficiarySchema>
42
- export type OriginatorFI = z.infer<typeof originatorFISchema>
43
- export type IntermediaryFI = z.infer<typeof intermediaryFISchema>
44
- export type WireTransfer = z.infer<typeof wireTransferSchema>
package/src/lib/utils.ts DELETED
@@ -1,6 +0,0 @@
1
- import { clsx, type ClassValue } from "clsx"
2
- import { twMerge } from "tailwind-merge"
3
-
4
- export function cn(...inputs: ClassValue[]) {
5
- return twMerge(clsx(inputs))
6
- }
package/src/main.tsx DELETED
@@ -1,10 +0,0 @@
1
- import { StrictMode } from 'react'
2
- import { createRoot } from 'react-dom/client'
3
- import App from './App.tsx'
4
- import './index.css'
5
-
6
- createRoot(document.getElementById("root")!).render(
7
- <StrictMode>
8
- <App />
9
- </StrictMode>
10
- );
@@ -1,16 +0,0 @@
1
- import { PageLayout } from "@/components/ui/page-layout"
2
-
3
- const Cases = () => {
4
- return (
5
- <PageLayout
6
- title="Cases"
7
- description="Manage and track investigation cases"
8
- >
9
- <div className="text-center py-12 text-muted-foreground">
10
- Cases content coming soon
11
- </div>
12
- </PageLayout>
13
- )
14
- }
15
-
16
- export default Cases
@@ -1,16 +0,0 @@
1
- import { PageLayout } from "@/components/ui/page-layout"
2
-
3
- const Dashboard = () => {
4
- return (
5
- <PageLayout
6
- title="Dashboard"
7
- description="Overview of your system metrics and activity"
8
- >
9
- <div className="text-center py-12 text-muted-foreground">
10
- Dashboard content coming soon
11
- </div>
12
- </PageLayout>
13
- )
14
- }
15
-
16
- export default Dashboard
@@ -1,27 +0,0 @@
1
- import { useLocation } from "react-router-dom";
2
- import { useEffect } from "react";
3
-
4
- const NotFound = () => {
5
- const location = useLocation();
6
-
7
- useEffect(() => {
8
- console.error(
9
- "404 Error: User attempted to access non-existent route:",
10
- location.pathname
11
- );
12
- }, [location.pathname]);
13
-
14
- return (
15
- <div className="min-h-screen flex items-center justify-center bg-gray-100">
16
- <div className="text-center">
17
- <h1 className="text-4xl font-bold mb-4">404</h1>
18
- <p className="text-xl text-gray-600 mb-4">Oops! Page not found</p>
19
- <a href="/" className="text-blue-500 hover:text-blue-700 underline">
20
- Return to Home
21
- </a>
22
- </div>
23
- </div>
24
- );
25
- };
26
-
27
- export default NotFound;
@@ -1,532 +0,0 @@
1
- import { useState } from "react"
2
- import { useNavigate } from "react-router-dom"
3
- import { StatusBadge } from "@/components/ui/status-badge"
4
- import { Button } from "@/components/ui/button"
5
- import { Badge } from "@/components/ui/badge"
6
- import { ChevronLeft, ChevronRight, Filter, Calendar as CalendarIcon } from "lucide-react"
7
- import { mockTransactions, Transaction } from "@/lib/mock-data/transaction-data"
8
- import { format } from "date-fns"
9
- import {
10
- DropdownMenu,
11
- DropdownMenuContent,
12
- DropdownMenuItem,
13
- DropdownMenuTrigger,
14
- } from "@/components/ui/dropdown-menu"
15
- import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger, SheetFooter } from "@/components/ui/sheet"
16
- import { EnhancedInput } from "@/components/ui/enhanced-input"
17
- import { EnhancedSelect } from "@/components/ui/enhanced-select"
18
- import { Calendar } from "@/components/ui/calendar"
19
- import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
20
- import { cn } from "@/lib/utils"
21
-
22
- const TransactionHistory = () => {
23
- const navigate = useNavigate()
24
- const [currentPage, setCurrentPage] = useState(1)
25
- const [rowsPerPage, setRowsPerPage] = useState(100)
26
- const [filters, setFilters] = useState({
27
- accountNumber: "",
28
- product: "",
29
- customerId: "",
30
- counterpartyId: "",
31
- settlementFileName: "",
32
- originalFileName: "",
33
- requesterIpAddress: "",
34
- requesterUsername: "",
35
- wireFileHandle: "",
36
- paymentId: "",
37
- transactionType: "",
38
- transactionStatus: "",
39
- processingStatus: "",
40
- direction: "",
41
- minAmount: "",
42
- maxAmount: "",
43
- creationDateStart: undefined as Date | undefined,
44
- creationDateEnd: undefined as Date | undefined,
45
- postDateStart: undefined as Date | undefined,
46
- postDateEnd: undefined as Date | undefined
47
- })
48
-
49
- const handleFilterChange = (field: string, value: string | Date | undefined) => {
50
- setFilters(prev => ({ ...prev, [field]: value }))
51
- }
52
-
53
- const applyFilters = () => {
54
- // Apply filter logic here
55
- console.log("Applying filters:", filters)
56
- }
57
-
58
- const resetFilters = () => {
59
- setFilters({
60
- accountNumber: "",
61
- product: "",
62
- customerId: "",
63
- counterpartyId: "",
64
- settlementFileName: "",
65
- originalFileName: "",
66
- requesterIpAddress: "",
67
- requesterUsername: "",
68
- wireFileHandle: "",
69
- paymentId: "",
70
- transactionType: "",
71
- transactionStatus: "",
72
- processingStatus: "",
73
- direction: "",
74
- minAmount: "",
75
- maxAmount: "",
76
- creationDateStart: undefined,
77
- creationDateEnd: undefined,
78
- postDateStart: undefined,
79
- postDateEnd: undefined
80
- })
81
- }
82
-
83
- // Pagination calculations
84
- const totalPages = Math.ceil(mockTransactions.length / rowsPerPage)
85
- const startIndex = (currentPage - 1) * rowsPerPage
86
- const endIndex = startIndex + rowsPerPage
87
- const paginatedTransactions = mockTransactions.slice(startIndex, endIndex)
88
-
89
- const handlePageChange = (newPage: number) => {
90
- if (newPage >= 1 && newPage <= totalPages) {
91
- setCurrentPage(newPage)
92
- }
93
- }
94
-
95
- const handleRowsPerPageChange = (value: number) => {
96
- setRowsPerPage(value)
97
- setCurrentPage(1)
98
- }
99
-
100
- const formatCurrency = (value: number) => {
101
- const formatted = new Intl.NumberFormat('en-US', {
102
- style: 'currency',
103
- currency: 'USD',
104
- minimumFractionDigits: 2
105
- }).format(value)
106
- return formatted
107
- }
108
-
109
- return (
110
- <div className="flex flex-col h-screen bg-gradient-subtle">
111
- {/* Fixed Header */}
112
- <div className="flex-none border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
113
- <div className="container mx-auto px-4 py-4 max-w-none">
114
- <div className="flex items-center justify-between">
115
- <h1 className="text-3xl font-bold text-foreground">Transaction History</h1>
116
- <Sheet>
117
- <SheetTrigger asChild>
118
- <Button variant="outline" className="gap-2">
119
- <Filter className="h-4 w-4" />
120
- Filters
121
- </Button>
122
- </SheetTrigger>
123
- <SheetContent side="right" className="w-full sm:max-w-xl overflow-y-auto">
124
- <SheetHeader>
125
- <SheetTitle>Transaction Filters</SheetTitle>
126
- </SheetHeader>
127
-
128
- <div className="space-y-6 py-6">
129
- <div className="grid grid-cols-2 gap-4">
130
- <EnhancedInput
131
- label="Account Number"
132
- value={filters.accountNumber}
133
- onChange={(e) => handleFilterChange("accountNumber", e.target.value)}
134
- placeholder="Enter account number"
135
- />
136
-
137
- <EnhancedSelect
138
- label="Product"
139
- value={filters.product}
140
- onValueChange={(value) => handleFilterChange("product", value)}
141
- placeholder="Select product"
142
- options={[
143
- { value: "wire", label: "Wire" },
144
- { value: "ach", label: "ACH" },
145
- { value: "check", label: "Check" }
146
- ]}
147
- />
148
- </div>
149
-
150
- <div className="grid grid-cols-2 gap-4">
151
- <EnhancedInput
152
- label="Customer ID"
153
- value={filters.customerId}
154
- onChange={(e) => handleFilterChange("customerId", e.target.value)}
155
- placeholder="Enter customer ID"
156
- />
157
-
158
- <EnhancedInput
159
- label="Counterparty ID"
160
- value={filters.counterpartyId}
161
- onChange={(e) => handleFilterChange("counterpartyId", e.target.value)}
162
- placeholder="Enter counterparty ID"
163
- />
164
- </div>
165
-
166
- <EnhancedInput
167
- label="Settlement File Name"
168
- value={filters.settlementFileName}
169
- onChange={(e) => handleFilterChange("settlementFileName", e.target.value)}
170
- placeholder="Enter settlement file name"
171
- />
172
-
173
- <EnhancedInput
174
- label="Original File Name"
175
- value={filters.originalFileName}
176
- onChange={(e) => handleFilterChange("originalFileName", e.target.value)}
177
- placeholder="Enter original file name"
178
- />
179
-
180
- <EnhancedInput
181
- label="Requester IP Address"
182
- value={filters.requesterIpAddress}
183
- onChange={(e) => handleFilterChange("requesterIpAddress", e.target.value)}
184
- placeholder="Enter IP address"
185
- />
186
-
187
- <EnhancedInput
188
- label="Requester Username"
189
- value={filters.requesterUsername}
190
- onChange={(e) => handleFilterChange("requesterUsername", e.target.value)}
191
- placeholder="Enter username"
192
- />
193
-
194
- <EnhancedInput
195
- label="Wire File Handle"
196
- value={filters.wireFileHandle}
197
- onChange={(e) => handleFilterChange("wireFileHandle", e.target.value)}
198
- placeholder="Enter wire file handle"
199
- />
200
-
201
- <EnhancedInput
202
- label="Payment ID"
203
- value={filters.paymentId}
204
- onChange={(e) => handleFilterChange("paymentId", e.target.value)}
205
- placeholder="Enter payment ID"
206
- />
207
-
208
- <EnhancedSelect
209
- label="Transaction Type"
210
- value={filters.transactionType}
211
- onValueChange={(value) => handleFilterChange("transactionType", value)}
212
- placeholder="Select transaction type"
213
- options={[
214
- { value: "ach_credit", label: "ACH Credit" },
215
- { value: "ach_debit", label: "ACH Debit" },
216
- { value: "wire_domestic", label: "Wire Domestic" },
217
- { value: "wire_international", label: "Wire International" }
218
- ]}
219
- />
220
-
221
- <EnhancedSelect
222
- label="Transaction Status"
223
- value={filters.transactionStatus}
224
- onValueChange={(value) => handleFilterChange("transactionStatus", value)}
225
- placeholder="Select transaction status"
226
- options={[
227
- { value: "PENDING", label: "Pending" },
228
- { value: "POSTED", label: "Posted" },
229
- { value: "FAILED", label: "Failed" },
230
- { value: "CANCELLED", label: "Cancelled" }
231
- ]}
232
- />
233
-
234
- <EnhancedSelect
235
- label="Processing Status"
236
- value={filters.processingStatus}
237
- onValueChange={(value) => handleFilterChange("processingStatus", value)}
238
- placeholder="Select processing status"
239
- options={[
240
- { value: "processing", label: "Processing" },
241
- { value: "completed", label: "Completed" },
242
- { value: "error", label: "Error" }
243
- ]}
244
- />
245
-
246
- <EnhancedSelect
247
- label="Direction"
248
- value={filters.direction}
249
- onValueChange={(value) => handleFilterChange("direction", value)}
250
- placeholder="Select direction"
251
- options={[
252
- { value: "credit", label: "Credit" },
253
- { value: "debit", label: "Debit" }
254
- ]}
255
- />
256
-
257
- <div className="grid grid-cols-2 gap-4">
258
- <EnhancedInput
259
- label="Min Amount"
260
- type="number"
261
- value={filters.minAmount}
262
- onChange={(e) => handleFilterChange("minAmount", e.target.value)}
263
- placeholder="0.00"
264
- />
265
-
266
- <EnhancedInput
267
- label="Max Amount"
268
- type="number"
269
- value={filters.maxAmount}
270
- onChange={(e) => handleFilterChange("maxAmount", e.target.value)}
271
- placeholder="0.00"
272
- />
273
- </div>
274
-
275
- <div className="grid grid-cols-2 gap-4">
276
- <div className="space-y-2">
277
- <label className="text-sm font-medium">Creation Date Start</label>
278
- <Popover>
279
- <PopoverTrigger asChild>
280
- <Button
281
- variant="outline"
282
- className={cn(
283
- "w-full justify-start text-left font-normal",
284
- !filters.creationDateStart && "text-muted-foreground"
285
- )}
286
- >
287
- <CalendarIcon className="mr-2 h-4 w-4" />
288
- {filters.creationDateStart ? format(filters.creationDateStart, "MM/dd/yyyy") : <span>MM/DD/YYYY</span>}
289
- </Button>
290
- </PopoverTrigger>
291
- <PopoverContent className="w-auto p-0 bg-background z-50" align="start">
292
- <Calendar
293
- mode="single"
294
- selected={filters.creationDateStart}
295
- onSelect={(date) => handleFilterChange("creationDateStart", date)}
296
- initialFocus
297
- className="pointer-events-auto"
298
- />
299
- </PopoverContent>
300
- </Popover>
301
- </div>
302
-
303
- <div className="space-y-2">
304
- <label className="text-sm font-medium">Creation Date End</label>
305
- <Popover>
306
- <PopoverTrigger asChild>
307
- <Button
308
- variant="outline"
309
- className={cn(
310
- "w-full justify-start text-left font-normal",
311
- !filters.creationDateEnd && "text-muted-foreground"
312
- )}
313
- >
314
- <CalendarIcon className="mr-2 h-4 w-4" />
315
- {filters.creationDateEnd ? format(filters.creationDateEnd, "MM/dd/yyyy") : <span>MM/DD/YYYY</span>}
316
- </Button>
317
- </PopoverTrigger>
318
- <PopoverContent className="w-auto p-0 bg-background z-50" align="start">
319
- <Calendar
320
- mode="single"
321
- selected={filters.creationDateEnd}
322
- onSelect={(date) => handleFilterChange("creationDateEnd", date)}
323
- initialFocus
324
- className="pointer-events-auto"
325
- />
326
- </PopoverContent>
327
- </Popover>
328
- </div>
329
- </div>
330
-
331
- <div className="grid grid-cols-2 gap-4">
332
- <div className="space-y-2">
333
- <label className="text-sm font-medium">Post Date Start</label>
334
- <Popover>
335
- <PopoverTrigger asChild>
336
- <Button
337
- variant="outline"
338
- className={cn(
339
- "w-full justify-start text-left font-normal",
340
- !filters.postDateStart && "text-muted-foreground"
341
- )}
342
- >
343
- <CalendarIcon className="mr-2 h-4 w-4" />
344
- {filters.postDateStart ? format(filters.postDateStart, "MM/dd/yyyy") : <span>MM/DD/YYYY</span>}
345
- </Button>
346
- </PopoverTrigger>
347
- <PopoverContent className="w-auto p-0 bg-background z-50" align="start">
348
- <Calendar
349
- mode="single"
350
- selected={filters.postDateStart}
351
- onSelect={(date) => handleFilterChange("postDateStart", date)}
352
- initialFocus
353
- className="pointer-events-auto"
354
- />
355
- </PopoverContent>
356
- </Popover>
357
- </div>
358
-
359
- <div className="space-y-2">
360
- <label className="text-sm font-medium">Post Date End</label>
361
- <Popover>
362
- <PopoverTrigger asChild>
363
- <Button
364
- variant="outline"
365
- className={cn(
366
- "w-full justify-start text-left font-normal",
367
- !filters.postDateEnd && "text-muted-foreground"
368
- )}
369
- >
370
- <CalendarIcon className="mr-2 h-4 w-4" />
371
- {filters.postDateEnd ? format(filters.postDateEnd, "MM/dd/yyyy") : <span>MM/DD/YYYY</span>}
372
- </Button>
373
- </PopoverTrigger>
374
- <PopoverContent className="w-auto p-0 bg-background z-50" align="start">
375
- <Calendar
376
- mode="single"
377
- selected={filters.postDateEnd}
378
- onSelect={(date) => handleFilterChange("postDateEnd", date)}
379
- initialFocus
380
- className="pointer-events-auto"
381
- />
382
- </PopoverContent>
383
- </Popover>
384
- </div>
385
- </div>
386
- </div>
387
-
388
- <SheetFooter className="gap-2">
389
- <Button variant="outline" onClick={resetFilters}>
390
- Reset Filters
391
- </Button>
392
- <Button onClick={applyFilters}>
393
- Apply Filters
394
- </Button>
395
- </SheetFooter>
396
- </SheetContent>
397
- </Sheet>
398
- </div>
399
- </div>
400
- </div>
401
-
402
- {/* Scrollable Content */}
403
- <div className="flex-1 overflow-hidden">
404
- <div className="container mx-auto px-4 h-full max-w-none flex flex-col">
405
- <div className="flex-1 mt-4 rounded-lg border bg-card overflow-hidden flex flex-col">
406
- <div className="flex-1 overflow-auto">
407
- <table className="w-full table-fixed">
408
- <colgroup>
409
- <col className="w-28" />
410
- <col className="w-28" />
411
- <col className="w-24" />
412
- <col className="w-36" />
413
- <col className="w-36" />
414
- <col className="w-auto" />
415
- <col className="w-36" />
416
- <col className="w-24" />
417
- <col className="w-28" />
418
- </colgroup>
419
- <thead className="sticky top-0 bg-card z-10 shadow-sm">
420
- <tr className="border-b">
421
- <th className="px-3 py-2 text-left text-xs font-medium bg-muted/50">Created</th>
422
- <th className="px-3 py-2 text-left text-xs font-medium bg-muted/50">Account Number</th>
423
- <th className="px-3 py-2 text-right text-xs font-medium bg-muted/50">Amount</th>
424
- <th className="px-3 py-2 text-left text-xs font-medium bg-muted/50">Customer</th>
425
- <th className="px-3 py-2 text-left text-xs font-medium bg-muted/50">Counterparty</th>
426
- <th className="px-3 py-2 text-left text-xs font-medium bg-muted/50">Description</th>
427
- <th className="px-3 py-2 text-left text-xs font-medium bg-muted/50">Transaction Type</th>
428
- <th className="px-3 py-2 text-left text-xs font-medium bg-muted/50">Status</th>
429
- <th className="px-3 py-2 text-left text-xs font-medium bg-muted/50">Updated</th>
430
- </tr>
431
- </thead>
432
- <tbody>
433
- {paginatedTransactions.map((transaction) => (
434
- <tr
435
- key={transaction.id}
436
- onClick={() => navigate(`/transactions/${transaction.id}`)}
437
- className="border-b hover:bg-muted/50 transition-colors cursor-pointer"
438
- >
439
- <td className="px-3 py-2 text-xs">{transaction.created}</td>
440
- <td className="px-3 py-2 text-xs">{transaction.accountNumber}</td>
441
- <td className="px-3 py-2 text-xs text-right">
442
- <span className={transaction.amount < 0 ? "text-destructive" : ""}>
443
- {formatCurrency(transaction.amount)}
444
- </span>
445
- </td>
446
- <td className="px-3 py-2">
447
- <Button variant="link" className="h-auto p-0 font-normal text-xs">
448
- {transaction.customer}
449
- </Button>
450
- </td>
451
- <td className="px-3 py-2">
452
- <Button variant="link" className="h-auto p-0 font-normal text-xs">
453
- {transaction.counterparty}
454
- </Button>
455
- </td>
456
- <td className="px-3 py-2 text-xs truncate">{transaction.description}</td>
457
- <td className="px-3 py-2">
458
- <Badge variant="outline" className="font-normal whitespace-nowrap text-xs">
459
- {transaction.transactionType}
460
- </Badge>
461
- </td>
462
- <td className="px-3 py-2">
463
- <StatusBadge status={transaction.status} />
464
- </td>
465
- <td className="px-3 py-2 text-xs">{transaction.updated}</td>
466
- </tr>
467
- ))}
468
- </tbody>
469
- </table>
470
- </div>
471
-
472
- {/* Pagination Footer */}
473
- <div className="flex-none border-t bg-background py-3 px-4">
474
- <div className="flex items-center justify-between">
475
- <div className="flex items-center gap-2">
476
- <span className="text-sm text-muted-foreground">Rows per page:</span>
477
- <DropdownMenu>
478
- <DropdownMenuTrigger asChild>
479
- <Button variant="outline" size="sm" className="h-8 gap-1">
480
- {rowsPerPage}
481
- <ChevronRight className="h-4 w-4 rotate-90" />
482
- </Button>
483
- </DropdownMenuTrigger>
484
- <DropdownMenuContent align="start" className="bg-background z-50">
485
- <DropdownMenuItem onClick={() => handleRowsPerPageChange(100)}>
486
- 100
487
- </DropdownMenuItem>
488
- <DropdownMenuItem onClick={() => handleRowsPerPageChange(200)}>
489
- 200
490
- </DropdownMenuItem>
491
- <DropdownMenuItem onClick={() => handleRowsPerPageChange(500)}>
492
- 500
493
- </DropdownMenuItem>
494
- </DropdownMenuContent>
495
- </DropdownMenu>
496
- </div>
497
-
498
- <div className="flex items-center gap-4">
499
- <span className="text-sm text-muted-foreground">
500
- Page {currentPage} of {totalPages}
501
- </span>
502
- <div className="flex items-center gap-1">
503
- <Button
504
- variant="outline"
505
- size="sm"
506
- className="h-8 w-8 p-0"
507
- onClick={() => handlePageChange(currentPage - 1)}
508
- disabled={currentPage === 1}
509
- >
510
- <ChevronLeft className="h-4 w-4" />
511
- </Button>
512
- <Button
513
- variant="outline"
514
- size="sm"
515
- className="h-8 w-8 p-0"
516
- onClick={() => handlePageChange(currentPage + 1)}
517
- disabled={currentPage === totalPages}
518
- >
519
- <ChevronRight className="h-4 w-4" />
520
- </Button>
521
- </div>
522
- </div>
523
- </div>
524
- </div>
525
- </div>
526
- </div>
527
- </div>
528
- </div>
529
- )
530
- }
531
-
532
- export default TransactionHistory