@trustless-work/blocks 1.0.6 → 1.0.7
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/bin/index.js +1930 -1921
- package/package.json +1 -1
- package/templates/deps.json +1 -1
- package/templates/escrows/details/Actions.tsx +1 -2
- package/templates/escrows/details/Entities.tsx +23 -2
- package/templates/escrows/details/GeneralInformation.tsx +1 -13
- package/templates/escrows/details/MilestoneCard.tsx +1 -1
- package/templates/escrows/details/MilestoneDetailDialog.tsx +38 -19
- package/templates/escrows/details/SuccessReleaseDialog.tsx +84 -28
- package/templates/escrows/details/useDetailsEscrow.ts +15 -2
- package/templates/escrows/multi-release/initialize-escrow/dialog/InitializeEscrow.tsx +76 -101
- package/templates/escrows/multi-release/initialize-escrow/form/InitializeEscrow.tsx +78 -102
- package/templates/escrows/multi-release/initialize-escrow/shared/schema.ts +8 -18
- package/templates/escrows/multi-release/initialize-escrow/shared/useInitializeEscrow.ts +21 -12
- package/templates/escrows/multi-release/release-milestone/button/ReleaseMilestone.tsx +5 -1
- package/templates/escrows/multi-release/update-escrow/dialog/UpdateEscrow.tsx +112 -101
- package/templates/escrows/multi-release/update-escrow/form/UpdateEscrow.tsx +103 -101
- package/templates/escrows/multi-release/update-escrow/shared/schema.ts +8 -16
- package/templates/escrows/multi-release/update-escrow/shared/useUpdateEscrow.ts +33 -14
- package/templates/escrows/multi-release/withdraw-remaining-funds/button/WithdrawRemainingFunds.tsx +0 -1
- package/templates/escrows/multi-release/withdraw-remaining-funds/shared/useWithdrawRemainingFunds.ts +0 -1
- package/templates/escrows/single-release/initialize-escrow/dialog/InitializeEscrow.tsx +2 -25
- package/templates/escrows/single-release/initialize-escrow/form/InitializeEscrow.tsx +3 -26
- package/templates/escrows/single-release/initialize-escrow/shared/schema.ts +0 -10
- package/templates/escrows/single-release/initialize-escrow/shared/useInitializeEscrow.ts +0 -4
- package/templates/escrows/single-release/release-escrow/button/ReleaseEscrow.tsx +5 -1
- package/templates/escrows/single-release/update-escrow/dialog/UpdateEscrow.tsx +41 -27
- package/templates/escrows/single-release/update-escrow/form/UpdateEscrow.tsx +38 -3
- package/templates/escrows/single-release/update-escrow/shared/useUpdateEscrow.ts +28 -14
- package/templates/providers/EscrowAmountProvider.tsx +8 -0
- package/templates/tanstack/useEscrowsMutations.ts +1 -6
- package/templates/wallet-kit/WalletButtons.tsx +2 -2
- package/templates/wallet-kit/WalletProvider.tsx +0 -1
package/package.json
CHANGED
package/templates/deps.json
CHANGED
|
@@ -91,8 +91,7 @@ export const Actions = ({
|
|
|
91
91
|
userRolesInEscrow.includes("platformAddress") &&
|
|
92
92
|
!selectedEscrow?.flags?.disputed &&
|
|
93
93
|
!selectedEscrow?.flags?.resolved &&
|
|
94
|
-
!selectedEscrow?.flags?.released
|
|
95
|
-
selectedEscrow?.balance === 0;
|
|
94
|
+
!selectedEscrow?.flags?.released;
|
|
96
95
|
|
|
97
96
|
const shouldShowDisputeButton =
|
|
98
97
|
selectedEscrow.type === "single-release" &&
|
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
GetEscrowsFromIndexerResponse as Escrow,
|
|
5
|
+
MultiReleaseMilestone,
|
|
6
|
+
} from "@trustless-work/escrow/types";
|
|
4
7
|
import { EntityCard } from "./EntityCard";
|
|
8
|
+
import { Separator } from "__UI_BASE__/separator";
|
|
5
9
|
|
|
6
10
|
interface EntitiesProps {
|
|
7
11
|
selectedEscrow: Escrow;
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
export const Entities = ({ selectedEscrow }: EntitiesProps) => {
|
|
15
|
+
const receivers =
|
|
16
|
+
selectedEscrow.type === "single-release"
|
|
17
|
+
? (selectedEscrow.roles as { receiver?: string })?.receiver
|
|
18
|
+
? [(selectedEscrow.roles as { receiver?: string }).receiver as string]
|
|
19
|
+
: []
|
|
20
|
+
: (selectedEscrow.milestones || [])
|
|
21
|
+
.map((m) => (m as MultiReleaseMilestone | undefined)?.receiver)
|
|
22
|
+
.filter((r): r is string => Boolean(r));
|
|
23
|
+
|
|
11
24
|
return (
|
|
12
25
|
<>
|
|
13
26
|
<div className="flex justify-between items-center mb-6">
|
|
@@ -41,7 +54,15 @@ export const Entities = ({ selectedEscrow }: EntitiesProps) => {
|
|
|
41
54
|
type="releaseSigner"
|
|
42
55
|
entity={selectedEscrow.roles?.releaseSigner}
|
|
43
56
|
/>
|
|
44
|
-
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<Separator className="my-4" />
|
|
60
|
+
|
|
61
|
+
<h2 className="text-lg font-semibold">Receivers</h2>
|
|
62
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-4">
|
|
63
|
+
{receivers.map((r, idx) => (
|
|
64
|
+
<EntityCard key={`receiver-${idx}-${r}`} type="receiver" entity={r} />
|
|
65
|
+
))}
|
|
45
66
|
</div>
|
|
46
67
|
</>
|
|
47
68
|
);
|
|
@@ -159,7 +159,7 @@ export const GeneralInformation = ({
|
|
|
159
159
|
</div>
|
|
160
160
|
</div>
|
|
161
161
|
|
|
162
|
-
<div className="grid grid-cols-1
|
|
162
|
+
<div className="grid grid-cols-1 gap-4">
|
|
163
163
|
<div className="p-4 bg-muted/50 rounded-lg border">
|
|
164
164
|
<div className="flex items-center gap-3 mb-3">
|
|
165
165
|
<Users className="h-5 w-5 text-primary flex-shrink-0" />
|
|
@@ -185,18 +185,6 @@ export const GeneralInformation = ({
|
|
|
185
185
|
})}
|
|
186
186
|
</div>
|
|
187
187
|
</div>
|
|
188
|
-
|
|
189
|
-
<div className="p-4 bg-muted/50 rounded-lg border">
|
|
190
|
-
<div className="flex items-center gap-3 mb-2">
|
|
191
|
-
<Info className="h-5 w-5 text-primary flex-shrink-0" />
|
|
192
|
-
<span className="text-sm font-medium text-muted-foreground">
|
|
193
|
-
Memo
|
|
194
|
-
</span>
|
|
195
|
-
</div>
|
|
196
|
-
<span className="font-medium text-foreground">
|
|
197
|
-
{selectedEscrow?.receiverMemo || "No Memo"}
|
|
198
|
-
</span>
|
|
199
|
-
</div>
|
|
200
188
|
</div>
|
|
201
189
|
|
|
202
190
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
@@ -221,7 +221,7 @@ const MilestoneCardComponent = ({
|
|
|
221
221
|
<Button
|
|
222
222
|
size="sm"
|
|
223
223
|
variant="outline"
|
|
224
|
-
className="w-full border-border text-muted-foreground"
|
|
224
|
+
className="w-full border-border text-muted-foreground cursor-pointer"
|
|
225
225
|
onClick={(e) => {
|
|
226
226
|
e.stopPropagation();
|
|
227
227
|
onViewDetails(milestone, milestoneIndex);
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
import { Card, CardContent, CardHeader, CardTitle } from "__UI_BASE__/card";
|
|
11
11
|
import { Badge } from "__UI_BASE__/badge";
|
|
12
12
|
import {
|
|
13
|
-
DollarSign,
|
|
14
13
|
FileCheck2,
|
|
15
14
|
User,
|
|
16
15
|
Calendar,
|
|
@@ -28,6 +27,9 @@ import {
|
|
|
28
27
|
SingleReleaseMilestone,
|
|
29
28
|
} from "@trustless-work/escrow";
|
|
30
29
|
import Link from "next/link";
|
|
30
|
+
import { formatCurrency } from "@/components/tw-blocks/helpers/format.helper";
|
|
31
|
+
import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
|
|
32
|
+
import { EntityCard } from "./EntityCard";
|
|
31
33
|
|
|
32
34
|
interface MilestoneDetailDialogProps {
|
|
33
35
|
isOpen: boolean;
|
|
@@ -49,6 +51,8 @@ export const MilestoneDetailDialog = ({
|
|
|
49
51
|
onClose,
|
|
50
52
|
selectedMilestone,
|
|
51
53
|
}: MilestoneDetailDialogProps) => {
|
|
54
|
+
const { selectedEscrow } = useEscrowContext();
|
|
55
|
+
|
|
52
56
|
const getMilestoneStatusBadge = (
|
|
53
57
|
milestone: SingleReleaseMilestone | MultiReleaseMilestone
|
|
54
58
|
) => {
|
|
@@ -115,11 +119,15 @@ export const MilestoneDetailDialog = ({
|
|
|
115
119
|
}
|
|
116
120
|
};
|
|
117
121
|
|
|
122
|
+
const currentReceiver =
|
|
123
|
+
selectedEscrow?.type === "multi-release" &&
|
|
124
|
+
((selectedMilestone?.milestone as MultiReleaseMilestone)?.receiver ?? "");
|
|
125
|
+
|
|
118
126
|
if (!selectedMilestone) return null;
|
|
119
127
|
|
|
120
128
|
return (
|
|
121
129
|
<Dialog open={isOpen} onOpenChange={onClose}>
|
|
122
|
-
<DialogContent className="max-w-
|
|
130
|
+
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto">
|
|
123
131
|
<DialogHeader className="pb-4 border-b border-border">
|
|
124
132
|
<div className="flex items-center gap-3">
|
|
125
133
|
<div className="flex items-center justify-center w-10 h-10 bg-primary/10 rounded-full">
|
|
@@ -154,6 +162,28 @@ export const MilestoneDetailDialog = ({
|
|
|
154
162
|
{getMilestoneStatusBadge(selectedMilestone.milestone)}
|
|
155
163
|
</div>
|
|
156
164
|
|
|
165
|
+
{"amount" in selectedMilestone.milestone && (
|
|
166
|
+
<div className="flex items-center justify-between p-4 rounded-lg border border-border">
|
|
167
|
+
<div className="flex items-center gap-3">
|
|
168
|
+
<div className="flex items-center justify-center w-8 h-8 bg-background rounded-full shadow-sm border border-border">
|
|
169
|
+
<Calendar className="w-4 h-4 text-primary" />
|
|
170
|
+
</div>
|
|
171
|
+
<div>
|
|
172
|
+
<p className="text-sm font-medium text-foreground">Amount</p>
|
|
173
|
+
<p className="text-xs text-muted-foreground">
|
|
174
|
+
The amount of the milestone
|
|
175
|
+
</p>
|
|
176
|
+
</div>
|
|
177
|
+
</div>
|
|
178
|
+
<span className="font-bold text-foreground">
|
|
179
|
+
{formatCurrency(
|
|
180
|
+
selectedMilestone.milestone.amount,
|
|
181
|
+
selectedEscrow?.trustline?.name ?? "USDC"
|
|
182
|
+
)}
|
|
183
|
+
</span>
|
|
184
|
+
</div>
|
|
185
|
+
)}
|
|
186
|
+
|
|
157
187
|
<Card className="border border-border shadow-sm">
|
|
158
188
|
<CardHeader className="pb-3">
|
|
159
189
|
<CardTitle className="text-lg flex items-center gap-2">
|
|
@@ -171,21 +201,6 @@ export const MilestoneDetailDialog = ({
|
|
|
171
201
|
{selectedMilestone.milestone.description}
|
|
172
202
|
</p>
|
|
173
203
|
</div>
|
|
174
|
-
|
|
175
|
-
{"amount" in selectedMilestone.milestone && (
|
|
176
|
-
<div className="space-y-2">
|
|
177
|
-
<label className="text-sm font-medium text-foreground flex items-center gap-2">
|
|
178
|
-
<DollarSign className="w-4 h-4 text-green-600 dark:text-green-400" />
|
|
179
|
-
Amount
|
|
180
|
-
</label>
|
|
181
|
-
<div className="flex items-center gap-2 bg-green-500/10 dark:bg-green-400/10 p-3 rounded-md border-l-4 border-green-500/20 dark:border-green-400/20">
|
|
182
|
-
<DollarSign className="w-5 h-5 text-green-600 dark:text-green-400" />
|
|
183
|
-
<span className="text-lg font-bold text-green-700 dark:text-green-300">
|
|
184
|
-
{selectedMilestone.milestone.amount}
|
|
185
|
-
</span>
|
|
186
|
-
</div>
|
|
187
|
-
</div>
|
|
188
|
-
)}
|
|
189
204
|
</CardContent>
|
|
190
205
|
</Card>
|
|
191
206
|
|
|
@@ -193,7 +208,7 @@ export const MilestoneDetailDialog = ({
|
|
|
193
208
|
<Card className="border border-border shadow-sm">
|
|
194
209
|
<CardHeader className="pb-3">
|
|
195
210
|
<CardTitle className="text-lg flex items-center gap-2">
|
|
196
|
-
<div className="w-1 h-6
|
|
211
|
+
<div className="w-1 h-6 rounded-full"></div>
|
|
197
212
|
Evidence
|
|
198
213
|
</CardTitle>
|
|
199
214
|
</CardHeader>
|
|
@@ -203,7 +218,7 @@ export const MilestoneDetailDialog = ({
|
|
|
203
218
|
<FileCheck2 className="w-4 h-4 text-green-600 dark:text-green-400" />
|
|
204
219
|
Evidence URL
|
|
205
220
|
</label>
|
|
206
|
-
<div className="bg-muted/50 p-3 rounded-md border-l-4
|
|
221
|
+
<div className="bg-muted/50 p-3 rounded-md border-l-4">
|
|
207
222
|
{(() => {
|
|
208
223
|
const result = isValidUrl(
|
|
209
224
|
selectedMilestone.milestone.evidence
|
|
@@ -269,6 +284,10 @@ export const MilestoneDetailDialog = ({
|
|
|
269
284
|
</Card>
|
|
270
285
|
)}
|
|
271
286
|
</div>
|
|
287
|
+
|
|
288
|
+
{currentReceiver && (
|
|
289
|
+
<EntityCard type="receiver" entity={currentReceiver} />
|
|
290
|
+
)}
|
|
272
291
|
</DialogContent>
|
|
273
292
|
</Dialog>
|
|
274
293
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { useMemo } from "react";
|
|
4
4
|
import {
|
|
5
5
|
Dialog,
|
|
6
6
|
DialogContent,
|
|
@@ -12,6 +12,7 @@ import { EntityCard } from "./EntityCard";
|
|
|
12
12
|
import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
|
|
13
13
|
import { useEscrowAmountContext } from "@/components/tw-blocks/providers/EscrowAmountProvider";
|
|
14
14
|
import { CircleCheckBig } from "lucide-react";
|
|
15
|
+
import { MultiReleaseMilestone } from "@trustless-work/escrow";
|
|
15
16
|
|
|
16
17
|
interface SuccessReleaseDialogProps {
|
|
17
18
|
isOpen: boolean;
|
|
@@ -23,8 +24,12 @@ export const SuccessReleaseDialog = ({
|
|
|
23
24
|
onOpenChange,
|
|
24
25
|
}: SuccessReleaseDialogProps) => {
|
|
25
26
|
const { selectedEscrow } = useEscrowContext();
|
|
26
|
-
const {
|
|
27
|
-
|
|
27
|
+
const {
|
|
28
|
+
receiverAmount,
|
|
29
|
+
platformFeeAmount,
|
|
30
|
+
trustlessWorkAmount,
|
|
31
|
+
lastReleasedMilestoneIndex,
|
|
32
|
+
} = useEscrowAmountContext();
|
|
28
33
|
|
|
29
34
|
const platformFee = Number(selectedEscrow?.platformFee || 0);
|
|
30
35
|
const trustlessPercentage = 0.3;
|
|
@@ -32,8 +37,15 @@ export const SuccessReleaseDialog = ({
|
|
|
32
37
|
|
|
33
38
|
const currency = selectedEscrow?.trustline?.name ?? "";
|
|
34
39
|
|
|
35
|
-
const cards = useMemo
|
|
36
|
-
|
|
40
|
+
const cards = useMemo<
|
|
41
|
+
Array<{
|
|
42
|
+
type: string;
|
|
43
|
+
entity?: string;
|
|
44
|
+
percentage?: number;
|
|
45
|
+
amount?: number;
|
|
46
|
+
}>
|
|
47
|
+
>(() => {
|
|
48
|
+
const baseCards = [
|
|
37
49
|
{
|
|
38
50
|
type: "Platform",
|
|
39
51
|
entity: selectedEscrow?.roles?.platformAddress,
|
|
@@ -46,24 +58,62 @@ export const SuccessReleaseDialog = ({
|
|
|
46
58
|
percentage: trustlessPercentage,
|
|
47
59
|
amount: trustlessWorkAmount,
|
|
48
60
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
if (selectedEscrow?.type === "single-release") {
|
|
64
|
+
return [
|
|
65
|
+
...baseCards,
|
|
66
|
+
{
|
|
67
|
+
type: "Receiver",
|
|
68
|
+
entity: (selectedEscrow?.roles as { receiver?: string })?.receiver,
|
|
69
|
+
percentage: receiverPercentage,
|
|
70
|
+
amount: receiverAmount,
|
|
71
|
+
},
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Multi-release: show only the receiver for the just-released milestone
|
|
76
|
+
const idx =
|
|
77
|
+
typeof lastReleasedMilestoneIndex === "number"
|
|
78
|
+
? lastReleasedMilestoneIndex
|
|
79
|
+
: -1;
|
|
80
|
+
const milestone = selectedEscrow?.milestones?.[idx] as
|
|
81
|
+
| MultiReleaseMilestone
|
|
82
|
+
| undefined;
|
|
83
|
+
const receiverForReleased = milestone?.receiver;
|
|
84
|
+
|
|
85
|
+
if (receiverForReleased) {
|
|
86
|
+
return [
|
|
87
|
+
...baseCards,
|
|
88
|
+
{
|
|
89
|
+
type: "Receiver",
|
|
90
|
+
entity: receiverForReleased,
|
|
91
|
+
percentage: receiverPercentage,
|
|
92
|
+
amount: receiverAmount,
|
|
93
|
+
},
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Fallback: if no index available, list all receivers (legacy behavior)
|
|
98
|
+
const receiverCards = (selectedEscrow?.milestones || [])
|
|
99
|
+
.map((m) => (m as MultiReleaseMilestone | undefined)?.receiver)
|
|
100
|
+
.filter((r): r is string => Boolean(r))
|
|
101
|
+
.map((r) => ({ type: "Receiver", entity: r }));
|
|
102
|
+
|
|
103
|
+
return [...baseCards, ...receiverCards];
|
|
104
|
+
}, [
|
|
105
|
+
platformFee,
|
|
106
|
+
receiverPercentage,
|
|
107
|
+
trustlessPercentage,
|
|
108
|
+
platformFeeAmount,
|
|
109
|
+
trustlessWorkAmount,
|
|
110
|
+
receiverAmount,
|
|
111
|
+
selectedEscrow?.roles?.platformAddress,
|
|
112
|
+
selectedEscrow?.type,
|
|
113
|
+
selectedEscrow?.milestones,
|
|
114
|
+
selectedEscrow?.roles,
|
|
115
|
+
lastReleasedMilestoneIndex,
|
|
116
|
+
]);
|
|
67
117
|
|
|
68
118
|
return (
|
|
69
119
|
<Dialog open={isOpen} onOpenChange={onOpenChange}>
|
|
@@ -81,13 +131,19 @@ export const SuccessReleaseDialog = ({
|
|
|
81
131
|
<div className="flex flex-col gap-3">
|
|
82
132
|
{cards.map((c) => (
|
|
83
133
|
<EntityCard
|
|
84
|
-
key={c.type}
|
|
134
|
+
key={`${c.type}-${c.entity ?? "unknown"}`}
|
|
85
135
|
type={c.type}
|
|
86
136
|
entity={c.entity}
|
|
87
|
-
hasPercentage
|
|
88
|
-
percentage={
|
|
89
|
-
|
|
90
|
-
|
|
137
|
+
hasPercentage={c.percentage !== undefined}
|
|
138
|
+
percentage={
|
|
139
|
+
c.percentage !== undefined
|
|
140
|
+
? Number(c.percentage.toFixed(2))
|
|
141
|
+
: undefined
|
|
142
|
+
}
|
|
143
|
+
hasAmount={c.amount !== undefined}
|
|
144
|
+
amount={
|
|
145
|
+
c.amount !== undefined ? Number(c.amount.toFixed(2)) : undefined
|
|
146
|
+
}
|
|
91
147
|
currency={currency}
|
|
92
148
|
/>
|
|
93
149
|
))}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
GetEscrowsFromIndexerResponse as Escrow,
|
|
4
|
+
MultiReleaseMilestone,
|
|
5
|
+
} from "@trustless-work/escrow/types";
|
|
3
6
|
import { useWalletContext } from "@/components/tw-blocks/wallet-kit/WalletProvider";
|
|
4
7
|
import { useEscrowContext } from "@/components/tw-blocks/providers/EscrowProvider";
|
|
5
8
|
import { useEscrowAmountContext } from "@/components/tw-blocks/providers/EscrowAmountProvider";
|
|
@@ -60,7 +63,17 @@ const useEscrowDetailDialog = ({
|
|
|
60
63
|
name: "disputeResolver",
|
|
61
64
|
address: selectedEscrow.roles.disputeResolver,
|
|
62
65
|
},
|
|
63
|
-
{
|
|
66
|
+
{
|
|
67
|
+
name: "receiver",
|
|
68
|
+
address:
|
|
69
|
+
selectedEscrow.type === "single-release"
|
|
70
|
+
? (selectedEscrow.roles as { receiver?: string })?.receiver
|
|
71
|
+
: (
|
|
72
|
+
selectedEscrow.milestones?.[0] as
|
|
73
|
+
| MultiReleaseMilestone
|
|
74
|
+
| undefined
|
|
75
|
+
)?.receiver,
|
|
76
|
+
},
|
|
64
77
|
];
|
|
65
78
|
|
|
66
79
|
const userRoles = roleMappings
|
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
DialogTitle,
|
|
30
30
|
DialogTrigger,
|
|
31
31
|
} from "__UI_BASE__/dialog";
|
|
32
|
+
import { Separator } from "__UI_BASE__/separator";
|
|
32
33
|
|
|
33
34
|
export const InitializeEscrowDialog = () => {
|
|
34
35
|
const {
|
|
@@ -130,7 +131,7 @@ export const InitializeEscrowDialog = () => {
|
|
|
130
131
|
</Button>
|
|
131
132
|
)}
|
|
132
133
|
</Card>
|
|
133
|
-
<div className="grid grid-cols-1 lg:grid-cols-
|
|
134
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
134
135
|
<FormField
|
|
135
136
|
control={form.control}
|
|
136
137
|
name="title"
|
|
@@ -174,7 +175,9 @@ export const InitializeEscrowDialog = () => {
|
|
|
174
175
|
</FormItem>
|
|
175
176
|
)}
|
|
176
177
|
/>
|
|
178
|
+
</div>
|
|
177
179
|
|
|
180
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
178
181
|
<FormField
|
|
179
182
|
control={form.control}
|
|
180
183
|
name="trustline.address"
|
|
@@ -211,6 +214,34 @@ export const InitializeEscrowDialog = () => {
|
|
|
211
214
|
</FormItem>
|
|
212
215
|
)}
|
|
213
216
|
/>
|
|
217
|
+
|
|
218
|
+
<FormField
|
|
219
|
+
control={form.control}
|
|
220
|
+
name="platformFee"
|
|
221
|
+
render={() => (
|
|
222
|
+
<FormItem>
|
|
223
|
+
<FormLabel className="flex items-center">
|
|
224
|
+
Platform Fee
|
|
225
|
+
<span className="text-destructive ml-1">*</span>
|
|
226
|
+
</FormLabel>
|
|
227
|
+
<FormControl>
|
|
228
|
+
<div className="relative">
|
|
229
|
+
<Percent
|
|
230
|
+
className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500"
|
|
231
|
+
size={18}
|
|
232
|
+
/>
|
|
233
|
+
<Input
|
|
234
|
+
placeholder="Enter platform fee"
|
|
235
|
+
className="pl-10"
|
|
236
|
+
value={form.watch("platformFee")?.toString() || ""}
|
|
237
|
+
onChange={handlePlatformFeeChange}
|
|
238
|
+
/>
|
|
239
|
+
</div>
|
|
240
|
+
</FormControl>
|
|
241
|
+
<FormMessage />
|
|
242
|
+
</FormItem>
|
|
243
|
+
)}
|
|
244
|
+
/>
|
|
214
245
|
</div>
|
|
215
246
|
|
|
216
247
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
@@ -320,7 +351,7 @@ export const InitializeEscrowDialog = () => {
|
|
|
320
351
|
/>
|
|
321
352
|
</div>
|
|
322
353
|
|
|
323
|
-
<div className="grid grid-cols-1
|
|
354
|
+
<div className="grid grid-cols-1 gap-4">
|
|
324
355
|
<FormField
|
|
325
356
|
control={form.control}
|
|
326
357
|
name="roles.platformAddress"
|
|
@@ -328,7 +359,7 @@ export const InitializeEscrowDialog = () => {
|
|
|
328
359
|
<FormItem>
|
|
329
360
|
<FormLabel className="flex items-center justify-between">
|
|
330
361
|
<span className="flex items-center">
|
|
331
|
-
Platform
|
|
362
|
+
Platform
|
|
332
363
|
<span className="text-destructive ml-1">*</span>
|
|
333
364
|
</span>
|
|
334
365
|
</FormLabel>
|
|
@@ -346,83 +377,6 @@ export const InitializeEscrowDialog = () => {
|
|
|
346
377
|
</FormItem>
|
|
347
378
|
)}
|
|
348
379
|
/>
|
|
349
|
-
<FormField
|
|
350
|
-
control={form.control}
|
|
351
|
-
name="roles.receiver"
|
|
352
|
-
render={({ field }) => (
|
|
353
|
-
<FormItem>
|
|
354
|
-
<FormLabel className="flex items-center justify-between">
|
|
355
|
-
<span className="flex items-center">
|
|
356
|
-
Receiver<span className="text-destructive ml-1">*</span>
|
|
357
|
-
</span>
|
|
358
|
-
</FormLabel>
|
|
359
|
-
|
|
360
|
-
<FormControl>
|
|
361
|
-
<Input
|
|
362
|
-
placeholder="Enter receiver address"
|
|
363
|
-
{...field}
|
|
364
|
-
onChange={(e) => {
|
|
365
|
-
field.onChange(e);
|
|
366
|
-
}}
|
|
367
|
-
/>
|
|
368
|
-
</FormControl>
|
|
369
|
-
<FormMessage />
|
|
370
|
-
</FormItem>
|
|
371
|
-
)}
|
|
372
|
-
/>
|
|
373
|
-
</div>
|
|
374
|
-
|
|
375
|
-
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
|
376
|
-
<FormField
|
|
377
|
-
control={form.control}
|
|
378
|
-
name="platformFee"
|
|
379
|
-
render={() => (
|
|
380
|
-
<FormItem>
|
|
381
|
-
<FormLabel className="flex items-center">
|
|
382
|
-
Platform Fee
|
|
383
|
-
<span className="text-destructive ml-1">*</span>
|
|
384
|
-
</FormLabel>
|
|
385
|
-
<FormControl>
|
|
386
|
-
<div className="relative">
|
|
387
|
-
<Percent
|
|
388
|
-
className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500"
|
|
389
|
-
size={18}
|
|
390
|
-
/>
|
|
391
|
-
<Input
|
|
392
|
-
placeholder="Enter platform fee"
|
|
393
|
-
className="pl-10"
|
|
394
|
-
value={form.watch("platformFee")?.toString() || ""}
|
|
395
|
-
onChange={handlePlatformFeeChange}
|
|
396
|
-
/>
|
|
397
|
-
</div>
|
|
398
|
-
</FormControl>
|
|
399
|
-
<FormMessage />
|
|
400
|
-
</FormItem>
|
|
401
|
-
)}
|
|
402
|
-
/>
|
|
403
|
-
|
|
404
|
-
<FormField
|
|
405
|
-
control={form.control}
|
|
406
|
-
name="receiverMemo"
|
|
407
|
-
render={({ field }) => (
|
|
408
|
-
<FormItem>
|
|
409
|
-
<FormLabel className="flex items-center">
|
|
410
|
-
Receiver Memo (opcional)
|
|
411
|
-
</FormLabel>
|
|
412
|
-
<FormControl>
|
|
413
|
-
<Input
|
|
414
|
-
type="text"
|
|
415
|
-
placeholder="Enter the escrow receiver Memo"
|
|
416
|
-
{...field}
|
|
417
|
-
onChange={(e) => {
|
|
418
|
-
field.onChange(e);
|
|
419
|
-
}}
|
|
420
|
-
/>
|
|
421
|
-
</FormControl>
|
|
422
|
-
<FormMessage />
|
|
423
|
-
</FormItem>
|
|
424
|
-
)}
|
|
425
|
-
/>
|
|
426
380
|
</div>
|
|
427
381
|
|
|
428
382
|
<FormField
|
|
@@ -453,19 +407,32 @@ export const InitializeEscrowDialog = () => {
|
|
|
453
407
|
</FormLabel>
|
|
454
408
|
{milestones.map((milestone, index) => (
|
|
455
409
|
<div key={index} className="space-y-4">
|
|
456
|
-
<div className="
|
|
457
|
-
<
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
410
|
+
<div className="grid grid-cols-1 md:grid-cols-12 gap-4 items-center">
|
|
411
|
+
<div className="md:col-span-4">
|
|
412
|
+
<Input
|
|
413
|
+
placeholder="Enter receiver address"
|
|
414
|
+
value={milestone.receiver}
|
|
415
|
+
onChange={(e) => {
|
|
416
|
+
const updatedMilestones = [...milestones];
|
|
417
|
+
updatedMilestones[index].receiver = e.target.value;
|
|
418
|
+
form.setValue("milestones", updatedMilestones);
|
|
419
|
+
}}
|
|
420
|
+
/>
|
|
421
|
+
</div>
|
|
422
|
+
|
|
423
|
+
<div className="md:col-span-4">
|
|
424
|
+
<Input
|
|
425
|
+
placeholder="Milestone description"
|
|
426
|
+
value={milestone.description}
|
|
427
|
+
onChange={(e) => {
|
|
428
|
+
const updatedMilestones = [...milestones];
|
|
429
|
+
updatedMilestones[index].description = e.target.value;
|
|
430
|
+
form.setValue("milestones", updatedMilestones);
|
|
431
|
+
}}
|
|
432
|
+
/>
|
|
433
|
+
</div>
|
|
467
434
|
|
|
468
|
-
<div className="
|
|
435
|
+
<div className="md:col-span-3 relative">
|
|
469
436
|
<DollarSign
|
|
470
437
|
className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500"
|
|
471
438
|
size={18}
|
|
@@ -478,21 +445,29 @@ export const InitializeEscrowDialog = () => {
|
|
|
478
445
|
/>
|
|
479
446
|
</div>
|
|
480
447
|
|
|
481
|
-
<
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
448
|
+
<div className="md:col-span-1 flex justify-end">
|
|
449
|
+
<Button
|
|
450
|
+
onClick={() => handleRemoveMilestone(index)}
|
|
451
|
+
className="p-2 bg-transparent text-red-500 hover:text-red-600"
|
|
452
|
+
disabled={milestones.length === 1}
|
|
453
|
+
type="button"
|
|
454
|
+
>
|
|
455
|
+
<Trash2 className="h-5 w-5" />
|
|
456
|
+
</Button>
|
|
457
|
+
</div>
|
|
489
458
|
</div>
|
|
490
459
|
|
|
460
|
+
{/* Separator */}
|
|
461
|
+
{index < milestones.length - 1 && (
|
|
462
|
+
<Separator className="w-full" />
|
|
463
|
+
)}
|
|
464
|
+
|
|
465
|
+
{/* Add button */}
|
|
491
466
|
{index === milestones.length - 1 && (
|
|
492
467
|
<div className="flex justify-end mt-4">
|
|
493
468
|
<Button
|
|
494
469
|
disabled={isAnyMilestoneEmpty}
|
|
495
|
-
className="w-full md:w-
|
|
470
|
+
className="w-full md:w-fit md:min-w-40 cursor-pointer"
|
|
496
471
|
variant="outline"
|
|
497
472
|
onClick={handleAddMilestone}
|
|
498
473
|
type="button"
|