@spaceinvoices/react-ui 0.4.6 → 0.4.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/cli/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/components/advance-invoices/create/create-advance-invoice-form.tsx +60 -44
- package/src/components/credit-notes/create/create-credit-note-form.tsx +52 -42
- package/src/components/dashboard/collection-rate-card/use-collection-rate.ts +48 -92
- package/src/components/dashboard/invoice-status-chart/use-invoice-status.ts +48 -82
- package/src/components/dashboard/payment-methods-chart/use-payment-methods.ts +22 -31
- package/src/components/dashboard/payment-trend-chart/use-payment-trend.ts +33 -48
- package/src/components/dashboard/revenue-trend-chart/use-revenue-trend.ts +56 -76
- package/src/components/dashboard/shared/index.ts +1 -1
- package/src/components/dashboard/shared/use-revenue-data.ts +106 -182
- package/src/components/dashboard/shared/use-stats-counts.ts +18 -68
- package/src/components/dashboard/shared/use-stats-query.ts +35 -5
- package/src/components/dashboard/tax-collected-card/use-tax-collected.ts +57 -75
- package/src/components/dashboard/top-customers-chart/use-top-customers.ts +38 -49
- package/src/components/delivery-notes/create/create-delivery-note-form.tsx +3 -2
- package/src/components/documents/create/document-details-section.tsx +6 -4
- package/src/components/documents/create/document-recipient-section.tsx +30 -1
- package/src/components/documents/create/live-preview.tsx +15 -28
- package/src/components/documents/create/prepare-document-submission.ts +1 -0
- package/src/components/documents/create/use-document-customer-form.ts +4 -0
- package/src/components/documents/shared/document-preview-skeleton.tsx +63 -0
- package/src/components/documents/shared/index.ts +1 -0
- package/src/components/documents/view/document-actions-bar.tsx +29 -7
- package/src/components/entities/settings/tax-rules-settings-form.tsx +31 -13
- package/src/components/estimates/create/create-estimate-form.tsx +3 -2
- package/src/components/invoices/create/create-invoice-form.tsx +134 -62
- package/src/components/invoices/create/locales/de.ts +6 -0
- package/src/components/invoices/create/locales/es.ts +6 -0
- package/src/components/invoices/create/locales/fr.ts +6 -0
- package/src/components/invoices/create/locales/hr.ts +6 -0
- package/src/components/invoices/create/locales/it.ts +6 -0
- package/src/components/invoices/create/locales/nl.ts +6 -0
- package/src/components/invoices/create/locales/pl.ts +6 -0
- package/src/components/invoices/create/locales/pt.ts +6 -0
- package/src/components/invoices/create/locales/sl.ts +6 -0
- package/src/components/invoices/invoices.hooks.ts +1 -1
- package/src/components/ui/progress.tsx +27 -0
- package/src/generate-schemas.ts +15 -2
- package/src/generated/schemas/advanceinvoice.ts +2 -0
- package/src/generated/schemas/creditnote.ts +2 -0
- package/src/generated/schemas/customer.ts +2 -0
- package/src/generated/schemas/deliverynote.ts +2 -0
- package/src/generated/schemas/entity.ts +10 -0
- package/src/generated/schemas/estimate.ts +2 -0
- package/src/generated/schemas/finasettings.ts +4 -3
- package/src/generated/schemas/invoice.ts +2 -0
- package/src/generated/schemas/renderadvanceinvoicepreview_body.ts +16 -10
- package/src/generated/schemas/rendercreditnotepreview_body.ts +16 -10
- package/src/generated/schemas/renderdeliverynotepreview_body.ts +14 -7
- package/src/generated/schemas/renderestimatepreview_body.ts +14 -7
- package/src/generated/schemas/renderinvoicepreview_body.ts +16 -10
- package/src/generated/schemas/startpdfexport_body.ts +12 -17
- package/src/hooks/use-transaction-type-check.ts +152 -0
- package/src/hooks/use-vies-check.ts +7 -131
|
@@ -1,47 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Payment methods hook using the entity stats API.
|
|
3
3
|
* Server-side aggregation by payment type.
|
|
4
|
+
* Sends 1 query in a batch request.
|
|
4
5
|
*/
|
|
5
6
|
import type { StatsQueryDataItem } from "@spaceinvoices/js-sdk";
|
|
6
|
-
import {
|
|
7
|
-
import { useSDK } from "@/ui/providers/sdk-provider";
|
|
8
|
-
import { STATS_QUERY_CACHE_KEY } from "../shared/use-stats-query";
|
|
7
|
+
import { useStatsQuery } from "../shared/use-stats-query";
|
|
9
8
|
|
|
10
9
|
export const PAYMENT_METHODS_CACHE_KEY = "dashboard-payment-methods";
|
|
11
10
|
|
|
12
11
|
export type PaymentMethodsData = { type: string; count: number; amount: number }[];
|
|
13
12
|
|
|
14
13
|
export function usePaymentMethodsData(entityId: string | undefined) {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
{ type: "sum", field: "amount", alias: "amount" },
|
|
26
|
-
],
|
|
27
|
-
table: "payments",
|
|
28
|
-
group_by: ["type"],
|
|
29
|
-
order_by: [{ field: "amount", direction: "desc" }],
|
|
30
|
-
},
|
|
31
|
-
{ entity_id: entityId },
|
|
32
|
-
);
|
|
14
|
+
const query = useStatsQuery(
|
|
15
|
+
entityId,
|
|
16
|
+
{
|
|
17
|
+
metrics: [
|
|
18
|
+
{ type: "count", alias: "count" },
|
|
19
|
+
{ type: "sum", field: "amount", alias: "amount" },
|
|
20
|
+
],
|
|
21
|
+
table: "payments",
|
|
22
|
+
group_by: ["type"],
|
|
23
|
+
order_by: [{ field: "amount", direction: "desc" }],
|
|
33
24
|
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
25
|
+
{
|
|
26
|
+
select: (response) => {
|
|
27
|
+
const data = response.data || [];
|
|
28
|
+
return (data as StatsQueryDataItem[]).map((row) => ({
|
|
29
|
+
type: String(row.type || "other"),
|
|
30
|
+
count: Number(row.count) || 0,
|
|
31
|
+
amount: Number(row.amount) || 0,
|
|
32
|
+
}));
|
|
33
|
+
},
|
|
43
34
|
},
|
|
44
|
-
|
|
35
|
+
);
|
|
45
36
|
|
|
46
37
|
return {
|
|
47
38
|
data: query.data || [],
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Payment trend hook using the entity stats API.
|
|
3
3
|
* Server-side aggregation by month for accurate trend data.
|
|
4
|
+
* Sends 1 query in a batch request.
|
|
4
5
|
*/
|
|
5
6
|
import type { StatsQueryDataItem } from "@spaceinvoices/js-sdk";
|
|
6
|
-
import {
|
|
7
|
-
import { useSDK } from "@/ui/providers/sdk-provider";
|
|
8
|
-
import { STATS_QUERY_CACHE_KEY } from "../shared/use-stats-query";
|
|
7
|
+
import { useStatsQuery } from "../shared/use-stats-query";
|
|
9
8
|
|
|
10
9
|
export const PAYMENT_TREND_CACHE_KEY = "dashboard-payment-trend";
|
|
11
10
|
|
|
@@ -13,9 +12,7 @@ function getLastMonths(count: number): { months: string[]; startDate: string; en
|
|
|
13
12
|
const months: string[] = [];
|
|
14
13
|
const now = new Date();
|
|
15
14
|
|
|
16
|
-
// Start of the month 'count-1' months ago
|
|
17
15
|
const startDate = new Date(now.getFullYear(), now.getMonth() - (count - 1), 1);
|
|
18
|
-
// End of current month
|
|
19
16
|
const endDate = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
|
20
17
|
|
|
21
18
|
for (let i = count - 1; i >= 0; i--) {
|
|
@@ -33,56 +30,44 @@ function getLastMonths(count: number): { months: string[]; startDate: string; en
|
|
|
33
30
|
export type PaymentTrendData = { month: string; amount: number }[];
|
|
34
31
|
|
|
35
32
|
export function usePaymentTrendData(entityId: string | undefined) {
|
|
36
|
-
const { sdk } = useSDK();
|
|
37
|
-
|
|
38
33
|
const { months, startDate, endDate } = getLastMonths(6);
|
|
39
34
|
|
|
40
|
-
const query =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
date_to: endDate,
|
|
50
|
-
group_by: ["month", "currency_code"], // Include currency for display
|
|
51
|
-
order_by: [{ field: "month", direction: "asc" }],
|
|
52
|
-
},
|
|
53
|
-
{ entity_id: entityId },
|
|
54
|
-
);
|
|
35
|
+
const query = useStatsQuery(
|
|
36
|
+
entityId,
|
|
37
|
+
{
|
|
38
|
+
metrics: [{ type: "sum", field: "amount_converted", alias: "amount" }],
|
|
39
|
+
table: "payments",
|
|
40
|
+
date_from: startDate,
|
|
41
|
+
date_to: endDate,
|
|
42
|
+
group_by: ["month", "currency_code"],
|
|
43
|
+
order_by: [{ field: "month", direction: "asc" }],
|
|
55
44
|
},
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
for (const month of months) {
|
|
62
|
-
monthMap[month] = 0;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Fill in the actual amounts from the API response
|
|
66
|
-
// Sum up amounts per month (in case of multiple rows due to currency_code grouping)
|
|
67
|
-
const data = response.data || [];
|
|
68
|
-
let currency = "EUR";
|
|
69
|
-
for (const row of data as StatsQueryDataItem[]) {
|
|
70
|
-
const month = String(row.month);
|
|
71
|
-
if (month in monthMap) {
|
|
72
|
-
monthMap[month] += Number(row.amount) || 0;
|
|
45
|
+
{
|
|
46
|
+
select: (response) => {
|
|
47
|
+
const monthMap: Record<string, number> = {};
|
|
48
|
+
for (const month of months) {
|
|
49
|
+
monthMap[month] = 0;
|
|
73
50
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
51
|
+
|
|
52
|
+
const data = response.data || [];
|
|
53
|
+
let currency = "EUR";
|
|
54
|
+
for (const row of data as StatsQueryDataItem[]) {
|
|
55
|
+
const month = String(row.month);
|
|
56
|
+
if (month in monthMap) {
|
|
57
|
+
monthMap[month] += Number(row.amount) || 0;
|
|
58
|
+
}
|
|
59
|
+
if (row.currency_code && currency === "EUR") {
|
|
60
|
+
currency = String(row.currency_code);
|
|
61
|
+
}
|
|
77
62
|
}
|
|
78
|
-
}
|
|
79
63
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
64
|
+
return {
|
|
65
|
+
data: months.map((month) => ({ month, amount: monthMap[month] })),
|
|
66
|
+
currency,
|
|
67
|
+
};
|
|
68
|
+
},
|
|
84
69
|
},
|
|
85
|
-
|
|
70
|
+
);
|
|
86
71
|
|
|
87
72
|
return {
|
|
88
73
|
data: query.data?.data || [],
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Revenue trend hook using the entity stats API.
|
|
3
3
|
* Server-side aggregation by month for accurate trend data.
|
|
4
|
+
* Sends 2 queries in a single batch request.
|
|
4
5
|
*/
|
|
5
|
-
import type { StatsQueryDataItem } from "@spaceinvoices/js-sdk";
|
|
6
|
-
import {
|
|
7
|
-
import { useSDK } from "@/ui/providers/sdk-provider";
|
|
8
|
-
import { STATS_QUERY_CACHE_KEY } from "../shared/use-stats-query";
|
|
6
|
+
import type { StatsQueryDataItem, StatsQueryRequest } from "@spaceinvoices/js-sdk";
|
|
7
|
+
import { useStatsBatchQuery } from "../shared/use-stats-query";
|
|
9
8
|
|
|
10
9
|
export const REVENUE_TREND_CACHE_KEY = "dashboard-revenue-trend";
|
|
11
10
|
|
|
@@ -13,9 +12,7 @@ function getLastMonths(count: number): { months: string[]; startDate: string; en
|
|
|
13
12
|
const months: string[] = [];
|
|
14
13
|
const now = new Date();
|
|
15
14
|
|
|
16
|
-
// Start of the month 'count-1' months ago
|
|
17
15
|
const startDate = new Date(now.getFullYear(), now.getMonth() - (count - 1), 1);
|
|
18
|
-
// End of current month
|
|
19
16
|
const endDate = new Date(now.getFullYear(), now.getMonth() + 1, 0);
|
|
20
17
|
|
|
21
18
|
for (let i = count - 1; i >= 0; i--) {
|
|
@@ -33,11 +30,9 @@ function getLastMonths(count: number): { months: string[]; startDate: string; en
|
|
|
33
30
|
export type RevenueTrendData = { month: string; revenue: number }[];
|
|
34
31
|
|
|
35
32
|
export function useRevenueTrendData(entityId: string | undefined) {
|
|
36
|
-
const { sdk } = useSDK();
|
|
37
|
-
|
|
38
33
|
const { months, startDate, endDate } = getLastMonths(6);
|
|
39
34
|
|
|
40
|
-
const
|
|
35
|
+
const sharedParams = {
|
|
41
36
|
date_from: startDate,
|
|
42
37
|
date_to: endDate,
|
|
43
38
|
filters: { is_draft: false },
|
|
@@ -45,78 +40,63 @@ export function useRevenueTrendData(entityId: string | undefined) {
|
|
|
45
40
|
order_by: [{ field: "month", direction: "asc" as const }],
|
|
46
41
|
};
|
|
47
42
|
|
|
48
|
-
const queries =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
},
|
|
63
|
-
enabled: !!entityId && !!sdk,
|
|
64
|
-
staleTime: 120_000,
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
queryKey: [STATS_QUERY_CACHE_KEY, entityId, "cn-revenue-trend", startDate, endDate],
|
|
68
|
-
queryFn: async () => {
|
|
69
|
-
if (!entityId || !sdk) throw new Error("Missing entity or SDK");
|
|
70
|
-
return sdk.entityStats.queryEntityStats(
|
|
71
|
-
{
|
|
72
|
-
metrics: [{ type: "sum", field: "total_with_tax_converted", alias: "revenue" }],
|
|
73
|
-
table: "credit_notes",
|
|
74
|
-
...sharedQueryParams,
|
|
75
|
-
},
|
|
76
|
-
{ entity_id: entityId },
|
|
77
|
-
);
|
|
78
|
-
},
|
|
79
|
-
enabled: !!entityId && !!sdk,
|
|
80
|
-
staleTime: 120_000,
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
});
|
|
43
|
+
const queries: StatsQueryRequest[] = [
|
|
44
|
+
// [0] Invoice revenue by month
|
|
45
|
+
{
|
|
46
|
+
metrics: [{ type: "sum", field: "total_with_tax_converted", alias: "revenue" }],
|
|
47
|
+
table: "invoices",
|
|
48
|
+
...sharedParams,
|
|
49
|
+
},
|
|
50
|
+
// [1] Credit note revenue by month
|
|
51
|
+
{
|
|
52
|
+
metrics: [{ type: "sum", field: "total_with_tax_converted", alias: "revenue" }],
|
|
53
|
+
table: "credit_notes",
|
|
54
|
+
...sharedParams,
|
|
55
|
+
},
|
|
56
|
+
];
|
|
84
57
|
|
|
85
|
-
const
|
|
58
|
+
const { data: results, isLoading } = useStatsBatchQuery(entityId, "revenue-trend", queries, {
|
|
59
|
+
select: (batch) => {
|
|
60
|
+
// Build month maps
|
|
61
|
+
const monthMap: Record<string, number> = {};
|
|
62
|
+
const cnMonthMap: Record<string, number> = {};
|
|
63
|
+
for (const month of months) {
|
|
64
|
+
monthMap[month] = 0;
|
|
65
|
+
cnMonthMap[month] = 0;
|
|
66
|
+
}
|
|
86
67
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
68
|
+
// Fill invoice revenue per month
|
|
69
|
+
const invoiceData = (batch[0].data || []) as StatsQueryDataItem[];
|
|
70
|
+
let currency = "EUR";
|
|
71
|
+
for (const row of invoiceData) {
|
|
72
|
+
const month = String(row.month);
|
|
73
|
+
if (month in monthMap) {
|
|
74
|
+
monthMap[month] += Number(row.revenue) || 0;
|
|
75
|
+
}
|
|
76
|
+
if (row.quote_currency && currency === "EUR") {
|
|
77
|
+
currency = String(row.quote_currency);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
94
80
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
if (row.quote_currency && currency === "EUR") {
|
|
104
|
-
currency = String(row.quote_currency);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
81
|
+
// Fill credit note revenue per month
|
|
82
|
+
const cnData = (batch[1].data || []) as StatsQueryDataItem[];
|
|
83
|
+
for (const row of cnData) {
|
|
84
|
+
const month = String(row.month);
|
|
85
|
+
if (month in cnMonthMap) {
|
|
86
|
+
cnMonthMap[month] += Number(row.revenue) || 0;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
107
89
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
}
|
|
90
|
+
return {
|
|
91
|
+
data: months.map((month) => ({ month, revenue: monthMap[month] - cnMonthMap[month] })),
|
|
92
|
+
currency,
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
});
|
|
116
96
|
|
|
117
97
|
return {
|
|
118
|
-
data:
|
|
119
|
-
currency,
|
|
120
|
-
isLoading
|
|
98
|
+
data: results?.data || [],
|
|
99
|
+
currency: results?.currency || "EUR",
|
|
100
|
+
isLoading,
|
|
121
101
|
};
|
|
122
102
|
}
|
|
@@ -2,4 +2,4 @@ export type { RevenueData } from "./use-revenue-data";
|
|
|
2
2
|
export { REVENUE_DATA_CACHE_KEY, useRevenueData } from "./use-revenue-data";
|
|
3
3
|
export type { StatsCountsData } from "./use-stats-counts";
|
|
4
4
|
export { STATS_COUNTS_CACHE_KEY, useStatsCountsData } from "./use-stats-counts";
|
|
5
|
-
export { STATS_QUERY_CACHE_KEY, useStatsQuery } from "./use-stats-query";
|
|
5
|
+
export { STATS_QUERY_CACHE_KEY, useStatsBatchQuery, useStatsQuery } from "./use-stats-query";
|