@flowselections/offertes-installatie-techniek 1.0.2

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 (73) hide show
  1. package/README.md +24 -0
  2. package/dist-lib/_core-safelist.d.ts +2 -0
  3. package/dist-lib/_core-safelist.d.ts.map +1 -0
  4. package/dist-lib/_core-safelist.js +15 -0
  5. package/dist-lib/components/OfferteDetailPage.d.ts +6 -0
  6. package/dist-lib/components/OfferteDetailPage.d.ts.map +1 -0
  7. package/dist-lib/components/OfferteDetailPage.js +48 -0
  8. package/dist-lib/components/OffertesOverzichtPage.d.ts +2 -0
  9. package/dist-lib/components/OffertesOverzichtPage.d.ts.map +1 -0
  10. package/dist-lib/components/OffertesOverzichtPage.js +40 -0
  11. package/dist-lib/components/offertes/NieuweOfferteDialog.d.ts +8 -0
  12. package/dist-lib/components/offertes/NieuweOfferteDialog.d.ts.map +1 -0
  13. package/dist-lib/components/offertes/NieuweOfferteDialog.js +81 -0
  14. package/dist-lib/components/offertes/OfferteDetailPage.d.ts +6 -0
  15. package/dist-lib/components/offertes/OfferteDetailPage.d.ts.map +1 -0
  16. package/dist-lib/components/offertes/OfferteDetailPage.js +48 -0
  17. package/dist-lib/components/offertes/OfferteDetailRoute.d.ts +2 -0
  18. package/dist-lib/components/offertes/OfferteDetailRoute.d.ts.map +1 -0
  19. package/dist-lib/components/offertes/OfferteDetailRoute.js +13 -0
  20. package/dist-lib/components/offertes/OfferteKpiCards.d.ts +7 -0
  21. package/dist-lib/components/offertes/OfferteKpiCards.d.ts.map +1 -0
  22. package/dist-lib/components/offertes/OfferteKpiCards.js +33 -0
  23. package/dist-lib/components/offertes/OfferteRegelsEditor.d.ts +12 -0
  24. package/dist-lib/components/offertes/OfferteRegelsEditor.d.ts.map +1 -0
  25. package/dist-lib/components/offertes/OfferteRegelsEditor.js +27 -0
  26. package/dist-lib/components/offertes/OfferteStatusBadge.d.ts +4 -0
  27. package/dist-lib/components/offertes/OfferteStatusBadge.d.ts.map +1 -0
  28. package/dist-lib/components/offertes/OfferteStatusBadge.js +16 -0
  29. package/dist-lib/components/offertes/OffertesOverzichtPage.d.ts +2 -0
  30. package/dist-lib/components/offertes/OffertesOverzichtPage.d.ts.map +1 -0
  31. package/dist-lib/components/offertes/OffertesOverzichtPage.js +40 -0
  32. package/dist-lib/hooks/useOfferte.d.ts +17 -0
  33. package/dist-lib/hooks/useOfferte.d.ts.map +1 -0
  34. package/dist-lib/hooks/useOfferte.js +135 -0
  35. package/dist-lib/hooks/useOffertes.d.ts +7 -0
  36. package/dist-lib/hooks/useOffertes.d.ts.map +1 -0
  37. package/dist-lib/hooks/useOffertes.js +38 -0
  38. package/dist-lib/hooks/useWerkbonPakketten.d.ts +7 -0
  39. package/dist-lib/hooks/useWerkbonPakketten.d.ts.map +1 -0
  40. package/dist-lib/hooks/useWerkbonPakketten.js +20 -0
  41. package/dist-lib/index.d.ts +15 -0
  42. package/dist-lib/index.d.ts.map +1 -0
  43. package/dist-lib/index.js +32 -0
  44. package/dist-lib/integrations/supabase/auth-attacher.d.ts +2 -0
  45. package/dist-lib/integrations/supabase/auth-attacher.d.ts.map +1 -0
  46. package/dist-lib/integrations/supabase/auth-attacher.js +12 -0
  47. package/dist-lib/integrations/supabase/auth-middleware.d.ts +23409 -0
  48. package/dist-lib/integrations/supabase/auth-middleware.d.ts.map +1 -0
  49. package/dist-lib/integrations/supabase/auth-middleware.js +52 -0
  50. package/dist-lib/integrations/supabase/client.d.ts +23405 -0
  51. package/dist-lib/integrations/supabase/client.d.ts.map +1 -0
  52. package/dist-lib/integrations/supabase/client.js +14 -0
  53. package/dist-lib/integrations/supabase/client.server.d.ts +23405 -0
  54. package/dist-lib/integrations/supabase/client.server.d.ts.map +1 -0
  55. package/dist-lib/integrations/supabase/client.server.js +30 -0
  56. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts +6 -0
  57. package/dist-lib/integrations/supabase/previewAuthStorage.d.ts.map +1 -0
  58. package/dist-lib/integrations/supabase/previewAuthStorage.js +92 -0
  59. package/dist-lib/integrations/supabase/types.d.ts +24034 -0
  60. package/dist-lib/integrations/supabase/types.d.ts.map +1 -0
  61. package/dist-lib/integrations/supabase/types.js +92 -0
  62. package/dist-lib/lib/offertes.d.ts +86 -0
  63. package/dist-lib/lib/offertes.d.ts.map +1 -0
  64. package/dist-lib/lib/offertes.js +51 -0
  65. package/dist-lib/lib/utils.d.ts +3 -0
  66. package/dist-lib/lib/utils.d.ts.map +1 -0
  67. package/dist-lib/lib/utils.js +5 -0
  68. package/dist-lib/lib/validationSchemas.d.ts +15 -0
  69. package/dist-lib/lib/validationSchemas.d.ts.map +1 -0
  70. package/dist-lib/lib/validationSchemas.js +25 -0
  71. package/dist-lib/styles.css +1 -0
  72. package/package.json +92 -0
  73. package/public/logo.png +0 -0
@@ -0,0 +1,135 @@
1
+ // ============================================================================
2
+ // src/hooks/useOfferte.ts — detaildata en acties voor één offerte
3
+ // ============================================================================
4
+ import { useCallback, useEffect, useState } from "react";
5
+ import { supabase, toast } from "@flowselections/core";
6
+ const db = supabase;
7
+ export function useOfferte(offerteId) {
8
+ const [offerte, setOfferte] = useState(null);
9
+ const [klantNaam, setKlantNaam] = useState(null);
10
+ const [werkbonNummer, setWerkbonNummer] = useState(null);
11
+ const [regels, setRegels] = useState([]);
12
+ const [events, setEvents] = useState([]);
13
+ const [restantMandaat, setRestantMandaat] = useState(0);
14
+ const [loading, setLoading] = useState(true);
15
+ const load = useCallback(async () => {
16
+ setLoading(true);
17
+ try {
18
+ const { data, error } = await db
19
+ .from("itk_offertes")
20
+ .select("*, itk_customers(name)")
21
+ .eq("id", offerteId)
22
+ .maybeSingle();
23
+ if (error)
24
+ throw error;
25
+ if (!data) {
26
+ setOfferte(null);
27
+ return;
28
+ }
29
+ setOfferte(data);
30
+ setKlantNaam(data.itk_customers?.name ?? null);
31
+ setWerkbonNummer(data.source_number ?? null);
32
+ const [regelRes, eventRes] = await Promise.all([
33
+ db.from("itk_offerte_regels").select("*").eq("offerte_id", offerteId).order("sort_order"),
34
+ db
35
+ .from("itk_offerte_events")
36
+ .select("*")
37
+ .eq("offerte_id", offerteId)
38
+ .order("created_at", { ascending: false }),
39
+ ]);
40
+ setRegels(Array.isArray(regelRes.data) ? regelRes.data : []);
41
+ setEvents(Array.isArray(eventRes.data) ? eventRes.data : []);
42
+ const bronRef = data.source_ref ?? data.werkbon_id;
43
+ if (bronRef) {
44
+ const { data: restant } = await db.rpc("itk_offerte_restant_mandaat", {
45
+ _werkbon_id: bronRef,
46
+ _exclude_offerte_id: offerteId,
47
+ });
48
+ setRestantMandaat(typeof restant === "number" ? restant : 0);
49
+ }
50
+ else {
51
+ setRestantMandaat(0);
52
+ }
53
+ }
54
+ catch {
55
+ toast.error("Offerte kon niet worden geladen");
56
+ }
57
+ finally {
58
+ setLoading(false);
59
+ }
60
+ }, [offerteId]);
61
+ useEffect(() => {
62
+ load();
63
+ }, [load]);
64
+ const logEvent = useCallback(async (eventType, omschrijving) => {
65
+ await db.from("itk_offerte_events").insert({
66
+ offerte_id: offerteId,
67
+ event_type: eventType,
68
+ omschrijving,
69
+ });
70
+ }, [offerteId]);
71
+ const updateOfferte = useCallback(async (patch, eventType, eventTekst) => {
72
+ const { error } = await db.from("itk_offertes").update(patch).eq("id", offerteId);
73
+ if (error) {
74
+ toast.error("Opslaan mislukt");
75
+ return false;
76
+ }
77
+ if (eventType)
78
+ await logEvent(eventType, eventTekst ?? "");
79
+ await load();
80
+ return true;
81
+ }, [offerteId, load, logEvent]);
82
+ const addRegel = useCallback(async (regel) => {
83
+ const { error } = await db.from("itk_offerte_regels").insert({
84
+ offerte_id: offerteId,
85
+ sort_order: regels.length,
86
+ ...regel,
87
+ });
88
+ if (error) {
89
+ toast.error("Regel toevoegen mislukt");
90
+ return;
91
+ }
92
+ await load();
93
+ }, [offerteId, regels.length, load]);
94
+ const updateRegel = useCallback(async (id, patch) => {
95
+ const { error } = await db.from("itk_offerte_regels").update(patch).eq("id", id);
96
+ if (error) {
97
+ toast.error("Regel bijwerken mislukt");
98
+ return;
99
+ }
100
+ await load();
101
+ }, [load]);
102
+ const deleteRegel = useCallback(async (id) => {
103
+ const { error } = await db.from("itk_offerte_regels").delete().eq("id", id);
104
+ if (error) {
105
+ toast.error("Regel verwijderen mislukt");
106
+ return;
107
+ }
108
+ await load();
109
+ }, [load]);
110
+ const naarWerkbon = useCallback(async () => {
111
+ const { error } = await db.rpc("itk_offerte_naar_werkbon", { _offerte_id: offerteId });
112
+ if (error) {
113
+ toast.error("Omzetten naar werkbon mislukt");
114
+ return false;
115
+ }
116
+ toast.success("Vervolgwerkbon aangemaakt");
117
+ await load();
118
+ return true;
119
+ }, [offerteId, load]);
120
+ return {
121
+ offerte,
122
+ klantNaam,
123
+ werkbonNummer,
124
+ regels,
125
+ events,
126
+ restantMandaat,
127
+ loading,
128
+ reload: load,
129
+ updateOfferte,
130
+ addRegel,
131
+ updateRegel,
132
+ deleteRegel,
133
+ naarWerkbon,
134
+ };
135
+ }
@@ -0,0 +1,7 @@
1
+ import type { OfferteMetKlant } from "../lib/offertes";
2
+ export declare function useOffertes(): {
3
+ offertes: OfferteMetKlant[];
4
+ loading: boolean;
5
+ reload: () => Promise<void>;
6
+ };
7
+ //# sourceMappingURL=useOffertes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useOffertes.d.ts","sourceRoot":"","sources":["../../src/hooks/useOffertes.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAIvD,wBAAgB,WAAW;;;;EAmC1B"}
@@ -0,0 +1,38 @@
1
+ // ============================================================================
2
+ // src/hooks/useOffertes.ts — overzichtsdata voor de offertemodule
3
+ // ============================================================================
4
+ import { useCallback, useEffect, useState } from "react";
5
+ import { supabase, toast } from "@flowselections/core";
6
+ const db = supabase;
7
+ export function useOffertes() {
8
+ const [offertes, setOffertes] = useState([]);
9
+ const [loading, setLoading] = useState(true);
10
+ const load = useCallback(async () => {
11
+ setLoading(true);
12
+ try {
13
+ const { data, error } = await db
14
+ .from("itk_offertes")
15
+ .select("*, itk_customers(name)")
16
+ .order("created_at", { ascending: false });
17
+ if (error)
18
+ throw error;
19
+ const rows = Array.isArray(data) ? data : [];
20
+ setOffertes(rows.map((row) => ({
21
+ ...row,
22
+ klant_naam: row.itk_customers?.name ?? null,
23
+ werkbon_nummer: row.source_number ?? null,
24
+ })));
25
+ }
26
+ catch {
27
+ toast.error("Offertes konden niet worden geladen");
28
+ setOffertes([]);
29
+ }
30
+ finally {
31
+ setLoading(false);
32
+ }
33
+ }, []);
34
+ useEffect(() => {
35
+ load();
36
+ }, [load]);
37
+ return { offertes, loading, reload: load };
38
+ }
@@ -0,0 +1,7 @@
1
+ import type { Pakket } from "../lib/offertes";
2
+ export declare function useWerkbonPakketten(): {
3
+ pakketten: Pakket[];
4
+ loading: boolean;
5
+ reload: () => Promise<void>;
6
+ };
7
+ //# sourceMappingURL=useWerkbonPakketten.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWerkbonPakketten.d.ts","sourceRoot":"","sources":["../../src/hooks/useWerkbonPakketten.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAI9C,wBAAgB,mBAAmB;;;;EAgBlC"}
@@ -0,0 +1,20 @@
1
+ // ============================================================================
2
+ // src/hooks/useWerkbonPakketten.ts — pakketten via het broncontract (RPC)
3
+ // ============================================================================
4
+ import { useCallback, useEffect, useState } from "react";
5
+ import { supabase } from "@flowselections/core";
6
+ const db = supabase;
7
+ export function useWerkbonPakketten() {
8
+ const [pakketten, setPakketten] = useState([]);
9
+ const [loading, setLoading] = useState(true);
10
+ const load = useCallback(async () => {
11
+ setLoading(true);
12
+ const { data } = await db.rpc("quote_list_packages");
13
+ setPakketten(Array.isArray(data) ? data : []);
14
+ setLoading(false);
15
+ }, []);
16
+ useEffect(() => {
17
+ load();
18
+ }, [load]);
19
+ return { pakketten, loading, reload: load };
20
+ }
@@ -0,0 +1,15 @@
1
+ import type { FlowModule } from "@flowselections/core";
2
+ export * from "./_core-safelist";
3
+ export * from "./lib/offertes";
4
+ export { OffertesOverzichtPage } from "./components/offertes/OffertesOverzichtPage";
5
+ export { OfferteDetailPage } from "./components/offertes/OfferteDetailPage";
6
+ export { OfferteDetailRoute } from "./components/offertes/OfferteDetailRoute";
7
+ export { OfferteStatusBadge } from "./components/offertes/OfferteStatusBadge";
8
+ export { OfferteKpiCards } from "./components/offertes/OfferteKpiCards";
9
+ export { OfferteRegelsEditor } from "./components/offertes/OfferteRegelsEditor";
10
+ export { NieuweOfferteDialog } from "./components/offertes/NieuweOfferteDialog";
11
+ export { useOffertes } from "./hooks/useOffertes";
12
+ export { useOfferte } from "./hooks/useOfferte";
13
+ export { useWerkbonPakketten } from "./hooks/useWerkbonPakketten";
14
+ export declare const offertesInstallatieTechniekModule: FlowModule;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAE/B,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA6C,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAC9E,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAEhF,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAElE,eAAO,MAAM,iCAAiC,EAAE,UAa/C,CAAC"}
@@ -0,0 +1,32 @@
1
+ // ============================================================================
2
+ // src/index.ts — MODULE CONTRACT
3
+ // ============================================================================
4
+ // De shell leest dit bestand voor het nav-item, de settingskaarten en de
5
+ // identiteit van de module. Pagina's worden als expliciete named exports
6
+ // geëxporteerd zodat de shell-configurator ze kan detecteren.
7
+ // ============================================================================
8
+ import { FileText, List } from "lucide-react";
9
+ export * from "./_core-safelist";
10
+ export * from "./lib/offertes";
11
+ export { OffertesOverzichtPage } from "./components/offertes/OffertesOverzichtPage";
12
+ export { OfferteDetailPage } from "./components/offertes/OfferteDetailPage";
13
+ export { OfferteDetailRoute } from "./components/offertes/OfferteDetailRoute";
14
+ export { OfferteStatusBadge } from "./components/offertes/OfferteStatusBadge";
15
+ export { OfferteKpiCards } from "./components/offertes/OfferteKpiCards";
16
+ export { OfferteRegelsEditor } from "./components/offertes/OfferteRegelsEditor";
17
+ export { NieuweOfferteDialog } from "./components/offertes/NieuweOfferteDialog";
18
+ export { useOffertes } from "./hooks/useOffertes";
19
+ export { useOfferte } from "./hooks/useOfferte";
20
+ export { useWerkbonPakketten } from "./hooks/useWerkbonPakketten";
21
+ export const offertesInstallatieTechniekModule = {
22
+ id: "offertes-installatietechniek",
23
+ name: "Offertes Installatie Techniek",
24
+ version: "1.0.0",
25
+ nav: {
26
+ label: "Offertes",
27
+ href: "/offertes",
28
+ icon: FileText,
29
+ children: [{ label: "Overzicht", href: "/offertes", icon: List }],
30
+ },
31
+ settingsCards: [],
32
+ };
@@ -0,0 +1,2 @@
1
+ export declare const attachSupabaseAuth: import("@tanstack/start-client-core").FunctionMiddlewareAfterClient<{}, unknown, undefined, undefined, undefined>;
2
+ //# sourceMappingURL=auth-attacher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-attacher.d.ts","sourceRoot":"","sources":["../../../src/integrations/supabase/auth-attacher.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,kBAAkB,mHAQ9B,CAAA"}
@@ -0,0 +1,12 @@
1
+ // This file is automatically generated. Do not edit it directly.
2
+ import { createMiddleware } from '@tanstack/react-start';
3
+ import { supabase } from './client';
4
+ // Must be registered as a global `functionMiddleware` in `src/start.ts`; otherwise
5
+ // the browser never attaches the bearer token to serverFn RPCs.
6
+ export const attachSupabaseAuth = createMiddleware({ type: 'function' }).client(async ({ next }) => {
7
+ const { data } = await supabase.auth.getSession();
8
+ const token = data.session?.access_token;
9
+ return next({
10
+ headers: token ? { Authorization: `Bearer ${token}` } : {},
11
+ });
12
+ });