@accounter/client 0.0.7-alpha-20251020201144-e623a2bb538d1219a5f541df2364646012ebe9ea → 0.0.7-alpha-20251021062721-ab43b5f013b9852ff5216bc141852da9dcfe0df7
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 +24 -1
- package/dist/assets/index-CJB5mMpd.js +1224 -0
- package/dist/assets/index-CzRRUK04.css +1 -0
- package/dist/assets/{index.es-CNXdeXse.js → index.es-NOVMdy_X.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +3 -2
- package/src/app.tsx +8 -4
- package/src/components/business/business-header.tsx +65 -0
- package/src/components/business/charges-section.tsx +82 -0
- package/src/components/business/charts-section.tsx +115 -0
- package/src/components/business/configurations-section.tsx +835 -0
- package/src/components/business/contact-info-section.tsx +544 -0
- package/src/components/business/contracts-section.tsx +195 -0
- package/src/components/business/documents-section.tsx +26 -0
- package/src/components/business/index.tsx +171 -0
- package/src/components/business/integrations-section.tsx +479 -0
- package/src/components/business/transactions-section.tsx +26 -0
- package/src/components/business-transactions/business-extended-info.tsx +9 -13
- package/src/components/charges/charge-extended-info-menu.tsx +27 -21
- package/src/components/charges/charges-row.tsx +12 -10
- package/src/components/charges/charges-table.tsx +15 -9
- package/src/components/clients/contracts/modify-contract-dialog.tsx +466 -0
- package/src/components/clients/modify-client-dialog.tsx +276 -0
- package/src/components/common/documents/issue-document/index.tsx +3 -3
- package/src/components/common/documents/issue-document/{recent-client-docs.tsx → recent-business-docs.tsx} +19 -13
- package/src/components/common/forms/business-card.tsx +1 -0
- package/src/components/common/forms/modify-business-fields.tsx +15 -33
- package/src/components/common/inputs/combo-box.tsx +1 -1
- package/src/components/common/modals/insert-business.tsx +4 -2
- package/src/components/reports/trial-balance-report/trial-balance-report-group.tsx +4 -6
- package/src/components/reports/trial-balance-report/trial-balance-report-sort-code.tsx +8 -11
- package/src/components/screens/businesses/business.tsx +50 -0
- package/src/components/screens/documents/issue-documents/edit-issue-document-modal.tsx +4 -4
- package/src/components/ui/progress.tsx +25 -0
- package/src/components/ui/skeleton.tsx +12 -0
- package/src/gql/gql.ts +96 -12
- package/src/gql/graphql.ts +290 -11
- package/src/helpers/contracts.ts +22 -0
- package/src/helpers/currency.ts +5 -0
- package/src/helpers/index.ts +2 -0
- package/src/helpers/pcn874.ts +17 -0
- package/src/hooks/use-create-contract.ts +62 -0
- package/src/hooks/use-delete-contract.ts +64 -0
- package/src/hooks/use-get-all-contracts.ts +0 -1
- package/src/hooks/use-insert-client.ts +80 -0
- package/src/hooks/use-update-client.ts +75 -0
- package/src/hooks/use-update-contract.ts +69 -0
- package/src/providers/user-provider.tsx +2 -0
- package/dist/assets/index-0eCf1BcD.css +0 -1
- package/dist/assets/index-Dh8zU8Ik.js +0 -1188
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { format } from 'date-fns';
|
|
2
|
+
import { Building2 } from 'lucide-react';
|
|
3
|
+
import { Badge } from '@/components/ui/badge.js';
|
|
4
|
+
import { BusinessHeaderFragmentDoc } from '@/gql/graphql.js';
|
|
5
|
+
import { getFragmentData, type FragmentType } from '@/gql/index.js';
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
8
|
+
/* GraphQL */ `
|
|
9
|
+
fragment BusinessHeader on Business {
|
|
10
|
+
__typename
|
|
11
|
+
id
|
|
12
|
+
name
|
|
13
|
+
createdAt
|
|
14
|
+
... on LtdFinancialEntity {
|
|
15
|
+
governmentId
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
interface Props {
|
|
21
|
+
data?: FragmentType<typeof BusinessHeaderFragmentDoc>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function BusinessHeader({ data }: Props) {
|
|
25
|
+
const business = getFragmentData(BusinessHeaderFragmentDoc, data);
|
|
26
|
+
|
|
27
|
+
if (!business || business.__typename !== 'LtdFinancialEntity') {
|
|
28
|
+
return <div />;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<header className="sticky top-0 z-50 w-full border-b border-border bg-card/95 backdrop-blur supports-[backdrop-filter]:bg-card/60">
|
|
33
|
+
<div className="container mx-auto px-4 md:px-6 lg:px-8 max-w-7xl">
|
|
34
|
+
<div className="flex h-16 items-center justify-between gap-4">
|
|
35
|
+
<div className="flex items-center gap-3 min-w-0 flex-1">
|
|
36
|
+
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-accent">
|
|
37
|
+
<Building2 className="h-5 w-5 text-accent-foreground" />
|
|
38
|
+
</div>
|
|
39
|
+
<div className="min-w-0 flex-1">
|
|
40
|
+
<div className="flex items-center gap-2 flex-wrap">
|
|
41
|
+
<h1 className="text-lg font-semibold text-foreground">{business.name}</h1>
|
|
42
|
+
{/* TODO: make dynamic, add client badge */}
|
|
43
|
+
<Badge variant="secondary">Active</Badge>
|
|
44
|
+
</div>
|
|
45
|
+
<p className="text-sm text-muted-foreground truncate">Business ID: {business.id}</p>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div className="hidden md:flex items-center gap-6 text-sm">
|
|
50
|
+
<div className="text-right">
|
|
51
|
+
<p className="text-muted-foreground">Tax ID</p>
|
|
52
|
+
<p className="font-medium text-foreground">{business.governmentId}</p>
|
|
53
|
+
</div>
|
|
54
|
+
<div className="text-right">
|
|
55
|
+
<p className="text-muted-foreground">Since</p>
|
|
56
|
+
<p className="font-medium text-foreground">
|
|
57
|
+
{format(business.createdAt, 'MMM yyyy')}
|
|
58
|
+
</p>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</header>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { useContext, useState } from 'react';
|
|
2
|
+
import { useQuery } from 'urql';
|
|
3
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card.js';
|
|
4
|
+
import { BusinessChargesSectionDocument, ChargeSortByField } from '@/gql/graphql.js';
|
|
5
|
+
import { UserContext } from '@/providers/user-provider.js';
|
|
6
|
+
import { Pagination } from '@mantine/core';
|
|
7
|
+
import { ChargesTable } from '../charges/charges-table';
|
|
8
|
+
|
|
9
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions -- used by codegen
|
|
10
|
+
/* GraphQL */ `
|
|
11
|
+
query BusinessChargesSection($page: Int, $limit: Int, $filters: ChargeFilter) {
|
|
12
|
+
allCharges(page: $page, limit: $limit, filters: $filters) {
|
|
13
|
+
nodes {
|
|
14
|
+
id
|
|
15
|
+
...ChargesTableFields
|
|
16
|
+
}
|
|
17
|
+
pageInfo {
|
|
18
|
+
totalPages
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
`;
|
|
23
|
+
|
|
24
|
+
interface Props {
|
|
25
|
+
businessId: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function ChargesSection({ businessId }: Props) {
|
|
29
|
+
const { userContext } = useContext(UserContext);
|
|
30
|
+
const [activePage, setActivePage] = useState(1);
|
|
31
|
+
|
|
32
|
+
const [{ data, fetching }] = useQuery({
|
|
33
|
+
query: BusinessChargesSectionDocument,
|
|
34
|
+
variables: {
|
|
35
|
+
filters: {
|
|
36
|
+
byOwners: userContext?.context.adminBusinessId
|
|
37
|
+
? [userContext.context.adminBusinessId]
|
|
38
|
+
: undefined,
|
|
39
|
+
sortBy: {
|
|
40
|
+
field: ChargeSortByField.Date,
|
|
41
|
+
asc: false,
|
|
42
|
+
},
|
|
43
|
+
byBusinesses: [businessId],
|
|
44
|
+
},
|
|
45
|
+
page: activePage,
|
|
46
|
+
limit: 100,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const totalPages = data?.allCharges?.pageInfo.totalPages ?? 1;
|
|
51
|
+
const charges = data?.allCharges?.nodes ?? [];
|
|
52
|
+
|
|
53
|
+
if (fetching) {
|
|
54
|
+
return <div>Loading charges...</div>;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<Card>
|
|
59
|
+
<CardHeader className="flex w-full justify-between items-center">
|
|
60
|
+
<div className="flex items-center justify-between">
|
|
61
|
+
<div>
|
|
62
|
+
<CardTitle>Charges</CardTitle>
|
|
63
|
+
<CardDescription>Recurring and one-time charges for this business</CardDescription>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
{totalPages > 1 && (
|
|
67
|
+
<Pagination
|
|
68
|
+
className="flex-fit"
|
|
69
|
+
value={activePage}
|
|
70
|
+
onChange={setActivePage}
|
|
71
|
+
total={totalPages}
|
|
72
|
+
/>
|
|
73
|
+
)}
|
|
74
|
+
</CardHeader>
|
|
75
|
+
<CardContent>
|
|
76
|
+
<div className="rounded-md border">
|
|
77
|
+
<ChargesTable data={charges} isAllOpened={false} />
|
|
78
|
+
</div>
|
|
79
|
+
</CardContent>
|
|
80
|
+
</Card>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { DollarSign, TrendingUp } from 'lucide-react';
|
|
2
|
+
import { CartesianGrid, Line, LineChart, ResponsiveContainer, XAxis, YAxis } from 'recharts';
|
|
3
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card.js';
|
|
4
|
+
import { ChartContainer, ChartTooltip, ChartTooltipContent } from '@/components/ui/chart.js';
|
|
5
|
+
|
|
6
|
+
const revenueData = [
|
|
7
|
+
{ month: 'Jan', revenue: 12_500, expenses: 8200 },
|
|
8
|
+
{ month: 'Feb', revenue: 15_800, expenses: 9100 },
|
|
9
|
+
{ month: 'Mar', revenue: 18_200, expenses: 10_500 },
|
|
10
|
+
{ month: 'Apr', revenue: 16_900, expenses: 9800 },
|
|
11
|
+
{ month: 'May', revenue: 21_300, expenses: 11_200 },
|
|
12
|
+
{ month: 'Jun', revenue: 24_500, expenses: 12_800 },
|
|
13
|
+
{ month: 'Jul', revenue: 22_800, expenses: 11_900 },
|
|
14
|
+
{ month: 'Aug', revenue: 26_100, expenses: 13_500 },
|
|
15
|
+
{ month: 'Sep', revenue: 28_900, expenses: 14_200 },
|
|
16
|
+
{ month: 'Oct', revenue: 31_200, expenses: 15_100 },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export function ChartsSection() {
|
|
20
|
+
const totalRevenue = revenueData.reduce((sum, item) => sum + item.revenue, 0);
|
|
21
|
+
const avgRevenue = totalRevenue / revenueData.length;
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Card>
|
|
25
|
+
<CardHeader>
|
|
26
|
+
<CardTitle>Revenue Analytics</CardTitle>
|
|
27
|
+
<CardDescription>Revenue and expenses over time</CardDescription>
|
|
28
|
+
</CardHeader>
|
|
29
|
+
<CardContent>
|
|
30
|
+
<div className="grid gap-4 md:grid-cols-3 mb-6">
|
|
31
|
+
<div className="rounded-lg border p-4 space-y-2">
|
|
32
|
+
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
33
|
+
<DollarSign className="h-4 w-4" />
|
|
34
|
+
Total Revenue
|
|
35
|
+
</div>
|
|
36
|
+
<p className="text-2xl font-bold">${totalRevenue.toLocaleString()}</p>
|
|
37
|
+
<div className="flex items-center gap-1 text-sm text-green-600">
|
|
38
|
+
<TrendingUp className="h-3 w-3" />
|
|
39
|
+
<span>+24.5% from last period</span>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
|
|
43
|
+
<div className="rounded-lg border p-4 space-y-2">
|
|
44
|
+
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
45
|
+
<DollarSign className="h-4 w-4" />
|
|
46
|
+
Average Monthly
|
|
47
|
+
</div>
|
|
48
|
+
<p className="text-2xl font-bold">
|
|
49
|
+
${avgRevenue.toLocaleString(undefined, { maximumFractionDigits: 0 })}
|
|
50
|
+
</p>
|
|
51
|
+
<div className="flex items-center gap-1 text-sm text-green-600">
|
|
52
|
+
<TrendingUp className="h-3 w-3" />
|
|
53
|
+
<span>+18.2% growth rate</span>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<div className="rounded-lg border p-4 space-y-2">
|
|
58
|
+
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
|
59
|
+
<DollarSign className="h-4 w-4" />
|
|
60
|
+
Current Month
|
|
61
|
+
</div>
|
|
62
|
+
<p className="text-2xl font-bold">
|
|
63
|
+
${revenueData[revenueData.length - 1].revenue.toLocaleString()}
|
|
64
|
+
</p>
|
|
65
|
+
<div className="flex items-center gap-1 text-sm text-green-600">
|
|
66
|
+
<TrendingUp className="h-3 w-3" />
|
|
67
|
+
<span>+8.0% from last month</span>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
<ChartContainer
|
|
73
|
+
config={{
|
|
74
|
+
revenue: {
|
|
75
|
+
label: 'Revenue',
|
|
76
|
+
color: 'hsl(var(--chart-1))',
|
|
77
|
+
},
|
|
78
|
+
expenses: {
|
|
79
|
+
label: 'Expenses',
|
|
80
|
+
color: 'hsl(var(--chart-2))',
|
|
81
|
+
},
|
|
82
|
+
}}
|
|
83
|
+
className="h-[400px]"
|
|
84
|
+
>
|
|
85
|
+
<ResponsiveContainer width="100%" height="100%">
|
|
86
|
+
<LineChart data={revenueData} margin={{ top: 5, right: 10, left: 10, bottom: 5 }}>
|
|
87
|
+
<CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
|
|
88
|
+
<XAxis
|
|
89
|
+
dataKey="month"
|
|
90
|
+
className="text-xs"
|
|
91
|
+
tick={{ fill: 'hsl(var(--muted-foreground))' }}
|
|
92
|
+
/>
|
|
93
|
+
<YAxis className="text-xs" tick={{ fill: 'hsl(var(--muted-foreground))' }} />
|
|
94
|
+
<ChartTooltip content={<ChartTooltipContent />} />
|
|
95
|
+
<Line
|
|
96
|
+
type="monotone"
|
|
97
|
+
dataKey="revenue"
|
|
98
|
+
stroke="var(--color-revenue)"
|
|
99
|
+
strokeWidth={2}
|
|
100
|
+
dot={{ fill: 'var(--color-revenue)', r: 4 }}
|
|
101
|
+
/>
|
|
102
|
+
<Line
|
|
103
|
+
type="monotone"
|
|
104
|
+
dataKey="expenses"
|
|
105
|
+
stroke="var(--color-expenses)"
|
|
106
|
+
strokeWidth={2}
|
|
107
|
+
dot={{ fill: 'var(--color-expenses)', r: 4 }}
|
|
108
|
+
/>
|
|
109
|
+
</LineChart>
|
|
110
|
+
</ResponsiveContainer>
|
|
111
|
+
</ChartContainer>
|
|
112
|
+
</CardContent>
|
|
113
|
+
</Card>
|
|
114
|
+
);
|
|
115
|
+
}
|