@accounter/client 0.0.7-alpha-20251021062721-ab43b5f013b9852ff5216bc141852da9dcfe0df7 → 0.0.8-alpha-20251021150028-9eb73ba6576d67c75a60786d0e4ab0876fd7a95c
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +102 -105
- package/dist/assets/index-0eCf1BcD.css +1 -0
- package/dist/assets/index-DHTbHvtz.js +1188 -0
- package/dist/assets/{index.es-NOVMdy_X.js → index.es-DHwHzag1.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +1 -2
- package/src/app.tsx +4 -8
- package/src/components/business-transactions/business-extended-info.tsx +13 -9
- package/src/components/charges/charge-extended-info-menu.tsx +21 -27
- package/src/components/charges/charges-row.tsx +10 -12
- package/src/components/charges/charges-table.tsx +9 -15
- package/src/components/common/documents/issue-document/index.tsx +3 -3
- package/src/components/common/documents/issue-document/{recent-business-docs.tsx → recent-client-docs.tsx} +13 -19
- package/src/components/common/forms/business-card.tsx +0 -1
- package/src/components/common/forms/modify-business-fields.tsx +19 -2
- package/src/components/common/inputs/combo-box.tsx +1 -1
- package/src/components/reports/trial-balance-report/trial-balance-report-group.tsx +6 -4
- package/src/components/reports/trial-balance-report/trial-balance-report-sort-code.tsx +11 -8
- package/src/components/screens/documents/issue-documents/edit-issue-document-modal.tsx +4 -4
- package/src/gql/gql.ts +9 -93
- package/src/gql/graphql.ts +20 -285
- package/src/helpers/currency.ts +0 -5
- package/src/helpers/index.ts +0 -2
- package/src/hooks/use-get-all-contracts.ts +1 -0
- package/dist/assets/index-CJB5mMpd.js +0 -1224
- package/dist/assets/index-CzRRUK04.css +0 -1
- package/src/components/business/business-header.tsx +0 -65
- package/src/components/business/charges-section.tsx +0 -82
- package/src/components/business/charts-section.tsx +0 -115
- package/src/components/business/configurations-section.tsx +0 -835
- package/src/components/business/contact-info-section.tsx +0 -544
- package/src/components/business/contracts-section.tsx +0 -195
- package/src/components/business/documents-section.tsx +0 -26
- package/src/components/business/index.tsx +0 -171
- package/src/components/business/integrations-section.tsx +0 -479
- package/src/components/business/transactions-section.tsx +0 -26
- package/src/components/clients/contracts/modify-contract-dialog.tsx +0 -466
- package/src/components/clients/modify-client-dialog.tsx +0 -276
- package/src/components/screens/businesses/business.tsx +0 -50
- package/src/components/ui/progress.tsx +0 -25
- package/src/components/ui/skeleton.tsx +0 -12
- package/src/helpers/contracts.ts +0 -22
- package/src/helpers/pcn874.ts +0 -17
- package/src/hooks/use-create-contract.ts +0 -62
- package/src/hooks/use-delete-contract.ts +0 -64
- package/src/hooks/use-insert-client.ts +0 -80
- package/src/hooks/use-update-client.ts +0 -75
- package/src/hooks/use-update-contract.ts +0 -69
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
-
import { Plus, X } from 'lucide-react';
|
|
3
|
-
import { useForm } from 'react-hook-form';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import { Button } from '@/components/ui/button.js';
|
|
6
|
-
import {
|
|
7
|
-
Dialog,
|
|
8
|
-
DialogContent,
|
|
9
|
-
DialogDescription,
|
|
10
|
-
DialogFooter,
|
|
11
|
-
DialogHeader,
|
|
12
|
-
DialogTitle,
|
|
13
|
-
DialogTrigger,
|
|
14
|
-
} from '@/components/ui/dialog.js';
|
|
15
|
-
import {
|
|
16
|
-
Form,
|
|
17
|
-
FormControl,
|
|
18
|
-
FormField,
|
|
19
|
-
FormItem,
|
|
20
|
-
FormLabel,
|
|
21
|
-
FormMessage,
|
|
22
|
-
} from '@/components/ui/form.js';
|
|
23
|
-
import { Input } from '@/components/ui/input.js';
|
|
24
|
-
import {
|
|
25
|
-
Select,
|
|
26
|
-
SelectContent,
|
|
27
|
-
SelectItem,
|
|
28
|
-
SelectTrigger,
|
|
29
|
-
SelectValue,
|
|
30
|
-
} from '@/components/ui/select.js';
|
|
31
|
-
import { DocumentType } from '@/gql/graphql.js';
|
|
32
|
-
import { getDocumentNameFromType } from '@/helpers/index.js';
|
|
33
|
-
import { useInsertClient } from '@/hooks/use-insert-client.js';
|
|
34
|
-
import { useUpdateClient } from '@/hooks/use-update-client.js';
|
|
35
|
-
import { zodResolver } from '@hookform/resolvers/zod';
|
|
36
|
-
import { Badge } from '../ui/badge';
|
|
37
|
-
|
|
38
|
-
const clientFormSchema = z.object({
|
|
39
|
-
id: z.uuid().optional(),
|
|
40
|
-
emails: z.array(z.email()).optional(),
|
|
41
|
-
generatedDocumentType: z.enum(Object.values(DocumentType)),
|
|
42
|
-
greenInvoiceId: z.uuid().optional(),
|
|
43
|
-
hiveId: z.string().optional(),
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
export type ClientFormValues = z.infer<typeof clientFormSchema>;
|
|
47
|
-
|
|
48
|
-
interface Props {
|
|
49
|
-
businessId: string;
|
|
50
|
-
client?: ClientFormValues | null;
|
|
51
|
-
onDone?: () => void;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function ModifyClientDialog({ client, businessId, onDone }: Props) {
|
|
55
|
-
const [isDialogOpen, setIsDialogOpen] = useState(false);
|
|
56
|
-
const [editingClient, setEditingClient] = useState<ClientFormValues | null>(null);
|
|
57
|
-
|
|
58
|
-
const { updateClient } = useUpdateClient();
|
|
59
|
-
const { insertClient } = useInsertClient();
|
|
60
|
-
|
|
61
|
-
const [newEmail, setNewEmail] = useState('');
|
|
62
|
-
|
|
63
|
-
const newClientDefaultValues: ClientFormValues = {
|
|
64
|
-
id: businessId,
|
|
65
|
-
generatedDocumentType: DocumentType.Proforma,
|
|
66
|
-
emails: [],
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const form = useForm<ClientFormValues>({
|
|
70
|
-
resolver: zodResolver(clientFormSchema),
|
|
71
|
-
defaultValues: client || newClientDefaultValues,
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
useEffect(() => {
|
|
75
|
-
if (client) {
|
|
76
|
-
setEditingClient(client);
|
|
77
|
-
form.reset({
|
|
78
|
-
emails: client.emails,
|
|
79
|
-
greenInvoiceId: client.greenInvoiceId,
|
|
80
|
-
hiveId: client.hiveId,
|
|
81
|
-
generatedDocumentType: client.generatedDocumentType,
|
|
82
|
-
id: client.id,
|
|
83
|
-
});
|
|
84
|
-
setIsDialogOpen(true);
|
|
85
|
-
}
|
|
86
|
-
}, [client, form]);
|
|
87
|
-
|
|
88
|
-
const handleNew = () => {
|
|
89
|
-
setEditingClient(null);
|
|
90
|
-
form.reset(newClientDefaultValues);
|
|
91
|
-
setIsDialogOpen(true);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
const addEmail = () => {
|
|
95
|
-
if (newEmail.trim()) {
|
|
96
|
-
const currentEmails = form.getValues('emails');
|
|
97
|
-
form.setValue('emails', [...(currentEmails ?? []), newEmail.trim()], { shouldDirty: true });
|
|
98
|
-
setNewEmail('');
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
const removeEmail = (index: number) => {
|
|
103
|
-
const currentEmails = form.getValues('emails');
|
|
104
|
-
form.setValue(
|
|
105
|
-
'emails',
|
|
106
|
-
(currentEmails ?? []).filter((_, i) => i !== index),
|
|
107
|
-
{ shouldDirty: true },
|
|
108
|
-
);
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const onSubmit = useCallback(
|
|
112
|
-
async (values: ClientFormValues) => {
|
|
113
|
-
if (editingClient) {
|
|
114
|
-
console.log('[v0] Updating client:', editingClient.id, values);
|
|
115
|
-
updateClient({
|
|
116
|
-
businessId,
|
|
117
|
-
fields: values,
|
|
118
|
-
});
|
|
119
|
-
} else {
|
|
120
|
-
if (!values.greenInvoiceId) {
|
|
121
|
-
form.setError('greenInvoiceId', { message: 'Green Invoice ID is required' });
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
console.log('[v0] Creating new client:', values);
|
|
125
|
-
insertClient({
|
|
126
|
-
fields: {
|
|
127
|
-
...values,
|
|
128
|
-
greenInvoiceId: values.greenInvoiceId!,
|
|
129
|
-
businessId,
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
setIsDialogOpen(false);
|
|
134
|
-
setEditingClient(null);
|
|
135
|
-
onDone?.();
|
|
136
|
-
},
|
|
137
|
-
[editingClient, onDone, updateClient, businessId, insertClient, form],
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
return (
|
|
141
|
-
<Dialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
|
|
142
|
-
<DialogTrigger asChild>
|
|
143
|
-
<Button size="sm" onClick={handleNew}>
|
|
144
|
-
<Plus className="h-4 w-4 mr-2" />
|
|
145
|
-
New Client
|
|
146
|
-
</Button>
|
|
147
|
-
</DialogTrigger>
|
|
148
|
-
<DialogContent className="max-w-2xl max-h-[90vh] overflow-y-auto">
|
|
149
|
-
<DialogHeader>
|
|
150
|
-
<DialogTitle>{editingClient ? 'Edit Client' : 'Create New Client'}</DialogTitle>
|
|
151
|
-
<DialogDescription>
|
|
152
|
-
{editingClient ? 'Update client details' : 'Add a new client with all required details'}
|
|
153
|
-
</DialogDescription>
|
|
154
|
-
</DialogHeader>
|
|
155
|
-
<Form {...form}>
|
|
156
|
-
<form onSubmit={form.handleSubmit(onSubmit)}>
|
|
157
|
-
<div className="grid gap-4 py-4">
|
|
158
|
-
<div className="grid gap-4 md:grid-cols-2">
|
|
159
|
-
<FormField
|
|
160
|
-
control={form.control}
|
|
161
|
-
name="emails"
|
|
162
|
-
render={({ field }) => (
|
|
163
|
-
<FormItem>
|
|
164
|
-
<FormLabel>Emails</FormLabel>
|
|
165
|
-
<div className="flex gap-2">
|
|
166
|
-
<Input
|
|
167
|
-
placeholder="Add email..."
|
|
168
|
-
value={newEmail}
|
|
169
|
-
onChange={e => setNewEmail(e.target.value)}
|
|
170
|
-
onKeyDown={e => {
|
|
171
|
-
if (e.key === 'Enter') {
|
|
172
|
-
e.preventDefault();
|
|
173
|
-
addEmail();
|
|
174
|
-
}
|
|
175
|
-
}}
|
|
176
|
-
/>
|
|
177
|
-
<Button type="button" size="sm" onClick={addEmail}>
|
|
178
|
-
<Plus className="h-4 w-4" />
|
|
179
|
-
</Button>
|
|
180
|
-
</div>
|
|
181
|
-
<div className="flex flex-wrap gap-2">
|
|
182
|
-
{field.value?.map((email, index) => (
|
|
183
|
-
<Badge key={index} variant="secondary" className="gap-1">
|
|
184
|
-
{email}
|
|
185
|
-
<Button
|
|
186
|
-
variant="ghost"
|
|
187
|
-
size="icon"
|
|
188
|
-
className="p-0 size-3"
|
|
189
|
-
onClick={() => removeEmail(index)}
|
|
190
|
-
>
|
|
191
|
-
<X className="size-3 cursor-pointer" />
|
|
192
|
-
</Button>
|
|
193
|
-
</Badge>
|
|
194
|
-
))}
|
|
195
|
-
</div>
|
|
196
|
-
<FormMessage />
|
|
197
|
-
</FormItem>
|
|
198
|
-
)}
|
|
199
|
-
/>
|
|
200
|
-
|
|
201
|
-
<FormField
|
|
202
|
-
control={form.control}
|
|
203
|
-
name="generatedDocumentType"
|
|
204
|
-
render={({ field }) => (
|
|
205
|
-
<FormItem>
|
|
206
|
-
<FormLabel>Default Document Type</FormLabel>
|
|
207
|
-
<Select onValueChange={field.onChange} defaultValue={field.value}>
|
|
208
|
-
<FormControl>
|
|
209
|
-
<SelectTrigger>
|
|
210
|
-
<SelectValue />
|
|
211
|
-
</SelectTrigger>
|
|
212
|
-
</FormControl>
|
|
213
|
-
<SelectContent>
|
|
214
|
-
{Object.values(DocumentType).map(type => (
|
|
215
|
-
<SelectItem key={type} value={type}>
|
|
216
|
-
{getDocumentNameFromType(type)}
|
|
217
|
-
</SelectItem>
|
|
218
|
-
))}
|
|
219
|
-
</SelectContent>
|
|
220
|
-
</Select>
|
|
221
|
-
<FormMessage />
|
|
222
|
-
</FormItem>
|
|
223
|
-
)}
|
|
224
|
-
/>
|
|
225
|
-
|
|
226
|
-
<FormField
|
|
227
|
-
control={form.control}
|
|
228
|
-
name="greenInvoiceId"
|
|
229
|
-
render={({ field }) => (
|
|
230
|
-
<FormItem>
|
|
231
|
-
<FormLabel>Green Invoice ID</FormLabel>
|
|
232
|
-
<FormControl>
|
|
233
|
-
<Input
|
|
234
|
-
type="text"
|
|
235
|
-
placeholder="Enter Green Invoice ID"
|
|
236
|
-
{...field}
|
|
237
|
-
required={!editingClient}
|
|
238
|
-
/>
|
|
239
|
-
</FormControl>
|
|
240
|
-
<FormMessage />
|
|
241
|
-
</FormItem>
|
|
242
|
-
)}
|
|
243
|
-
/>
|
|
244
|
-
|
|
245
|
-
<FormField
|
|
246
|
-
control={form.control}
|
|
247
|
-
name="hiveId"
|
|
248
|
-
render={({ field }) => (
|
|
249
|
-
<FormItem>
|
|
250
|
-
<FormLabel>Hive ID</FormLabel>
|
|
251
|
-
<FormControl>
|
|
252
|
-
<Input
|
|
253
|
-
type="text"
|
|
254
|
-
placeholder="Enter Hive ID"
|
|
255
|
-
{...field}
|
|
256
|
-
required={!editingClient}
|
|
257
|
-
/>
|
|
258
|
-
</FormControl>
|
|
259
|
-
<FormMessage />
|
|
260
|
-
</FormItem>
|
|
261
|
-
)}
|
|
262
|
-
/>
|
|
263
|
-
</div>
|
|
264
|
-
</div>
|
|
265
|
-
<DialogFooter>
|
|
266
|
-
<Button type="button" variant="outline" onClick={() => setIsDialogOpen(false)}>
|
|
267
|
-
Cancel
|
|
268
|
-
</Button>
|
|
269
|
-
<Button type="submit">{editingClient ? 'Update Client' : 'Create Client'}</Button>
|
|
270
|
-
</DialogFooter>
|
|
271
|
-
</form>
|
|
272
|
-
</Form>
|
|
273
|
-
</DialogContent>
|
|
274
|
-
</Dialog>
|
|
275
|
-
);
|
|
276
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { useEffect, type ReactElement } from 'react';
|
|
2
|
-
import { useMatch } from 'react-router-dom';
|
|
3
|
-
import { useQuery } from 'urql';
|
|
4
|
-
import Business from '@/components/business/index.js';
|
|
5
|
-
import { BusinessScreenDocument } from '../../../gql/graphql.js';
|
|
6
|
-
import { AccounterLoader } from '../../common/index.js';
|
|
7
|
-
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
9
|
-
/* GraphQL */ `
|
|
10
|
-
query BusinessScreen($businessId: UUID!) {
|
|
11
|
-
business(id: $businessId) {
|
|
12
|
-
id
|
|
13
|
-
...BusinessPage
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
`;
|
|
17
|
-
|
|
18
|
-
export function getBusinessHref(businessId: string): string {
|
|
19
|
-
return `/businesses/${businessId}`;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export const BusinessScreen = (): ReactElement => {
|
|
23
|
-
const match = useMatch('/businesses/:businessId');
|
|
24
|
-
|
|
25
|
-
const businessId = match?.params.businessId;
|
|
26
|
-
|
|
27
|
-
const [{ data, fetching }, fetchBusiness] = useQuery({
|
|
28
|
-
query: BusinessScreenDocument,
|
|
29
|
-
pause: !businessId,
|
|
30
|
-
variables: {
|
|
31
|
-
businessId: businessId ?? '',
|
|
32
|
-
},
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
if (businessId) {
|
|
37
|
-
fetchBusiness();
|
|
38
|
-
}
|
|
39
|
-
}, [businessId, fetchBusiness]);
|
|
40
|
-
|
|
41
|
-
if (fetching && !data?.business) {
|
|
42
|
-
return <AccounterLoader />;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (!businessId || !data?.business) {
|
|
46
|
-
return <div>Business not found</div>;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return <Business data={data.business} refetchBusiness={async () => fetchBusiness()} />;
|
|
50
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { forwardRef, type ComponentPropsWithoutRef, type ComponentRef } from 'react';
|
|
2
|
-
import { cn } from '@/lib/utils.js';
|
|
3
|
-
import * as ProgressPrimitive from '@radix-ui/react-progress';
|
|
4
|
-
|
|
5
|
-
const Progress = forwardRef<
|
|
6
|
-
ComponentRef<typeof ProgressPrimitive.Root>,
|
|
7
|
-
ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
|
|
8
|
-
>(({ className, value, ...props }, ref) => (
|
|
9
|
-
<ProgressPrimitive.Root
|
|
10
|
-
ref={ref}
|
|
11
|
-
className={cn(
|
|
12
|
-
'relative h-2 w-full overflow-hidden rounded-full bg-gray-900/20 dark:bg-gray-50/20',
|
|
13
|
-
className,
|
|
14
|
-
)}
|
|
15
|
-
{...props}
|
|
16
|
-
>
|
|
17
|
-
<ProgressPrimitive.Indicator
|
|
18
|
-
className="h-full w-full flex-1 bg-gray-900 transition-all dark:bg-gray-50"
|
|
19
|
-
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
|
20
|
-
/>
|
|
21
|
-
</ProgressPrimitive.Root>
|
|
22
|
-
));
|
|
23
|
-
Progress.displayName = ProgressPrimitive.Root.displayName;
|
|
24
|
-
|
|
25
|
-
export { Progress };
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { cn } from '@/lib/utils.js';
|
|
2
|
-
|
|
3
|
-
function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
|
|
4
|
-
return (
|
|
5
|
-
<div
|
|
6
|
-
className={cn('animate-pulse rounded-md bg-gray-900/10 dark:bg-gray-50/10', className)}
|
|
7
|
-
{...props}
|
|
8
|
-
/>
|
|
9
|
-
);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export { Skeleton };
|
package/src/helpers/contracts.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { BillingCycle, SubscriptionPlan } from '@/gql/graphql.js';
|
|
2
|
-
|
|
3
|
-
export function standardBillingCycle(billingCycle: BillingCycle): string {
|
|
4
|
-
switch (billingCycle) {
|
|
5
|
-
case BillingCycle.Annual:
|
|
6
|
-
return 'Annual';
|
|
7
|
-
case BillingCycle.Monthly:
|
|
8
|
-
return 'Monthly';
|
|
9
|
-
default:
|
|
10
|
-
throw new Error(`Unsupported Billing Cycle: ${billingCycle}`);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
export function standardPlan(plan: SubscriptionPlan): string {
|
|
14
|
-
switch (plan) {
|
|
15
|
-
case SubscriptionPlan.Enterprise:
|
|
16
|
-
return 'Enterprise';
|
|
17
|
-
case SubscriptionPlan.Pro:
|
|
18
|
-
return 'Pro';
|
|
19
|
-
default:
|
|
20
|
-
throw new Error(`Unsupported Subscription plan: ${plan}`);
|
|
21
|
-
}
|
|
22
|
-
}
|
package/src/helpers/pcn874.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { Pcn874RecordType } from '@/gql/graphql.js';
|
|
2
|
-
|
|
3
|
-
export const pcn874RecordEnum: Record<Pcn874RecordType, string> = {
|
|
4
|
-
C: 'INPUT_SELF_INVOICE',
|
|
5
|
-
H: 'INPUT_SINGLE_DOC_BY_LAW',
|
|
6
|
-
I: 'SALE_PALESTINIAN_CUSTOMER',
|
|
7
|
-
K: 'INPUT_PETTY_CASH',
|
|
8
|
-
L1: 'SALE_UNIDENTIFIED_CUSTOMER',
|
|
9
|
-
L2: 'SALE_UNIDENTIFIED_ZERO_OR_EXEMPT',
|
|
10
|
-
M: 'SALE_SELF_INVOICE',
|
|
11
|
-
P: 'INPUT_PALESTINIAN_SUPPLIER',
|
|
12
|
-
R: 'INPUT_IMPORT',
|
|
13
|
-
S1: 'SALE_REGULAR',
|
|
14
|
-
S2: 'SALE_ZERO_OR_EXEMPT',
|
|
15
|
-
T: 'INPUT_REGULAR',
|
|
16
|
-
Y: 'SALE_EXPORT',
|
|
17
|
-
} as const;
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
import { toast } from 'sonner';
|
|
3
|
-
import { useMutation } from 'urql';
|
|
4
|
-
import { CreateContractDocument, type CreateContractMutationVariables } from '../gql/graphql.js';
|
|
5
|
-
import { handleCommonErrors } from '../helpers/error-handling.js';
|
|
6
|
-
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
8
|
-
/* GraphQL */ `
|
|
9
|
-
mutation CreateContract($input: CreateContractInput!) {
|
|
10
|
-
createContract(input: $input) {
|
|
11
|
-
id
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
`;
|
|
15
|
-
|
|
16
|
-
type UseCreateContract = {
|
|
17
|
-
creating: boolean;
|
|
18
|
-
createContract: (variables: CreateContractMutationVariables) => Promise<void>;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const NOTIFICATION_ID = 'createContract';
|
|
22
|
-
|
|
23
|
-
export const useCreateContract = (): UseCreateContract => {
|
|
24
|
-
// TODO: add authentication
|
|
25
|
-
// TODO: add local data update method after chang e
|
|
26
|
-
|
|
27
|
-
const [{ fetching }, mutate] = useMutation(CreateContractDocument);
|
|
28
|
-
const createContract = useCallback(
|
|
29
|
-
async (variables: CreateContractMutationVariables) => {
|
|
30
|
-
const message = `Error creating new contract for client[${variables.input.clientId}]`;
|
|
31
|
-
const notificationId = `${NOTIFICATION_ID}-${variables.input.clientId}`;
|
|
32
|
-
toast.loading('Creating contract', {
|
|
33
|
-
id: notificationId,
|
|
34
|
-
});
|
|
35
|
-
try {
|
|
36
|
-
const res = await mutate(variables);
|
|
37
|
-
const data = handleCommonErrors(res, message, notificationId);
|
|
38
|
-
if (data) {
|
|
39
|
-
toast.success('Success', {
|
|
40
|
-
id: notificationId,
|
|
41
|
-
description: `Contract for client ${variables.input.clientId} was successfully created`,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
} catch (e) {
|
|
45
|
-
console.error(`${message}: ${e}`);
|
|
46
|
-
toast.error('Error', {
|
|
47
|
-
id: notificationId,
|
|
48
|
-
description: message,
|
|
49
|
-
duration: 100_000,
|
|
50
|
-
closeButton: true,
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
return void 0;
|
|
54
|
-
},
|
|
55
|
-
[mutate],
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
return {
|
|
59
|
-
creating: fetching,
|
|
60
|
-
createContract,
|
|
61
|
-
};
|
|
62
|
-
};
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
import { toast } from 'sonner';
|
|
3
|
-
import { useMutation } from 'urql';
|
|
4
|
-
import { DeleteContractDocument, type DeleteContractMutationVariables } from '../gql/graphql.js';
|
|
5
|
-
import { handleCommonErrors } from '../helpers/error-handling.js';
|
|
6
|
-
|
|
7
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
8
|
-
/* GraphQL */ `
|
|
9
|
-
mutation DeleteContract($contractId: UUID!) {
|
|
10
|
-
deleteContract(id: $contractId)
|
|
11
|
-
}
|
|
12
|
-
`;
|
|
13
|
-
|
|
14
|
-
type UseDeleteContract = {
|
|
15
|
-
fetching: boolean;
|
|
16
|
-
deleteContract: (variables: DeleteContractMutationVariables) => Promise<boolean>;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const NOTIFICATION_ID = 'deleteContract';
|
|
20
|
-
|
|
21
|
-
export const useDeleteContract = (): UseDeleteContract => {
|
|
22
|
-
// TODO: add authentication
|
|
23
|
-
// TODO: add local data delete method after change
|
|
24
|
-
|
|
25
|
-
const [{ fetching }, mutate] = useMutation(DeleteContractDocument);
|
|
26
|
-
const deleteContract = useCallback(
|
|
27
|
-
async (variables: DeleteContractMutationVariables) => {
|
|
28
|
-
const message = `Error deleting contract ID [${variables.contractId}]`;
|
|
29
|
-
const notificationId = `${NOTIFICATION_ID}-${variables.contractId}`;
|
|
30
|
-
toast.loading('Deleting contract', {
|
|
31
|
-
id: notificationId,
|
|
32
|
-
});
|
|
33
|
-
try {
|
|
34
|
-
const res = await mutate(variables);
|
|
35
|
-
const data = handleCommonErrors(res, message, notificationId);
|
|
36
|
-
if (data) {
|
|
37
|
-
if (data.deleteContract === false) {
|
|
38
|
-
throw new Error('Unsuccessful deletion');
|
|
39
|
-
}
|
|
40
|
-
toast.success('Success', {
|
|
41
|
-
id: notificationId,
|
|
42
|
-
description: 'Contract was deleted',
|
|
43
|
-
});
|
|
44
|
-
return data.deleteContract;
|
|
45
|
-
}
|
|
46
|
-
} catch (e) {
|
|
47
|
-
console.error(`${message}: ${e}`);
|
|
48
|
-
toast.error('Error', {
|
|
49
|
-
id: notificationId,
|
|
50
|
-
description: message,
|
|
51
|
-
duration: 100_000,
|
|
52
|
-
closeButton: true,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return false;
|
|
56
|
-
},
|
|
57
|
-
[mutate],
|
|
58
|
-
);
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
fetching,
|
|
62
|
-
deleteContract,
|
|
63
|
-
};
|
|
64
|
-
};
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
import { toast } from 'sonner';
|
|
3
|
-
import { useMutation } from 'urql';
|
|
4
|
-
import {
|
|
5
|
-
InsertClientDocument,
|
|
6
|
-
type InsertClientMutation,
|
|
7
|
-
type InsertClientMutationVariables,
|
|
8
|
-
} from '../gql/graphql.js';
|
|
9
|
-
import { handleCommonErrors } from '../helpers/error-handling.js';
|
|
10
|
-
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
12
|
-
/* GraphQL */ `
|
|
13
|
-
mutation InsertClient($fields: ClientInsertInput!) {
|
|
14
|
-
insertClient(fields: $fields) {
|
|
15
|
-
__typename
|
|
16
|
-
... on Client {
|
|
17
|
-
id
|
|
18
|
-
}
|
|
19
|
-
... on CommonError {
|
|
20
|
-
message
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
`;
|
|
25
|
-
|
|
26
|
-
type InsertClientSuccessfulResult = Extract<
|
|
27
|
-
InsertClientMutation['insertClient'],
|
|
28
|
-
{ __typename: 'Client' }
|
|
29
|
-
>;
|
|
30
|
-
|
|
31
|
-
type UseInsertClient = {
|
|
32
|
-
fetching: boolean;
|
|
33
|
-
insertClient: (
|
|
34
|
-
variables: InsertClientMutationVariables,
|
|
35
|
-
) => Promise<InsertClientSuccessfulResult | void>;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const NOTIFICATION_ID = 'insertClient';
|
|
39
|
-
|
|
40
|
-
export const useInsertClient = (): UseInsertClient => {
|
|
41
|
-
// TODO: add authentication
|
|
42
|
-
// TODO: add local data update method after insert
|
|
43
|
-
|
|
44
|
-
const [{ fetching }, mutate] = useMutation(InsertClientDocument);
|
|
45
|
-
const insertClient = useCallback(
|
|
46
|
-
async (variables: InsertClientMutationVariables) => {
|
|
47
|
-
const errorMessage = `Error creating client [${variables.fields.businessId}]`;
|
|
48
|
-
const notificationId = `${NOTIFICATION_ID}-${variables.fields.businessId}`;
|
|
49
|
-
toast.loading('Creating Client...', {
|
|
50
|
-
id: notificationId,
|
|
51
|
-
});
|
|
52
|
-
try {
|
|
53
|
-
const res = await mutate(variables);
|
|
54
|
-
const data = handleCommonErrors(res, errorMessage, notificationId, 'insertClient');
|
|
55
|
-
if (data) {
|
|
56
|
-
toast.success('Success', {
|
|
57
|
-
id: notificationId,
|
|
58
|
-
description: `Client [${variables.fields.businessId}] was created`,
|
|
59
|
-
});
|
|
60
|
-
return data.insertClient;
|
|
61
|
-
}
|
|
62
|
-
} catch (e) {
|
|
63
|
-
console.error(`${errorMessage}: ${e}`);
|
|
64
|
-
toast.error('Error', {
|
|
65
|
-
id: notificationId,
|
|
66
|
-
description: errorMessage,
|
|
67
|
-
duration: 100_000,
|
|
68
|
-
closeButton: true,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
return void 0;
|
|
72
|
-
},
|
|
73
|
-
[mutate],
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
fetching,
|
|
78
|
-
insertClient,
|
|
79
|
-
};
|
|
80
|
-
};
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react';
|
|
2
|
-
import { toast } from 'sonner';
|
|
3
|
-
import { useMutation } from 'urql';
|
|
4
|
-
import {
|
|
5
|
-
UpdateClientDocument,
|
|
6
|
-
type UpdateClientMutation,
|
|
7
|
-
type UpdateClientMutationVariables,
|
|
8
|
-
} from '../gql/graphql.js';
|
|
9
|
-
import { handleCommonErrors } from '../helpers/error-handling.js';
|
|
10
|
-
|
|
11
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
12
|
-
/* GraphQL */ `
|
|
13
|
-
mutation UpdateClient($businessId: UUID!, $fields: ClientUpdateInput!) {
|
|
14
|
-
updateClient(businessId: $businessId, fields: $fields) {
|
|
15
|
-
__typename
|
|
16
|
-
... on Client {
|
|
17
|
-
id
|
|
18
|
-
}
|
|
19
|
-
... on CommonError {
|
|
20
|
-
message
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
`;
|
|
25
|
-
|
|
26
|
-
type Client = Extract<UpdateClientMutation['updateClient'], { __typename: 'Client' }>;
|
|
27
|
-
|
|
28
|
-
type UseUpdateClient = {
|
|
29
|
-
fetching: boolean;
|
|
30
|
-
updateClient: (variables: UpdateClientMutationVariables) => Promise<Client | void>;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const NOTIFICATION_ID = 'updateClient';
|
|
34
|
-
|
|
35
|
-
export const useUpdateClient = (): UseUpdateClient => {
|
|
36
|
-
// TODO: add authentication
|
|
37
|
-
// TODO: add local data update method after change
|
|
38
|
-
|
|
39
|
-
const [{ fetching }, mutate] = useMutation(UpdateClientDocument);
|
|
40
|
-
const updateClient = useCallback(
|
|
41
|
-
async (variables: UpdateClientMutationVariables) => {
|
|
42
|
-
const message = `Error updating client ID [${variables.businessId}]`;
|
|
43
|
-
const notificationId = `${NOTIFICATION_ID}-${variables.businessId}`;
|
|
44
|
-
toast.loading('Updating client', {
|
|
45
|
-
id: notificationId,
|
|
46
|
-
});
|
|
47
|
-
try {
|
|
48
|
-
const res = await mutate(variables);
|
|
49
|
-
const data = handleCommonErrors(res, message, notificationId, 'updateClient');
|
|
50
|
-
if (data) {
|
|
51
|
-
toast.success('Success', {
|
|
52
|
-
id: notificationId,
|
|
53
|
-
description: 'Client updated',
|
|
54
|
-
});
|
|
55
|
-
return data.updateClient;
|
|
56
|
-
}
|
|
57
|
-
} catch (e) {
|
|
58
|
-
console.error(`${message}: ${e}`);
|
|
59
|
-
toast.error('Error', {
|
|
60
|
-
id: notificationId,
|
|
61
|
-
description: message,
|
|
62
|
-
duration: 100_000,
|
|
63
|
-
closeButton: true,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
return void 0;
|
|
67
|
-
},
|
|
68
|
-
[mutate],
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
return {
|
|
72
|
-
fetching,
|
|
73
|
-
updateClient,
|
|
74
|
-
};
|
|
75
|
-
};
|