@trustless-work/blocks 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.
Files changed (74) hide show
  1. package/README.md +96 -0
  2. package/bin/index.js +1123 -0
  3. package/package.json +44 -0
  4. package/templates/deps.json +29 -0
  5. package/templates/escrows/details/Actions.tsx +149 -0
  6. package/templates/escrows/details/Entities.tsx +48 -0
  7. package/templates/escrows/details/EntityCard.tsx +98 -0
  8. package/templates/escrows/details/EscrowDetailDialog.tsx +154 -0
  9. package/templates/escrows/details/GeneralInformation.tsx +329 -0
  10. package/templates/escrows/details/MilestoneCard.tsx +254 -0
  11. package/templates/escrows/details/MilestoneDetailDialog.tsx +276 -0
  12. package/templates/escrows/details/Milestones.tsx +87 -0
  13. package/templates/escrows/details/ProgressEscrow.tsx +191 -0
  14. package/templates/escrows/details/StatisticsCard.tsx +79 -0
  15. package/templates/escrows/details/SuccessReleaseDialog.tsx +101 -0
  16. package/templates/escrows/details/useDetailsEscrow.ts +126 -0
  17. package/templates/escrows/escrow-context/EscrowAmountProvider.tsx +86 -0
  18. package/templates/escrows/escrow-context/EscrowDialogsProvider.tsx +108 -0
  19. package/templates/escrows/escrow-context/EscrowProvider.tsx +124 -0
  20. package/templates/escrows/escrows-by-role/cards/EscrowsCards.tsx +503 -0
  21. package/templates/escrows/escrows-by-role/cards/Filters.tsx +421 -0
  22. package/templates/escrows/escrows-by-role/table/EscrowsTable.tsx +427 -0
  23. package/templates/escrows/escrows-by-role/table/Filters.tsx +421 -0
  24. package/templates/escrows/escrows-by-role/useEscrowsByRole.shared.ts +336 -0
  25. package/templates/escrows/escrows-by-signer/cards/EscrowsCards.tsx +502 -0
  26. package/templates/escrows/escrows-by-signer/cards/Filters.tsx +389 -0
  27. package/templates/escrows/escrows-by-signer/table/EscrowsTable.tsx +422 -0
  28. package/templates/escrows/escrows-by-signer/table/Filters.tsx +389 -0
  29. package/templates/escrows/escrows-by-signer/useEscrowsBySigner.shared.ts +320 -0
  30. package/templates/escrows/single-release/approve-milestone/button/ApproveMilestone.tsx +78 -0
  31. package/templates/escrows/single-release/approve-milestone/dialog/ApproveMilestone.tsx +102 -0
  32. package/templates/escrows/single-release/approve-milestone/form/ApproveMilestone.tsx +80 -0
  33. package/templates/escrows/single-release/approve-milestone/shared/schema.ts +9 -0
  34. package/templates/escrows/single-release/approve-milestone/shared/useApproveMilestone.ts +67 -0
  35. package/templates/escrows/single-release/change-milestone-status/button/ChangeMilestoneStatus.tsx +78 -0
  36. package/templates/escrows/single-release/change-milestone-status/dialog/ChangeMilestoneStatus.tsx +167 -0
  37. package/templates/escrows/single-release/change-milestone-status/form/ChangeMilestoneStatus.tsx +114 -0
  38. package/templates/escrows/single-release/change-milestone-status/shared/schema.ts +15 -0
  39. package/templates/escrows/single-release/change-milestone-status/shared/useChangeMilestoneStatus.ts +77 -0
  40. package/templates/escrows/single-release/dispute-escrow/button/DisputeEscrow.tsx +68 -0
  41. package/templates/escrows/single-release/fund-escrow/button/FundEscrow.tsx +84 -0
  42. package/templates/escrows/single-release/fund-escrow/dialog/FundEscrow.tsx +77 -0
  43. package/templates/escrows/single-release/fund-escrow/form/FundEscrow.tsx +54 -0
  44. package/templates/escrows/single-release/fund-escrow/shared/schema.ts +10 -0
  45. package/templates/escrows/single-release/fund-escrow/shared/useFundEscrow.ts +66 -0
  46. package/templates/escrows/single-release/initialize-escrow/dialog/InitializeEscrow.tsx +526 -0
  47. package/templates/escrows/single-release/initialize-escrow/form/InitializeEscrow.tsx +504 -0
  48. package/templates/escrows/single-release/initialize-escrow/shared/schema.ts +232 -0
  49. package/templates/escrows/single-release/initialize-escrow/shared/useInitializeEscrow.ts +115 -0
  50. package/templates/escrows/single-release/release-escrow/button/ReleaseEscrow.tsx +80 -0
  51. package/templates/escrows/single-release/resolve-dispute/button/ResolveDispute.tsx +94 -0
  52. package/templates/escrows/single-release/resolve-dispute/dialog/ResolveDispute.tsx +123 -0
  53. package/templates/escrows/single-release/resolve-dispute/form/ResolveDispute.tsx +82 -0
  54. package/templates/escrows/single-release/resolve-dispute/shared/schema.ts +82 -0
  55. package/templates/escrows/single-release/resolve-dispute/shared/useResolveDispute.ts +58 -0
  56. package/templates/escrows/single-release/update-escrow/dialog/UpdateEscrow.tsx +485 -0
  57. package/templates/escrows/single-release/update-escrow/form/UpdateEscrow.tsx +463 -0
  58. package/templates/escrows/single-release/update-escrow/shared/schema.ts +139 -0
  59. package/templates/escrows/single-release/update-escrow/shared/useUpdateEscrow.ts +211 -0
  60. package/templates/handle-errors/errors.enum.ts +6 -0
  61. package/templates/handle-errors/handle.ts +47 -0
  62. package/templates/helpers/format.helper.ts +27 -0
  63. package/templates/helpers/useCopy.ts +13 -0
  64. package/templates/providers/ReactQueryClientProvider.tsx +28 -0
  65. package/templates/providers/TrustlessWork.tsx +30 -0
  66. package/templates/tanstak/useEscrowsByRoleQuery.ts +87 -0
  67. package/templates/tanstak/useEscrowsBySignerQuery.ts +78 -0
  68. package/templates/tanstak/useEscrowsMutations.ts +411 -0
  69. package/templates/wallet-kit/WalletButtons.tsx +116 -0
  70. package/templates/wallet-kit/WalletProvider.tsx +94 -0
  71. package/templates/wallet-kit/trustlines.ts +40 -0
  72. package/templates/wallet-kit/useWallet.ts +77 -0
  73. package/templates/wallet-kit/validators.ts +12 -0
  74. package/templates/wallet-kit/wallet-kit.ts +30 -0
@@ -0,0 +1,389 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { Button } from "__UI_BASE__/button";
5
+ import { Input } from "__UI_BASE__/input";
6
+ import { Checkbox } from "__UI_BASE__/checkbox";
7
+ import {
8
+ Select,
9
+ SelectContent,
10
+ SelectItem,
11
+ SelectTrigger,
12
+ SelectValue,
13
+ } from "__UI_BASE__/select";
14
+ import { Popover, PopoverContent, PopoverTrigger } from "__UI_BASE__/popover";
15
+ import { Calendar } from "__UI_BASE__/calendar";
16
+ import type { DateRange as DayPickerDateRange } from "react-day-picker";
17
+ import {
18
+ RefreshCcw,
19
+ Trash2,
20
+ Search,
21
+ DollarSign,
22
+ Filter as FilterIcon,
23
+ Calendar as CalendarIcon,
24
+ SlidersHorizontal,
25
+ } from "lucide-react";
26
+ import {
27
+ Select as OrderSelect,
28
+ SelectTrigger as OrderSelectTrigger,
29
+ SelectContent as OrderSelectContent,
30
+ SelectItem as OrderSelectItem,
31
+ SelectValue as OrderSelectValue,
32
+ } from "@/components/ui/select";
33
+
34
+ type FiltersProps = {
35
+ // values
36
+ title: string;
37
+ engagementId: string;
38
+ isActive: boolean;
39
+ validateOnChain: boolean;
40
+ type: "single-release" | "multi-release" | "all";
41
+ status:
42
+ | "working"
43
+ | "pendingRelease"
44
+ | "released"
45
+ | "resolved"
46
+ | "inDispute"
47
+ | "all";
48
+ minAmount: string;
49
+ maxAmount: string;
50
+ dateRange: DayPickerDateRange;
51
+ formattedRangeLabel: string;
52
+
53
+ // setters
54
+ setTitle: (v: string) => void;
55
+ setEngagementId: (v: string) => void;
56
+ setIsActive: (v: boolean) => void;
57
+ setValidateOnChain: (v: boolean) => void;
58
+ setType: (v: "single-release" | "multi-release" | "all") => void;
59
+ setStatus: (
60
+ v:
61
+ | "working"
62
+ | "pendingRelease"
63
+ | "released"
64
+ | "resolved"
65
+ | "inDispute"
66
+ | "all"
67
+ ) => void;
68
+ setMinAmount: (v: string) => void;
69
+ setMaxAmount: (v: string) => void;
70
+ setDateRange: (r: DayPickerDateRange) => void;
71
+
72
+ // actions
73
+ onClearFilters: () => void;
74
+ onRefresh: () => void;
75
+ isRefreshing: boolean;
76
+
77
+ // ordering
78
+ orderBy: "createdAt" | "updatedAt" | "amount";
79
+ orderDirection: "asc" | "desc";
80
+ setOrderBy: (v: "createdAt" | "updatedAt" | "amount") => void;
81
+ setOrderDirection: (v: "asc" | "desc") => void;
82
+ };
83
+
84
+ function Filters({
85
+ title,
86
+ engagementId,
87
+ isActive,
88
+ validateOnChain,
89
+ type,
90
+ status,
91
+ minAmount,
92
+ maxAmount,
93
+ dateRange,
94
+ formattedRangeLabel,
95
+ isRefreshing,
96
+ orderBy,
97
+ orderDirection,
98
+ setTitle,
99
+ setEngagementId,
100
+ setIsActive,
101
+ setValidateOnChain,
102
+ setType,
103
+ setStatus,
104
+ setMinAmount,
105
+ setMaxAmount,
106
+ setDateRange,
107
+ onClearFilters,
108
+ onRefresh,
109
+ setOrderBy,
110
+ setOrderDirection,
111
+ }: FiltersProps) {
112
+ return (
113
+ <div className="w-full bg-card/50 backdrop-blur-sm border border-border/50 rounded-lg p-4 shadow-sm">
114
+ {/* Header Section */}
115
+ <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-3 mb-4">
116
+ <div className="flex items-center gap-2">
117
+ <SlidersHorizontal className="w-4 h-4 text-primary" />
118
+ <h3 className="font-semibold text-foreground">Filters</h3>
119
+ </div>
120
+
121
+ <div className="flex items-center gap-2">
122
+ <Button
123
+ variant="outline"
124
+ size="sm"
125
+ className="h-8 px-3 text-xs font-medium border-border/60 bg-background/80 hover:bg-muted/80 transition-colors cursor-pointer"
126
+ onClick={onRefresh}
127
+ disabled={isRefreshing}
128
+ >
129
+ <RefreshCcw
130
+ className={`w-3 h-3 ${isRefreshing ? "animate-spin" : ""}`}
131
+ />
132
+ <span className="hidden xs:inline">Refresh</span>
133
+ </Button>
134
+
135
+ <Button
136
+ variant="ghost"
137
+ size="sm"
138
+ className="h-8 px-3 text-xs font-medium text-destructive hover:text-destructive hover:bg-destructive/10 transition-colors cursor-pointer"
139
+ onClick={onClearFilters}
140
+ >
141
+ <Trash2 className="w-3 h-3" />
142
+ <span className="hidden xs:inline">Clear</span>
143
+ </Button>
144
+ </div>
145
+ </div>
146
+
147
+ {/* Filters Grid */}
148
+ <div className="space-y-4">
149
+ {/* Row 1: Search, ID, Amount Range, and Type */}
150
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-3">
151
+ <div className="space-y-1.5">
152
+ <label className="text-xs font-medium text-muted-foreground">
153
+ Search
154
+ </label>
155
+ <div className="relative">
156
+ <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-muted-foreground" />
157
+ <Input
158
+ placeholder="Search title..."
159
+ value={title}
160
+ onChange={(e) => setTitle(e.target.value)}
161
+ className="h-9 pl-9 text-sm border-border/60 focus:border-primary/60 bg-background/80 transition-colors w-full"
162
+ />
163
+ </div>
164
+ </div>
165
+
166
+ <div className="space-y-1.5">
167
+ <label className="text-xs font-medium text-muted-foreground">
168
+ Engagement ID
169
+ </label>
170
+ <div className="relative">
171
+ <FilterIcon className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-muted-foreground" />
172
+ <Input
173
+ placeholder="Engagement ID"
174
+ value={engagementId}
175
+ onChange={(e) => setEngagementId(e.target.value)}
176
+ className="h-9 pl-9 text-sm border-border/60 focus:border-primary/60 bg-background/80 transition-colors w-full"
177
+ />
178
+ </div>
179
+ </div>
180
+
181
+ <div className="space-y-1.5">
182
+ <label className="text-xs font-medium text-muted-foreground">
183
+ Amount Range
184
+ </label>
185
+ <div className="w-full">
186
+ <div className="flex items-center gap-2 w-full">
187
+ <div className="relative flex-1">
188
+ <DollarSign className="absolute left-2 top-1/2 transform -translate-y-1/2 w-3 h-3 text-muted-foreground" />
189
+ <Input
190
+ placeholder="Min"
191
+ type="number"
192
+ min="0"
193
+ value={minAmount}
194
+ onChange={(e) => setMinAmount(e.target.value)}
195
+ className="h-9 pl-7 text-sm border-border/60 focus:border-primary/60 bg-background/80 w-full"
196
+ />
197
+ </div>
198
+ <span className="text-xs text-muted-foreground px-1">-</span>
199
+ <div className="relative flex-1">
200
+ <DollarSign className="absolute left-2 top-1/2 transform -translate-y-1/2 w-3 h-3 text-muted-foreground" />
201
+ <Input
202
+ placeholder="Max"
203
+ type="number"
204
+ min="0"
205
+ value={maxAmount}
206
+ onChange={(e) => setMaxAmount(e.target.value)}
207
+ className="h-9 pl-7 text-sm border-border/60 focus:border-primary/60 bg-background/80 w-full"
208
+ />
209
+ </div>
210
+ </div>
211
+ </div>
212
+ </div>
213
+
214
+ <div className="space-y-1.5">
215
+ <label className="text-xs font-medium text-muted-foreground">
216
+ Type
217
+ </label>
218
+ <div className="w-full">
219
+ <Select
220
+ value={type}
221
+ onValueChange={(v) => setType(v as typeof type)}
222
+ >
223
+ <SelectTrigger className="h-9 text-sm border-border/60 bg-background/80 w-full">
224
+ <SelectValue placeholder="Select type" />
225
+ </SelectTrigger>
226
+ <SelectContent>
227
+ <SelectItem value="all">All types</SelectItem>
228
+ <SelectItem value="single-release">Single release</SelectItem>
229
+ <SelectItem value="multi-release">Multi release</SelectItem>
230
+ </SelectContent>
231
+ </Select>
232
+ </div>
233
+ </div>
234
+ </div>
235
+
236
+ {/* Row 2: Status, Date Range, Active Checkbox, and Ordering */}
237
+ <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-3 items-end">
238
+ <div className="space-y-1.5">
239
+ <label className="text-xs font-medium text-muted-foreground">
240
+ Status
241
+ </label>
242
+ <div className="w-full">
243
+ <Select
244
+ value={status}
245
+ onValueChange={(v) => setStatus(v as typeof status)}
246
+ >
247
+ <SelectTrigger className="h-9 text-sm border-border/60 bg-background/80 w-full">
248
+ <SelectValue placeholder="Select status" />
249
+ </SelectTrigger>
250
+ <SelectContent>
251
+ <SelectItem value="all">All statuses</SelectItem>
252
+ <SelectItem value="working">Working</SelectItem>
253
+ <SelectItem value="pendingRelease">
254
+ Pending release
255
+ </SelectItem>
256
+ <SelectItem value="released">Released</SelectItem>
257
+ <SelectItem value="resolved">Resolved</SelectItem>
258
+ <SelectItem value="inDispute">In dispute</SelectItem>
259
+ </SelectContent>
260
+ </Select>
261
+ </div>
262
+ </div>
263
+
264
+ <div className="space-y-1.5">
265
+ <label className="text-xs font-medium text-muted-foreground">
266
+ Date Range
267
+ </label>
268
+ <div className="w-full">
269
+ <Popover>
270
+ <PopoverTrigger asChild>
271
+ <Button
272
+ variant="outline"
273
+ size="sm"
274
+ className="h-9 text-sm border-border/60 bg-background/80 hover:bg-muted/80 w-full justify-start transition-colors"
275
+ >
276
+ <CalendarIcon className="w-4 h-4 mr-2 flex-shrink-0" />
277
+ <span className="truncate">{formattedRangeLabel}</span>
278
+ </Button>
279
+ </PopoverTrigger>
280
+ <PopoverContent className="w-auto p-0" align="start">
281
+ <div className="p-3">
282
+ <Calendar
283
+ mode="range"
284
+ selected={dateRange}
285
+ onSelect={(range: DayPickerDateRange | undefined) =>
286
+ setDateRange(
287
+ range ?? { from: undefined, to: undefined }
288
+ )
289
+ }
290
+ numberOfMonths={2}
291
+ />
292
+ <div className="mt-3 flex justify-end">
293
+ <Button
294
+ variant="ghost"
295
+ size="sm"
296
+ onClick={() =>
297
+ setDateRange({ from: undefined, to: undefined })
298
+ }
299
+ >
300
+ Clear
301
+ </Button>
302
+ </div>
303
+ </div>
304
+ </PopoverContent>
305
+ </Popover>
306
+ </div>
307
+ </div>
308
+
309
+ <div className="space-y-1.5">
310
+ <label className="text-xs font-medium text-muted-foreground">
311
+ Active / OnChain
312
+ </label>
313
+ <div className="w-full lg:w-auto lg:min-w-fit">
314
+ <div className="grid grid-cols-2 gap-2 w-full lg:w-auto">
315
+ <div className="flex items-center justify-center lg:justify-start gap-2 h-9 px-3 rounded-md border border-border/60 bg-background/80 w-full lg:w-auto">
316
+ <Checkbox
317
+ checked={Boolean(isActive)}
318
+ onCheckedChange={(checked) => setIsActive(Boolean(checked))}
319
+ />
320
+ <span className="text-sm text-foreground font-medium whitespace-nowrap">
321
+ Active
322
+ </span>
323
+ </div>
324
+ <div className="flex items-center justify-center lg:justify-start gap-2 h-9 px-3 rounded-md border border-border/60 bg-background/80 w-full lg:w-auto">
325
+ <Checkbox
326
+ checked={Boolean(validateOnChain)}
327
+ onCheckedChange={(checked) =>
328
+ setValidateOnChain(Boolean(checked))
329
+ }
330
+ />
331
+ <span className="text-sm text-foreground font-medium whitespace-nowrap">
332
+ OnChain
333
+ </span>
334
+ </div>
335
+ </div>
336
+ </div>
337
+ </div>
338
+
339
+ <div className="space-y-1.5 w-full lg:col-span-2">
340
+ <label className="text-xs font-medium text-muted-foreground">
341
+ Sort By
342
+ </label>
343
+ <div className="w-full">
344
+ <div className="flex items-center gap-2 w-full">
345
+ <div className="flex-1">
346
+ <OrderSelect
347
+ value={orderBy}
348
+ onValueChange={(v) => setOrderBy(v as typeof orderBy)}
349
+ >
350
+ <OrderSelectTrigger className="h-9 text-sm border-border/60 bg-background/80 w-full">
351
+ <OrderSelectValue placeholder="Order by" />
352
+ </OrderSelectTrigger>
353
+ <OrderSelectContent>
354
+ <OrderSelectItem value="createdAt">
355
+ Created
356
+ </OrderSelectItem>
357
+ <OrderSelectItem value="updatedAt">
358
+ Updated
359
+ </OrderSelectItem>
360
+ <OrderSelectItem value="amount">Amount</OrderSelectItem>
361
+ </OrderSelectContent>
362
+ </OrderSelect>
363
+ </div>
364
+ <div className="flex-1">
365
+ <OrderSelect
366
+ value={orderDirection}
367
+ onValueChange={(v) =>
368
+ setOrderDirection(v as typeof orderDirection)
369
+ }
370
+ >
371
+ <OrderSelectTrigger className="h-9 text-sm border-border/60 bg-background/80 w-full">
372
+ <OrderSelectValue placeholder="Direction" />
373
+ </OrderSelectTrigger>
374
+ <OrderSelectContent>
375
+ <OrderSelectItem value="desc">Descending</OrderSelectItem>
376
+ <OrderSelectItem value="asc">Ascending</OrderSelectItem>
377
+ </OrderSelectContent>
378
+ </OrderSelect>
379
+ </div>
380
+ </div>
381
+ </div>
382
+ </div>
383
+ </div>
384
+ </div>
385
+ </div>
386
+ );
387
+ }
388
+
389
+ export default React.memo(Filters);