@apptimate/ui 7.1.0 → 7.3.0

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.
@@ -0,0 +1,153 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { Modal, ModalFooter, Button, Badge, DateLabel } from "../index";
5
+
6
+ interface DirectTransactionDetailModalProps {
7
+ isOpen: boolean;
8
+ onClose: () => void;
9
+ transaction: any | null;
10
+ }
11
+
12
+ export default function DirectTransactionDetailModal({
13
+ isOpen,
14
+ onClose,
15
+ transaction,
16
+ }: DirectTransactionDetailModalProps) {
17
+ if (!isOpen || !transaction) return null;
18
+
19
+ const formatCurrency = (val: any) => {
20
+ return Number(val).toLocaleString("en-US", {
21
+ minimumFractionDigits: 2,
22
+ maximumFractionDigits: 2,
23
+ });
24
+ };
25
+
26
+ const API_URL = process.env.NEXT_PUBLIC_API_URL;
27
+
28
+ return (
29
+ <Modal isOpen={isOpen} onClose={onClose} title="Transaction Details" size="md">
30
+ <div className="space-y-6 text-sm">
31
+ <div className="grid grid-cols-2 gap-y-4 gap-x-6 border-b border-gray-100 pb-5">
32
+ <div className="space-y-1">
33
+ <p className="text-[11px] font-bold text-gray-500 uppercase tracking-wider">
34
+ Type
35
+ </p>
36
+ <div>
37
+ <Badge
38
+ color={transaction.type === "income" ? "success" : "danger"}
39
+ variant="flat"
40
+ >
41
+ {transaction.type === "income" ? "Income" : "Expense"}
42
+ </Badge>
43
+ </div>
44
+ </div>
45
+ <div className="space-y-1">
46
+ <p className="text-[11px] font-bold text-gray-500 uppercase tracking-wider">
47
+ Date
48
+ </p>
49
+ <div className="font-medium text-gray-900">
50
+ <DateLabel date={transaction.transaction_date} />
51
+ </div>
52
+ </div>
53
+ <div className="space-y-1">
54
+ <p className="text-[11px] font-bold text-gray-500 uppercase tracking-wider">
55
+ Reference
56
+ </p>
57
+ <p className="font-medium text-gray-900">
58
+ {transaction.reference || "-"}
59
+ </p>
60
+ </div>
61
+ <div className="space-y-1">
62
+ <p className="text-[11px] font-bold text-gray-500 uppercase tracking-wider">
63
+ Account
64
+ </p>
65
+ <p className="font-medium text-gray-900">
66
+ {transaction.account?.name || "-"}
67
+ </p>
68
+ </div>
69
+ <div className="space-y-1">
70
+ <p className="text-[11px] font-bold text-gray-500 uppercase tracking-wider">
71
+ Paid Via
72
+ </p>
73
+ <p className="font-medium text-gray-900">
74
+ {transaction.payment_method === "cash"
75
+ ? "Cash"
76
+ : transaction.bank_account?.account_name || "-"}
77
+ </p>
78
+ </div>
79
+ <div className="col-span-2 space-y-1">
80
+ <p className="text-[11px] font-bold text-gray-500 uppercase tracking-wider">
81
+ Description
82
+ </p>
83
+ <p className="font-medium text-gray-900 whitespace-pre-wrap">
84
+ {transaction.description || "-"}
85
+ </p>
86
+ </div>
87
+ </div>
88
+
89
+ <div className="flex items-center justify-between pt-2 pb-5 border-b border-gray-100">
90
+ <p className="text-gray-500 font-medium">Total Amount</p>
91
+ <p className="text-xl font-bold text-gray-900">
92
+ {formatCurrency(transaction.amount)}
93
+ </p>
94
+ </div>
95
+
96
+ {/* Attachments Section */}
97
+ {transaction.attachments && transaction.attachments.length > 0 && (
98
+ <div className="space-y-3 pt-2">
99
+ <h3 className="text-[11px] font-bold text-gray-500 uppercase tracking-wider">
100
+ Attachments ({transaction.attachments.length})
101
+ </h3>
102
+ <div className="grid grid-cols-2 sm:grid-cols-3 gap-3">
103
+ {transaction.attachments.map((attachment: any, idx: number) => {
104
+ const url = typeof attachment === 'string'
105
+ ? (attachment.startsWith('http') ? attachment : `${API_URL}/storage/${attachment}`)
106
+ : attachment.url;
107
+
108
+ const isImage = url?.match(/\.(jpeg|jpg|gif|png|webp)$/i) != null ||
109
+ (typeof attachment === 'object' && attachment.mime_type?.startsWith('image/'));
110
+
111
+ return (
112
+ <a
113
+ key={idx}
114
+ href={url}
115
+ target="_blank"
116
+ rel="noopener noreferrer"
117
+ className="block group relative rounded-lg border border-gray-200 overflow-hidden hover:border-primary/50 transition-colors bg-gray-50"
118
+ >
119
+ {isImage ? (
120
+ <div className="aspect-square w-full">
121
+ {/* eslint-disable-next-line @next/next/no-img-element */}
122
+ <img
123
+ src={url}
124
+ alt="Attachment"
125
+ className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
126
+ />
127
+ </div>
128
+ ) : (
129
+ <div className="aspect-square w-full flex flex-col items-center justify-center p-3 text-center">
130
+ <div className="w-10 h-10 rounded-full bg-white shadow-sm flex items-center justify-center mb-2 text-gray-400">
131
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/></svg>
132
+ </div>
133
+ <span className="text-[10px] font-medium text-gray-600 truncate w-full" title={attachment.original_name || attachment.filename || `File ${idx + 1}`}>
134
+ {attachment.original_name || attachment.filename || `File ${idx + 1}`}
135
+ </span>
136
+ </div>
137
+ )}
138
+ </a>
139
+ );
140
+ })}
141
+ </div>
142
+ </div>
143
+ )}
144
+ </div>
145
+
146
+ <ModalFooter>
147
+ <Button variant="flat" color="secondary" onClick={onClose}>
148
+ Close
149
+ </Button>
150
+ </ModalFooter>
151
+ </Modal>
152
+ );
153
+ }
package/src/index.tsx CHANGED
@@ -11,6 +11,7 @@ export * from './base-components/ChipInput';
11
11
  export * from './base-components/Divider';
12
12
  export * from './base-components/Dropdown';
13
13
  export * from './base-components/EmptyState';
14
+ export * from './base-components/FormattedNumberInput';
14
15
  export * from './base-components/HintIcon';
15
16
  export * from './base-components/RecordCount';
16
17
  export * from './base-components/DateLabel';
@@ -49,6 +50,7 @@ export * from './common-components/pickers/EntityPickerModal';
49
50
  export * from './common-components/pickers/UomGroupPicker';
50
51
  export * from './common-components/pickers/UomPicker';
51
52
  export * from './common-components/pickers/PartyPicker';
53
+ export * from './common-components/pickers/QuickPartyAddModal';
52
54
  export * from './common-components/pickers/WarehousePicker';
53
55
 
54
56
  // Item Wizard
@@ -80,3 +82,4 @@ export * from "./base-components/ChartOfAccountPicker";
80
82
  export * from './common-components/print/TemplateRenderer';
81
83
  export { default as TransactionPrintSelector } from './common-components/print/TransactionPrintSelector';
82
84
  export { default as DirectExpenseModal } from "./finance-components/DirectExpenseModal";
85
+ export { default as DirectTransactionDetailModal } from "./finance-components/DirectTransactionDetailModal";