ptechcore_ui 1.0.29 → 1.0.31

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/dist/index.cjs CHANGED
@@ -39,7 +39,10 @@ __export(index_exports, {
39
39
  AuthServices: () => AuthServices,
40
40
  CHOICES: () => Choices_default,
41
41
  CountrySelector: () => CountrySelector,
42
+ DataTable: () => DataTable,
42
43
  DateInput: () => DateInput,
44
+ DocumentFooter: () => DocumentFooter,
45
+ DocumentHeader: () => DocumentHeader,
43
46
  EntityFileManager: () => EntityFileManager,
44
47
  FDrawer: () => FDrawer,
45
48
  FetchApi: () => FetchApi,
@@ -47,14 +50,18 @@ __export(index_exports, {
47
50
  FileManager: () => FileManager,
48
51
  FileManagerProvider: () => FileManagerProvider,
49
52
  ForeignCurrencySelector: () => ForeignCurrencySelector,
53
+ InfoBox: () => InfoBox,
50
54
  InputField: () => InputField,
51
55
  InvoiceTypeSelector: () => InvoiceTypeSelector,
52
56
  LegalFormSelector: () => LegalFormSelector,
53
57
  Modal: () => Modals_default,
54
58
  NumberInput: () => NumberInput,
59
+ PRINT_GREEN: () => PRINT_GREEN,
55
60
  Pages: () => Pages_default,
56
61
  PaymentMethodSelector: () => PaymentMethodSelector,
57
62
  PrimaryButton: () => Buttons_default,
63
+ PrintPreview: () => PrintPreview,
64
+ PrintableDocument: () => PrintableDocument,
58
65
  RewiseLayout: () => ModernDoubleSidebarLayout_default,
59
66
  SecondaryButton: () => SecondaryButton,
60
67
  SelectCostCenter: () => SelectCostCenter,
@@ -64,18 +71,23 @@ __export(index_exports, {
64
71
  SelectUser: () => SelectUser,
65
72
  SelectVendor: () => SelectVendor,
66
73
  SessionProvider: () => SessionProvider,
74
+ SignatureSection: () => SignatureSection,
67
75
  TaxSelector: () => TaxSelector,
68
76
  TemplateFNESelector: () => TemplateFNESelector,
69
77
  TextInput: () => TextInput,
70
78
  ThemeProvider: () => ThemeContext_default,
71
79
  ToastContainer: () => Toast_default,
72
80
  ToastProvider: () => ToastProvider,
81
+ TotalsSection: () => TotalsSection,
73
82
  UnitServices: () => UnitServices,
74
83
  UserServices: () => UserServices,
75
84
  fileManagerApi: () => fileManagerApi,
85
+ formatCurrency: () => formatCurrency,
76
86
  formatDate: () => formatDate,
87
+ formatDateFR: () => formatDateFR,
77
88
  formatFileSize: () => formatFileSize,
78
89
  getFileIcon: () => getFileIcon,
90
+ numberToWords: () => numberToWords,
79
91
  useAlert: () => useAlert,
80
92
  useFileManager: () => useFileManager,
81
93
  useFileManagerApi: () => useFileManagerApi,
@@ -886,6 +898,7 @@ var AuthServices = {
886
898
  addUser: (payload) => FetchApi.post(`${API_BASE_URL}add-user/`, payload),
887
899
  login: (payload) => FetchApi.post(`${API_BASE_URL}login/`, payload),
888
900
  getUserInformations: (token) => FetchApi.get(`${API_BASE_URL}user-informations/`, token),
901
+ getUserInformationsByOldId: (id) => FetchApi.get(`${API_BASE_URL}user-informations-by-old-id/${id}/`),
889
902
  logout: () => FetchApi.post(`${API_BASE_URL}logout/`)
890
903
  };
891
904
 
@@ -929,13 +942,31 @@ var SessionProvider = ({ children }) => {
929
942
  const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
930
943
  const [showAuthModal, setShowAuthModal] = (0, import_react2.useState)(false);
931
944
  (0, import_react2.useEffect)(() => {
932
- const params = new URLSearchParams(window.location.search);
933
- const tkn = params.get("tkn");
934
- if (tkn) {
935
- localStorage.setItem("token", tkn);
936
- setToken(tkn);
937
- window.history.replaceState({}, document.title, window.location.pathname);
938
- }
945
+ const initializeSession = async () => {
946
+ const params = new URLSearchParams(window.location.search);
947
+ const tkn = params.get("tkn");
948
+ if (tkn) {
949
+ localStorage.setItem("token", tkn);
950
+ setToken(tkn);
951
+ window.history.replaceState({}, document.title, window.location.pathname);
952
+ }
953
+ const old_rewise_user_id = params.get("rewise_user_id");
954
+ if (old_rewise_user_id) {
955
+ try {
956
+ const res = await AuthServices.getUserInformationsByOldId(parseInt(old_rewise_user_id));
957
+ const result = res;
958
+ if (result.success === true) {
959
+ setLoggedUser(result.data.user);
960
+ setActiveBusinessEntity(
961
+ result.data.user.centers_access.find((item) => parseInt(String(item.id)) === parseInt(saved_center_id)) || result.data.user.centers_access[0] || null
962
+ );
963
+ }
964
+ } catch (error) {
965
+ console.error("Failed to refresh session:", error);
966
+ }
967
+ }
968
+ };
969
+ initializeSession();
939
970
  }, []);
940
971
  const [vendors, setVendors] = (0, import_react2.useState)(() => {
941
972
  const cacheKey = `vendors_cache_${activeBusinessEntity?.id || "default"}`;
@@ -5915,30 +5946,57 @@ var MinimalVendorForm = ({
5915
5946
  open: isOpen,
5916
5947
  onClose,
5917
5948
  children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("form", { onSubmit: handleSubmit, className: "p-", children: [
5918
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "space-y-4", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
5919
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5920
- TextInput,
5921
- {
5922
- label: "Raison sociale",
5923
- name: "legal_name",
5924
- value: formData.legal_name || "",
5925
- placeholder: "Nom l\xE9gal de l'entit\xE9",
5926
- required: true,
5927
- error: errors.legal_name,
5928
- onChange: handleInputChange
5929
- }
5930
- ),
5931
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5932
- TextInput,
5933
- {
5934
- label: "Nom commercial",
5935
- name: "trading_name",
5936
- value: formData.trading_name || "",
5937
- placeholder: "Nom commercial (optionnel)",
5938
- onChange: handleInputChange
5939
- }
5940
- )
5941
- ] }) }),
5949
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-4", children: [
5950
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
5951
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5952
+ TextInput,
5953
+ {
5954
+ label: "Raison sociale",
5955
+ name: "legal_name",
5956
+ value: formData.legal_name || "",
5957
+ placeholder: "Nom l\xE9gal de l'entit\xE9",
5958
+ required: true,
5959
+ error: errors.legal_name,
5960
+ onChange: handleInputChange
5961
+ }
5962
+ ),
5963
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5964
+ TextInput,
5965
+ {
5966
+ label: "Nom commercial",
5967
+ name: "trading_name",
5968
+ value: formData.trading_name || "",
5969
+ placeholder: "Nom commercial (optionnel)",
5970
+ onChange: handleInputChange
5971
+ }
5972
+ )
5973
+ ] }),
5974
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [
5975
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5976
+ InputField,
5977
+ {
5978
+ label: "T\xE9l\xE9phone",
5979
+ name: "phone",
5980
+ type: "tel",
5981
+ value: formData.phone || "",
5982
+ placeholder: "+33 1 23 45 67 89",
5983
+ onChange: handleInputChange
5984
+ }
5985
+ ),
5986
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5987
+ InputField,
5988
+ {
5989
+ label: "Email",
5990
+ name: "email",
5991
+ type: "email",
5992
+ value: formData.email || "",
5993
+ placeholder: "contact@entite.com",
5994
+ error: errors.email,
5995
+ onChange: handleInputChange
5996
+ }
5997
+ )
5998
+ ] })
5999
+ ] }),
5942
6000
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex justify-between pt-6 mt-8", children: [
5943
6001
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
5944
6002
  "button",
@@ -5955,7 +6013,7 @@ var MinimalVendorForm = ({
5955
6013
  type: "button",
5956
6014
  onClick: handleSubmit,
5957
6015
  disabled: loading,
5958
- children: loading ? "chargement..." : "Enregistrer l'entit\xE9"
6016
+ children: loading ? "chargement..." : "Enregistrer le fournisseur"
5959
6017
  }
5960
6018
  )
5961
6019
  ] })
@@ -8367,6 +8425,380 @@ var EntityFileManager = ({
8367
8425
  }
8368
8426
  ) });
8369
8427
  };
8428
+
8429
+ // src/components/common/PrintPreview.tsx
8430
+ var import_react23 = __toESM(require("react"), 1);
8431
+ var import_react_to_print = require("react-to-print");
8432
+ var import_lucide_react18 = require("lucide-react");
8433
+ var import_jsx_runtime30 = require("react/jsx-runtime");
8434
+ var PrintableDocument = ({
8435
+ children,
8436
+ className = "",
8437
+ style = {}
8438
+ }) => {
8439
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8440
+ "div",
8441
+ {
8442
+ className: `bg-white text-gray-900 ${className}`,
8443
+ style: {
8444
+ fontFamily: "Arial, sans-serif",
8445
+ fontSize: "11px",
8446
+ ...style
8447
+ },
8448
+ children
8449
+ }
8450
+ );
8451
+ };
8452
+ var PrintPreview = ({
8453
+ children,
8454
+ isOpen,
8455
+ onClose,
8456
+ title = "Aper\xE7u avant impression",
8457
+ documentName = "document",
8458
+ pageWidth = "210mm",
8459
+ pageMinHeight = "297mm",
8460
+ orientation = "portrait",
8461
+ onAfterPrint,
8462
+ onBeforePrint
8463
+ }) => {
8464
+ const printRef = (0, import_react23.useRef)(null);
8465
+ const [zoom, setZoom] = import_react23.default.useState(100);
8466
+ const handlePrint = (0, import_react_to_print.useReactToPrint)({
8467
+ contentRef: printRef,
8468
+ documentTitle: documentName,
8469
+ onAfterPrint: () => {
8470
+ onAfterPrint?.();
8471
+ },
8472
+ onBeforePrint
8473
+ });
8474
+ const handleZoomIn = () => {
8475
+ setZoom((prev) => Math.min(prev + 10, 150));
8476
+ };
8477
+ const handleZoomOut = () => {
8478
+ setZoom((prev) => Math.max(prev - 10, 50));
8479
+ };
8480
+ if (!isOpen) return null;
8481
+ const pageStyles = {
8482
+ width: orientation === "portrait" ? pageWidth : pageMinHeight,
8483
+ minHeight: orientation === "portrait" ? pageMinHeight : pageWidth,
8484
+ transform: `scale(${zoom / 100})`,
8485
+ transformOrigin: "top center",
8486
+ transition: "transform 0.2s ease"
8487
+ };
8488
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "fixed inset-0 z-50 overflow-hidden print:hidden", children: [
8489
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8490
+ "div",
8491
+ {
8492
+ className: "absolute inset-0 bg-black/60 backdrop-blur-sm",
8493
+ onClick: onClose
8494
+ }
8495
+ ),
8496
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8497
+ "button",
8498
+ {
8499
+ onClick: onClose,
8500
+ className: "absolute top-4 right-4 z-20 p-2 bg-white/90 hover:bg-white rounded-full shadow-lg transition-colors",
8501
+ title: "Fermer",
8502
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react18.X, { className: "w-5 h-5 text-gray-600" })
8503
+ }
8504
+ ),
8505
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "relative h-full flex items-center justify-center p-8", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex items-start gap-4 max-h-full", children: [
8506
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "overflow-auto max-h-[90vh] bg-transparent", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8507
+ "div",
8508
+ {
8509
+ ref: printRef,
8510
+ className: "bg-white shadow-2xl",
8511
+ style: pageStyles,
8512
+ children
8513
+ }
8514
+ ) }),
8515
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-2 bg-white rounded-lg shadow-lg p-2", children: [
8516
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
8517
+ "button",
8518
+ {
8519
+ onClick: () => handlePrint(),
8520
+ className: "p-3 hover:bg-gray-100 rounded-lg transition-colors flex flex-col items-center gap-1 group",
8521
+ title: "Imprimer / PDF",
8522
+ children: [
8523
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react18.FileText, { className: "w-6 h-6 text-gray-600 group-hover:text-blue-600" }),
8524
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("span", { className: "text-[10px] text-gray-500 group-hover:text-blue-600", children: "PDF" })
8525
+ ]
8526
+ }
8527
+ ),
8528
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "border-t border-gray-200 my-1" }),
8529
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8530
+ "button",
8531
+ {
8532
+ onClick: () => handlePrint(),
8533
+ className: "p-3 hover:bg-gray-100 rounded-lg transition-colors flex flex-col items-center gap-1 group",
8534
+ title: "T\xE9l\xE9charger",
8535
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react18.Download, { className: "w-6 h-6 text-gray-600 group-hover:text-blue-600" })
8536
+ }
8537
+ ),
8538
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "border-t border-gray-200 my-1" }),
8539
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8540
+ "button",
8541
+ {
8542
+ onClick: handleZoomIn,
8543
+ className: "p-3 hover:bg-gray-100 rounded-lg transition-colors",
8544
+ title: "Zoom avant",
8545
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react18.ZoomIn, { className: "w-5 h-5 text-gray-600" })
8546
+ }
8547
+ ),
8548
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "text-xs text-gray-500 text-center py-1", children: [
8549
+ zoom,
8550
+ "%"
8551
+ ] }),
8552
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8553
+ "button",
8554
+ {
8555
+ onClick: handleZoomOut,
8556
+ className: "p-3 hover:bg-gray-100 rounded-lg transition-colors",
8557
+ title: "Zoom arri\xE8re",
8558
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react18.ZoomOut, { className: "w-5 h-5 text-gray-600" })
8559
+ }
8560
+ )
8561
+ ] })
8562
+ ] }) })
8563
+ ] });
8564
+ };
8565
+ var PRINT_GREEN = "#2d7d46";
8566
+ var DocumentHeader = ({
8567
+ companyName,
8568
+ address,
8569
+ phone,
8570
+ email,
8571
+ website,
8572
+ documentTitle,
8573
+ documentNumber,
8574
+ date,
8575
+ extraInfo = []
8576
+ }) => {
8577
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex justify-between items-start mb-6 p-8 pb-0", children: [
8578
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex-1", children: [
8579
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "mb-2", children: [
8580
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8581
+ "h1",
8582
+ {
8583
+ className: "text-xl font-bold tracking-wider text-gray-800",
8584
+ style: { letterSpacing: "0.15em" },
8585
+ children: companyName.toUpperCase()
8586
+ }
8587
+ ),
8588
+ address && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-xs text-gray-600 mt-1", children: address })
8589
+ ] }),
8590
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "text-xs text-gray-600 space-y-0.5 mt-3", children: [
8591
+ phone && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { children: phone }),
8592
+ email && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { children: email }),
8593
+ website && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { children: website })
8594
+ ] })
8595
+ ] }),
8596
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "text-right", children: [
8597
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8598
+ "h2",
8599
+ {
8600
+ className: "text-4xl font-bold mb-4",
8601
+ style: { color: PRINT_GREEN },
8602
+ children: documentTitle
8603
+ }
8604
+ ),
8605
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("table", { className: "ml-auto text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("tbody", { children: [
8606
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("tr", { children: [
8607
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("td", { className: "text-gray-600 pr-4 py-0.5", children: "Date" }),
8608
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("td", { className: "font-medium border-b border-gray-300 pl-2 py-0.5", children: date })
8609
+ ] }),
8610
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("tr", { children: [
8611
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("td", { className: "text-gray-600 pr-4 py-0.5", children: "N\xB0" }),
8612
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("td", { className: "font-medium border-b border-gray-300 pl-2 py-0.5", children: documentNumber })
8613
+ ] }),
8614
+ extraInfo.map((info, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("tr", { children: [
8615
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("td", { className: "text-gray-600 pr-4 py-0.5", children: info.label }),
8616
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("td", { className: "font-medium border-b border-gray-300 pl-2 py-0.5", children: info.value })
8617
+ ] }, index))
8618
+ ] }) })
8619
+ ] })
8620
+ ] });
8621
+ };
8622
+ var InfoBox = ({
8623
+ title,
8624
+ children,
8625
+ variant = "green"
8626
+ }) => {
8627
+ const headerBg = variant === "green" ? PRINT_GREEN : "#6b7280";
8628
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
8629
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8630
+ "div",
8631
+ {
8632
+ className: "text-white text-xs font-semibold py-1.5 px-3 rounded-t",
8633
+ style: { backgroundColor: headerBg },
8634
+ children: title
8635
+ }
8636
+ ),
8637
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "border border-gray-300 border-t-0 p-3 min-h-[80px]", children })
8638
+ ] });
8639
+ };
8640
+ function DataTable({
8641
+ columns,
8642
+ data,
8643
+ minEmptyRows = 0,
8644
+ keyExtractor
8645
+ }) {
8646
+ const emptyRowsCount = Math.max(0, minEmptyRows - data.length);
8647
+ const getNestedValue = (obj, path) => {
8648
+ return path.split(".").reduce((acc, part) => acc && acc[part], obj);
8649
+ };
8650
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("table", { className: "w-full border-collapse", children: [
8651
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("tr", { style: { backgroundColor: PRINT_GREEN }, children: columns.map((col, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8652
+ "th",
8653
+ {
8654
+ className: "text-white text-xs font-semibold py-2 px-2 border border-gray-400",
8655
+ style: {
8656
+ width: col.width,
8657
+ textAlign: col.align || "left"
8658
+ },
8659
+ children: col.header
8660
+ },
8661
+ index
8662
+ )) }) }),
8663
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("tbody", { children: [
8664
+ data.map((item, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("tr", { className: "border-b border-gray-300", children: columns.map((col, colIndex) => {
8665
+ const value = typeof col.key === "string" ? getNestedValue(item, col.key) : item[col.key];
8666
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8667
+ "td",
8668
+ {
8669
+ className: "py-2 px-2 text-xs text-gray-900 border-l border-r border-gray-300",
8670
+ style: { textAlign: col.align || "left" },
8671
+ children: col.render ? col.render(value, item, rowIndex) : value
8672
+ },
8673
+ colIndex
8674
+ );
8675
+ }) }, keyExtractor(item, rowIndex))),
8676
+ Array.from({ length: emptyRowsCount }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("tr", { className: "border-b border-gray-300", children: columns.map((_2, colIndex) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8677
+ "td",
8678
+ {
8679
+ className: "py-2 px-2 border-l border-r border-gray-300",
8680
+ children: "\xA0"
8681
+ },
8682
+ colIndex
8683
+ )) }, `empty-${index}`))
8684
+ ] })
8685
+ ] });
8686
+ }
8687
+ var TotalsSection = ({
8688
+ rows,
8689
+ amountInWords
8690
+ }) => {
8691
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "w-64", children: [
8692
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("table", { className: "w-full text-xs", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("tbody", { children: rows.map((row, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
8693
+ "tr",
8694
+ {
8695
+ className: row.isTotal ? "" : "border-b border-gray-200",
8696
+ children: [
8697
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8698
+ "td",
8699
+ {
8700
+ className: `py-1.5 px-2 ${row.isTotal ? "font-semibold text-gray-900" : "text-gray-600"}`,
8701
+ children: row.label
8702
+ }
8703
+ ),
8704
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
8705
+ "td",
8706
+ {
8707
+ className: `py-1.5 px-2 text-right font-medium`,
8708
+ style: row.isTotal ? {
8709
+ backgroundColor: PRINT_GREEN,
8710
+ color: "white",
8711
+ fontWeight: "bold"
8712
+ } : { color: row.valueColor },
8713
+ children: row.value
8714
+ }
8715
+ )
8716
+ ]
8717
+ },
8718
+ index
8719
+ )) }) }),
8720
+ amountInWords && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "mt-2 text-xs text-gray-600 italic text-center px-2", children: amountInWords })
8721
+ ] });
8722
+ };
8723
+ var SignatureSection = ({
8724
+ date,
8725
+ leftLabel = "Signature Client",
8726
+ rightLabel = "Cachet et signature",
8727
+ rightName
8728
+ }) => {
8729
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "grid grid-cols-2 gap-8 mt-12 pt-4 px-8", children: [
8730
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { children: [
8731
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-xs text-gray-600 mb-1", children: "Date:" }),
8732
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "border-b border-gray-400 w-32 mb-4 text-xs", children: date || "" }),
8733
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("p", { className: "text-xs text-gray-600 mb-1", children: [
8734
+ leftLabel,
8735
+ ":"
8736
+ ] }),
8737
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "h-16 border-b border-gray-400 w-48" })
8738
+ ] }),
8739
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "text-right", children: [
8740
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-xs text-gray-600 mb-2", children: rightLabel }),
8741
+ rightName && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-xs font-medium text-gray-900 mb-2", children: rightName }),
8742
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "inline-block border-2 border-dashed border-gray-300 rounded-full w-24 h-24" })
8743
+ ] })
8744
+ ] });
8745
+ };
8746
+ var DocumentFooter = ({ lines }) => {
8747
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "mt-8 pt-3 border-t border-gray-300 text-center text-xs text-gray-500 px-8 pb-8", children: lines.map((line, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { children: line }, index)) });
8748
+ };
8749
+ var numberToWords = (num) => {
8750
+ if (num === 0) return "z\xE9ro";
8751
+ const units = ["", "un", "deux", "trois", "quatre", "cinq", "six", "sept", "huit", "neuf", "dix", "onze", "douze", "treize", "quatorze", "quinze", "seize", "dix-sept", "dix-huit", "dix-neuf"];
8752
+ const tens = ["", "", "vingt", "trente", "quarante", "cinquante", "soixante", "soixante", "quatre-vingt", "quatre-vingt"];
8753
+ const convertHundreds = (n) => {
8754
+ if (n < 20) return units[n];
8755
+ if (n < 100) {
8756
+ const ten = Math.floor(n / 10);
8757
+ const unit = n % 10;
8758
+ if (ten === 7 || ten === 9) {
8759
+ return tens[ten] + "-" + units[10 + unit];
8760
+ }
8761
+ return tens[ten] + (unit ? "-" + units[unit] : ten === 8 ? "s" : "");
8762
+ }
8763
+ const hundred = Math.floor(n / 100);
8764
+ const rest = n % 100;
8765
+ return (hundred === 1 ? "cent" : units[hundred] + " cent") + (rest ? " " + convertHundreds(rest) : hundred > 1 && rest === 0 ? "s" : "");
8766
+ };
8767
+ const convertThousands = (n) => {
8768
+ if (n < 1e3) return convertHundreds(n);
8769
+ const thousands = Math.floor(n / 1e3);
8770
+ const rest = n % 1e3;
8771
+ return (thousands === 1 ? "mille" : convertHundreds(thousands) + " mille") + (rest ? " " + convertHundreds(rest) : "");
8772
+ };
8773
+ const convertMillions = (n) => {
8774
+ if (n < 1e6) return convertThousands(n);
8775
+ const millions = Math.floor(n / 1e6);
8776
+ const rest = n % 1e6;
8777
+ return convertHundreds(millions) + " million" + (millions > 1 ? "s" : "") + (rest ? " " + convertThousands(rest) : "");
8778
+ };
8779
+ return convertMillions(Math.floor(num));
8780
+ };
8781
+ var formatDateFR = (date, format = "short") => {
8782
+ const d = typeof date === "string" ? new Date(date) : date;
8783
+ if (format === "short") {
8784
+ return d.toLocaleDateString("fr-FR", {
8785
+ day: "2-digit",
8786
+ month: "2-digit",
8787
+ year: "numeric"
8788
+ });
8789
+ }
8790
+ return d.toLocaleDateString("fr-FR", {
8791
+ day: "numeric",
8792
+ month: "long",
8793
+ year: "numeric"
8794
+ });
8795
+ };
8796
+ var formatCurrency = (amount, currency = "XOF", showDecimals = false) => {
8797
+ return amount.toLocaleString("fr-FR", {
8798
+ minimumFractionDigits: showDecimals ? 2 : 0,
8799
+ maximumFractionDigits: showDecimals ? 2 : 0
8800
+ }) + (currency ? ` ${currency}` : "");
8801
+ };
8370
8802
  // Annotate the CommonJS export names for ESM import in node:
8371
8803
  0 && (module.exports = {
8372
8804
  Alert,
@@ -8379,7 +8811,10 @@ var EntityFileManager = ({
8379
8811
  AuthServices,
8380
8812
  CHOICES,
8381
8813
  CountrySelector,
8814
+ DataTable,
8382
8815
  DateInput,
8816
+ DocumentFooter,
8817
+ DocumentHeader,
8383
8818
  EntityFileManager,
8384
8819
  FDrawer,
8385
8820
  FetchApi,
@@ -8387,14 +8822,18 @@ var EntityFileManager = ({
8387
8822
  FileManager,
8388
8823
  FileManagerProvider,
8389
8824
  ForeignCurrencySelector,
8825
+ InfoBox,
8390
8826
  InputField,
8391
8827
  InvoiceTypeSelector,
8392
8828
  LegalFormSelector,
8393
8829
  Modal,
8394
8830
  NumberInput,
8831
+ PRINT_GREEN,
8395
8832
  Pages,
8396
8833
  PaymentMethodSelector,
8397
8834
  PrimaryButton,
8835
+ PrintPreview,
8836
+ PrintableDocument,
8398
8837
  RewiseLayout,
8399
8838
  SecondaryButton,
8400
8839
  SelectCostCenter,
@@ -8404,18 +8843,23 @@ var EntityFileManager = ({
8404
8843
  SelectUser,
8405
8844
  SelectVendor,
8406
8845
  SessionProvider,
8846
+ SignatureSection,
8407
8847
  TaxSelector,
8408
8848
  TemplateFNESelector,
8409
8849
  TextInput,
8410
8850
  ThemeProvider,
8411
8851
  ToastContainer,
8412
8852
  ToastProvider,
8853
+ TotalsSection,
8413
8854
  UnitServices,
8414
8855
  UserServices,
8415
8856
  fileManagerApi,
8857
+ formatCurrency,
8416
8858
  formatDate,
8859
+ formatDateFR,
8417
8860
  formatFileSize,
8418
8861
  getFileIcon,
8862
+ numberToWords,
8419
8863
  useAlert,
8420
8864
  useFileManager,
8421
8865
  useFileManagerApi,