@driveflux/pdf 4.0.77 → 5.0.0-feature-e-invoicing.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.
Files changed (282) hide show
  1. package/.env +0 -0
  2. package/.env.development +4 -0
  3. package/.turbo/turbo-build.log +14 -0
  4. package/CHANGELOG.md +15 -0
  5. package/build.ts +45 -0
  6. package/bun-env.d.ts +34 -0
  7. package/bunfig.toml +8 -0
  8. package/catalog-version-stamp.json +8 -0
  9. package/dist/main.js +4 -0
  10. package/dist/main.js.map +11 -0
  11. package/dist/src/config.d.ts +20 -0
  12. package/dist/src/create-logger.d.ts +1 -0
  13. package/dist/src/errors.d.ts +43 -0
  14. package/dist/src/main.d.ts +1 -0
  15. package/dist/src/preview/api.d.ts +264 -0
  16. package/dist/src/preview/client/app.d.ts +2 -0
  17. package/dist/src/preview/client/invoice/invoice-display.d.ts +5 -0
  18. package/dist/src/preview/client/invoice/invoice-setup.d.ts +8 -0
  19. package/dist/src/preview/client/preview-targets.d.ts +12 -0
  20. package/dist/src/preview/client/preview.d.ts +6 -0
  21. package/dist/src/preview/client/sidebar.d.ts +7 -0
  22. package/dist/src/preview/client/treaty.d.ts +200 -0
  23. package/dist/src/preview/client/use-target.d.ts +1 -0
  24. package/dist/src/preview/fonts/register-fonts.d.ts +1 -0
  25. package/dist/src/preview/frontend.d.ts +1 -0
  26. package/dist/src/preview/server.d.ts +1 -0
  27. package/dist/src/repository.d.ts +171 -0
  28. package/dist/src/templates/invoice/colors.d.ts +6 -0
  29. package/dist/src/templates/invoice/company-details.d.ts +10 -0
  30. package/dist/src/templates/invoice/flux-invoice.d.ts +6 -0
  31. package/dist/src/templates/invoice/footer.d.ts +2 -0
  32. package/dist/src/templates/invoice/host-invoice.d.ts +9 -0
  33. package/dist/src/templates/invoice/invoice-details.d.ts +13 -0
  34. package/dist/src/templates/invoice/invoice-notes.d.ts +1 -0
  35. package/dist/src/templates/invoice/invoice-summary.d.ts +7 -0
  36. package/dist/src/templates/invoice/letter-head.d.ts +10 -0
  37. package/dist/src/templates/invoice/li.d.ts +10 -0
  38. package/dist/src/templates/invoice/platform-and-host-details.d.ts +11 -0
  39. package/dist/src/templates/invoice/spacer.d.ts +3 -0
  40. package/dist/src/templates/invoice/split-container-items.d.ts +10 -0
  41. package/dist/src/templates/invoice/split-container.d.ts +7 -0
  42. package/dist/src/templates/invoice/standard-page.d.ts +7 -0
  43. package/dist/src/templates/invoice/types.d.ts +3 -0
  44. package/dist/src/templates/invoice/ul.d.ts +8 -0
  45. package/dist/src/templates/invoice/utils.d.ts +2 -0
  46. package/dist/tsconfig.tsbuildinfo +1 -0
  47. package/package.json +34 -40
  48. package/src/config.ts +42 -0
  49. package/src/create-logger.ts +4 -0
  50. package/src/errors.ts +35 -0
  51. package/src/main.ts +7 -0
  52. package/src/preview/api.ts +33 -0
  53. package/src/preview/client/app.tsx +30 -0
  54. package/src/preview/client/invoice/invoice-display.tsx +27 -0
  55. package/src/preview/client/invoice/invoice-setup.tsx +95 -0
  56. package/src/preview/client/preview-targets.ts +30 -0
  57. package/src/preview/client/preview.tsx +37 -0
  58. package/src/preview/client/sidebar.tsx +39 -0
  59. package/src/preview/client/treaty.ts +8 -0
  60. package/src/preview/client/use-target.ts +11 -0
  61. package/src/preview/fonts/GOTHAM-BLACK.TTF +0 -0
  62. package/src/preview/fonts/GOTHAM-BLACKITALIC.TTF +0 -0
  63. package/src/preview/fonts/GOTHAM-BOLD.TTF +0 -0
  64. package/src/preview/fonts/GOTHAM-BOLDITALIC.TTF +0 -0
  65. package/src/preview/fonts/GOTHAM-LIGHT.TTF +0 -0
  66. package/src/preview/fonts/GOTHAM-LIGHTITALIC.TTF +0 -0
  67. package/src/preview/fonts/GOTHAM-MEDIUM.TTF +0 -0
  68. package/src/preview/fonts/GOTHAM-MEDIUMITALIC.TTF +0 -0
  69. package/src/preview/fonts/GOTHAM-THIN.TTF +0 -0
  70. package/src/preview/fonts/GOTHAM-THINITALIC.TTF +0 -0
  71. package/src/preview/fonts/GOTHAM-ULTRA.TTF +0 -0
  72. package/src/preview/fonts/GOTHAM-ULTRAITALIC.TTF +0 -0
  73. package/src/preview/fonts/GOTHAM-XLIGHT.TTF +0 -0
  74. package/src/preview/fonts/GOTHAM-XLIGHTITALIC.TTF +0 -0
  75. package/src/preview/fonts/Gotham Book Italic.otf +0 -0
  76. package/src/preview/fonts/Gotham-BoldItalic.otf +0 -0
  77. package/src/preview/fonts/Gotham-Book.otf +0 -0
  78. package/src/preview/fonts/Gotham-BookItalic.otf +0 -0
  79. package/src/preview/fonts/Gotham-ExtraLight.otf +0 -0
  80. package/src/preview/fonts/Gotham-ExtraLightItalic.otf +0 -0
  81. package/src/preview/fonts/Gotham-Light.otf +0 -0
  82. package/src/preview/fonts/Gotham-LightItalic.otf +0 -0
  83. package/src/preview/fonts/Gotham-Medium.otf +0 -0
  84. package/src/preview/fonts/Gotham-MediumItalic.otf +0 -0
  85. package/src/preview/fonts/Gotham-Thin.otf +0 -0
  86. package/src/preview/fonts/Gotham-ThinItalic.otf +0 -0
  87. package/src/preview/fonts/Gotham-Ultra.otf +0 -0
  88. package/src/preview/fonts/Gotham-UltraItalic.otf +0 -0
  89. package/src/preview/fonts/GothamNarrow-Black.otf +0 -0
  90. package/src/preview/fonts/GothamNarrow-BlackItalic.otf +0 -0
  91. package/src/preview/fonts/GothamNarrow-Book.otf +0 -0
  92. package/src/preview/fonts/GothamNarrow-BookItalic.otf +0 -0
  93. package/src/preview/fonts/GothamNarrow-Light.otf +0 -0
  94. package/src/preview/fonts/GothamNarrow-LightItalic.otf +0 -0
  95. package/src/preview/fonts/GothamNarrow-Medium.otf +0 -0
  96. package/src/preview/fonts/GothamNarrow-MediumItalic.otf +0 -0
  97. package/src/preview/fonts/GothamNarrow-Thin.otf +0 -0
  98. package/src/preview/fonts/GothamNarrow-ThinItalic.otf +0 -0
  99. package/src/preview/fonts/GothamNarrow-Ultra.otf +0 -0
  100. package/src/preview/fonts/GothamNarrow-UltraItalic.otf +0 -0
  101. package/src/preview/fonts/GothamNarrow-XLight.otf +0 -0
  102. package/src/preview/fonts/GothamNarrow-XLightItalic.otf +0 -0
  103. package/src/preview/fonts/gotham-extra-narrow-bold-italic.otf +0 -0
  104. package/src/preview/fonts/gotham-extra-narrow-bold.otf +0 -0
  105. package/src/preview/fonts/gotham-extra-narrow-book-italic.otf +0 -0
  106. package/src/preview/fonts/gotham-extra-narrow-book.otf +0 -0
  107. package/src/preview/fonts/gotham-extra-narrow-light-italic.otf +0 -0
  108. package/src/preview/fonts/gotham-extra-narrow-light.otf +0 -0
  109. package/src/preview/fonts/gotham-extra-narrow-medium-italic.otf +0 -0
  110. package/src/preview/fonts/gotham-extra-narrow-medium.otf +0 -0
  111. package/src/preview/fonts/gotham-rounded-bold-italic.otf +0 -0
  112. package/src/preview/fonts/gotham-rounded-bold.otf +0 -0
  113. package/src/preview/fonts/gotham-rounded-book-italic.otf +0 -0
  114. package/src/preview/fonts/gotham-rounded-book.otf +0 -0
  115. package/src/preview/fonts/gotham-rounded-light-italic.otf +0 -0
  116. package/src/preview/fonts/gotham-rounded-light.otf +0 -0
  117. package/src/preview/fonts/gotham-rounded-medium-italic.otf +0 -0
  118. package/src/preview/fonts/gotham-rounded-medium.otf +0 -0
  119. package/src/preview/fonts/register-fonts.ts +395 -0
  120. package/src/preview/frontend.tsx +23 -0
  121. package/src/preview/global.css +39 -0
  122. package/src/preview/preview.html +12 -0
  123. package/src/preview/server.ts +28 -0
  124. package/src/repository.ts +39 -0
  125. package/src/templates/invoice/E Invoice Format.pdf +0 -0
  126. package/src/templates/invoice/colors.ts +6 -0
  127. package/src/templates/invoice/company-details.tsx +124 -0
  128. package/src/templates/invoice/flux-invoice.tsx +134 -0
  129. package/src/templates/invoice/footer.tsx +46 -0
  130. package/src/templates/invoice/host-invoice.tsx +134 -0
  131. package/src/templates/invoice/images/logo.png +0 -0
  132. package/src/templates/invoice/images/logo.svg +41 -0
  133. package/src/templates/invoice/invoice-details.tsx +231 -0
  134. package/src/templates/invoice/invoice-notes.tsx +74 -0
  135. package/src/templates/invoice/invoice-summary.tsx +135 -0
  136. package/src/templates/invoice/letter-head.tsx +132 -0
  137. package/src/templates/invoice/li.tsx +48 -0
  138. package/src/templates/invoice/platform-and-host-details.tsx +56 -0
  139. package/src/templates/invoice/spacer.tsx +5 -0
  140. package/src/templates/invoice/split-container-items.tsx +80 -0
  141. package/src/templates/invoice/split-container.tsx +35 -0
  142. package/src/templates/invoice/standard-page.tsx +45 -0
  143. package/src/templates/invoice/types.ts +6 -0
  144. package/src/templates/invoice/ul.tsx +19 -0
  145. package/src/templates/invoice/utils.ts +5 -0
  146. package/tsconfig.json +21 -0
  147. package/dist/components/FluxLogo.d.ts +0 -3
  148. package/dist/components/FluxLogo.d.ts.map +0 -1
  149. package/dist/components/FluxLogo.js +0 -66
  150. package/dist/components/FluxLogo.js.map +0 -1
  151. package/dist/components/StandardPage.d.ts +0 -7
  152. package/dist/components/StandardPage.d.ts.map +0 -1
  153. package/dist/components/StandardPage.js +0 -132
  154. package/dist/components/StandardPage.js.map +0 -1
  155. package/dist/index.d.ts +0 -4
  156. package/dist/index.d.ts.map +0 -1
  157. package/dist/index.js +0 -3
  158. package/dist/index.js.map +0 -1
  159. package/dist/templates/QuotationPdf/CustomerSubscriptionSection.d.ts +0 -10
  160. package/dist/templates/QuotationPdf/CustomerSubscriptionSection.d.ts.map +0 -1
  161. package/dist/templates/QuotationPdf/CustomerSubscriptionSection.js +0 -165
  162. package/dist/templates/QuotationPdf/CustomerSubscriptionSection.js.map +0 -1
  163. package/dist/templates/QuotationPdf/GFV.d.ts +0 -10
  164. package/dist/templates/QuotationPdf/GFV.d.ts.map +0 -1
  165. package/dist/templates/QuotationPdf/GFV.js +0 -61
  166. package/dist/templates/QuotationPdf/GFV.js.map +0 -1
  167. package/dist/templates/QuotationPdf/Header.d.ts +0 -9
  168. package/dist/templates/QuotationPdf/Header.d.ts.map +0 -1
  169. package/dist/templates/QuotationPdf/Header.js +0 -71
  170. package/dist/templates/QuotationPdf/Header.js.map +0 -1
  171. package/dist/templates/QuotationPdf/Pricing.d.ts +0 -10
  172. package/dist/templates/QuotationPdf/Pricing.d.ts.map +0 -1
  173. package/dist/templates/QuotationPdf/Pricing.js +0 -723
  174. package/dist/templates/QuotationPdf/Pricing.js.map +0 -1
  175. package/dist/templates/QuotationPdf/QuotationPdfPage.d.ts +0 -8
  176. package/dist/templates/QuotationPdf/QuotationPdfPage.d.ts.map +0 -1
  177. package/dist/templates/QuotationPdf/QuotationPdfPage.js +0 -30
  178. package/dist/templates/QuotationPdf/QuotationPdfPage.js.map +0 -1
  179. package/dist/templates/QuotationPdf/SectionBoxNew.d.ts +0 -9
  180. package/dist/templates/QuotationPdf/SectionBoxNew.d.ts.map +0 -1
  181. package/dist/templates/QuotationPdf/SectionBoxNew.js +0 -38
  182. package/dist/templates/QuotationPdf/SectionBoxNew.js.map +0 -1
  183. package/dist/templates/QuotationPdf/TermsSection.d.ts +0 -8
  184. package/dist/templates/QuotationPdf/TermsSection.d.ts.map +0 -1
  185. package/dist/templates/QuotationPdf/TermsSection.js +0 -50
  186. package/dist/templates/QuotationPdf/TermsSection.js.map +0 -1
  187. package/dist/templates/QuotationPdf/VehiclePhotos.d.ts +0 -10
  188. package/dist/templates/QuotationPdf/VehiclePhotos.d.ts.map +0 -1
  189. package/dist/templates/QuotationPdf/VehiclePhotos.js +0 -66
  190. package/dist/templates/QuotationPdf/VehiclePhotos.js.map +0 -1
  191. package/dist/templates/QuotationPdf/index.d.ts +0 -12
  192. package/dist/templates/QuotationPdf/index.d.ts.map +0 -1
  193. package/dist/templates/QuotationPdf/index.js +0 -214
  194. package/dist/templates/QuotationPdf/index.js.map +0 -1
  195. package/dist/templates/QuotationPdf/translations.d.ts +0 -68
  196. package/dist/templates/QuotationPdf/translations.d.ts.map +0 -1
  197. package/dist/templates/QuotationPdf/translations.js +0 -101
  198. package/dist/templates/QuotationPdf/translations.js.map +0 -1
  199. package/dist/templates/QuotationPdf/utils.d.ts +0 -14
  200. package/dist/templates/QuotationPdf/utils.d.ts.map +0 -1
  201. package/dist/templates/QuotationPdf/utils.js +0 -152
  202. package/dist/templates/QuotationPdf/utils.js.map +0 -1
  203. package/dist/templates/SubscriptionAgreement/Confirmation.d.ts +0 -12
  204. package/dist/templates/SubscriptionAgreement/Confirmation.d.ts.map +0 -1
  205. package/dist/templates/SubscriptionAgreement/Confirmation.js +0 -80
  206. package/dist/templates/SubscriptionAgreement/Confirmation.js.map +0 -1
  207. package/dist/templates/SubscriptionAgreement/CoverPage.d.ts +0 -14
  208. package/dist/templates/SubscriptionAgreement/CoverPage.d.ts.map +0 -1
  209. package/dist/templates/SubscriptionAgreement/CoverPage.js +0 -111
  210. package/dist/templates/SubscriptionAgreement/CoverPage.js.map +0 -1
  211. package/dist/templates/SubscriptionAgreement/CoverPageSection.d.ts +0 -7
  212. package/dist/templates/SubscriptionAgreement/CoverPageSection.d.ts.map +0 -1
  213. package/dist/templates/SubscriptionAgreement/CoverPageSection.js +0 -25
  214. package/dist/templates/SubscriptionAgreement/CoverPageSection.js.map +0 -1
  215. package/dist/templates/SubscriptionAgreement/Details.d.ts +0 -10
  216. package/dist/templates/SubscriptionAgreement/Details.d.ts.map +0 -1
  217. package/dist/templates/SubscriptionAgreement/Details.js +0 -223
  218. package/dist/templates/SubscriptionAgreement/Details.js.map +0 -1
  219. package/dist/templates/SubscriptionAgreement/Footer.d.ts +0 -10
  220. package/dist/templates/SubscriptionAgreement/Footer.d.ts.map +0 -1
  221. package/dist/templates/SubscriptionAgreement/Footer.js +0 -58
  222. package/dist/templates/SubscriptionAgreement/Footer.js.map +0 -1
  223. package/dist/templates/SubscriptionAgreement/Header.d.ts +0 -10
  224. package/dist/templates/SubscriptionAgreement/Header.d.ts.map +0 -1
  225. package/dist/templates/SubscriptionAgreement/Header.js +0 -46
  226. package/dist/templates/SubscriptionAgreement/Header.js.map +0 -1
  227. package/dist/templates/SubscriptionAgreement/LabelValue.d.ts +0 -8
  228. package/dist/templates/SubscriptionAgreement/LabelValue.d.ts.map +0 -1
  229. package/dist/templates/SubscriptionAgreement/LabelValue.js +0 -29
  230. package/dist/templates/SubscriptionAgreement/LabelValue.js.map +0 -1
  231. package/dist/templates/SubscriptionAgreement/SubscriptionAgreementPage.d.ts +0 -10
  232. package/dist/templates/SubscriptionAgreement/SubscriptionAgreementPage.d.ts.map +0 -1
  233. package/dist/templates/SubscriptionAgreement/SubscriptionAgreementPage.js +0 -33
  234. package/dist/templates/SubscriptionAgreement/SubscriptionAgreementPage.js.map +0 -1
  235. package/dist/templates/SubscriptionAgreement/TermsOfUse.d.ts +0 -8
  236. package/dist/templates/SubscriptionAgreement/TermsOfUse.d.ts.map +0 -1
  237. package/dist/templates/SubscriptionAgreement/TermsOfUse.js +0 -101
  238. package/dist/templates/SubscriptionAgreement/TermsOfUse.js.map +0 -1
  239. package/dist/templates/SubscriptionAgreement/TermsOfUseSubSection.d.ts +0 -12
  240. package/dist/templates/SubscriptionAgreement/TermsOfUseSubSection.d.ts.map +0 -1
  241. package/dist/templates/SubscriptionAgreement/TermsOfUseSubSection.js +0 -103
  242. package/dist/templates/SubscriptionAgreement/TermsOfUseSubSection.js.map +0 -1
  243. package/dist/templates/SubscriptionAgreement/index.d.ts +0 -13
  244. package/dist/templates/SubscriptionAgreement/index.d.ts.map +0 -1
  245. package/dist/templates/SubscriptionAgreement/index.js +0 -271
  246. package/dist/templates/SubscriptionAgreement/index.js.map +0 -1
  247. package/dist/templates/SubscriptionAgreement/translations.d.ts +0 -78
  248. package/dist/templates/SubscriptionAgreement/translations.d.ts.map +0 -1
  249. package/dist/templates/SubscriptionAgreement/translations.js +0 -662
  250. package/dist/templates/SubscriptionAgreement/translations.js.map +0 -1
  251. package/dist/templates/SubscriptionAgreement/types.d.ts +0 -7
  252. package/dist/templates/SubscriptionAgreement/types.d.ts.map +0 -1
  253. package/dist/templates/SubscriptionAgreement/types.js +0 -1
  254. package/dist/templates/SubscriptionAgreement/types.js.map +0 -1
  255. package/dist/templates/SubscriptionAgreement/utils.d.ts +0 -6
  256. package/dist/templates/SubscriptionAgreement/utils.d.ts.map +0 -1
  257. package/dist/templates/SubscriptionAgreement/utils.js +0 -37
  258. package/dist/templates/SubscriptionAgreement/utils.js.map +0 -1
  259. package/dist/templates/index.d.ts +0 -3
  260. package/dist/templates/index.d.ts.map +0 -1
  261. package/dist/templates/index.js +0 -2
  262. package/dist/templates/index.js.map +0 -1
  263. package/dist/theme/colors.d.ts +0 -148
  264. package/dist/theme/colors.d.ts.map +0 -1
  265. package/dist/theme/colors.js +0 -137
  266. package/dist/theme/colors.js.map +0 -1
  267. package/dist/theme/index.d.ts +0 -2
  268. package/dist/theme/index.d.ts.map +0 -1
  269. package/dist/theme/index.js +0 -1
  270. package/dist/theme/index.js.map +0 -1
  271. package/dist/types.d.ts +0 -2
  272. package/dist/types.d.ts.map +0 -1
  273. package/dist/types.js +0 -1
  274. package/dist/types.js.map +0 -1
  275. package/dist/utils.d.ts +0 -10
  276. package/dist/utils.d.ts.map +0 -1
  277. package/dist/utils.js +0 -175
  278. package/dist/utils.js.map +0 -1
  279. package/dist/watch.d.ts +0 -2
  280. package/dist/watch.d.ts.map +0 -1
  281. package/dist/watch.js +0 -11
  282. package/dist/watch.js.map +0 -1
@@ -0,0 +1,134 @@
1
+ import { tz } from '@date-fns/tz'
2
+ import type { BillingAddress } from '@driveflux/db'
3
+ import { StyleSheet, Text, View } from '@react-pdf/renderer'
4
+ import { format } from 'date-fns/format'
5
+ import { config } from '../../config'
6
+ import logo from './images/logo.png'
7
+ import { InvoiceDetails } from './invoice-details'
8
+ import { InvoiceNotes } from './invoice-notes'
9
+ import { LetterHead } from './letter-head'
10
+ import { PlatformAndHostDetails } from './platform-and-host-details'
11
+ import { Spacer } from './spacer'
12
+ import { SplitContainer } from './split-container'
13
+ import { SplitContainerItems } from './split-container-items'
14
+ import { StandardPage } from './standard-page'
15
+ import type { InvoiceForPDF } from './types'
16
+
17
+ type FLUXInvoiceProps = {
18
+ data: InvoiceForPDF
19
+ }
20
+
21
+ // Helper function to format billing address
22
+ const formatBillingAddress = (
23
+ address: BillingAddress | null | undefined,
24
+ ): string => {
25
+ if (!address) return '-'
26
+ const parts = [
27
+ address.street1,
28
+ address.street2,
29
+ address.city,
30
+ address.state,
31
+ address.postalCode,
32
+ ].filter(Boolean)
33
+ return parts.join(', ')
34
+ }
35
+
36
+ const styles = StyleSheet.create({
37
+ phoneEmailContainer: {
38
+ display: 'flex',
39
+ flexDirection: 'column',
40
+ gap: 4,
41
+ },
42
+ })
43
+
44
+ export const FLUXInvoice = ({ data }: FLUXInvoiceProps) => {
45
+ const logoUri = new URL(logo, config.appUrl).toString()
46
+ return (
47
+ <StandardPage
48
+ letterHead={
49
+ <LetterHead
50
+ logoSource={logoUri}
51
+ companyName="FLUX Sdn. Bhd."
52
+ companyAddress="15-2 Jalan Solaris, Solaris Mont Kiara, 50480 Kuala Lumpur"
53
+ purpose="Invoice"
54
+ idLabel="Inv No"
55
+ idValue={data.eInvoice?.fluxDetails.invoiceNumber || '-'}
56
+ />
57
+ }
58
+ >
59
+ <SplitContainer
60
+ left={
61
+ <SplitContainerItems
62
+ items={[
63
+ {
64
+ title: 'Bill To',
65
+ value: data.payerName,
66
+ },
67
+ {
68
+ title: 'Address',
69
+ value: formatBillingAddress(data.billingAddress),
70
+ },
71
+ {
72
+ title: 'Tel / Email',
73
+ value: (
74
+ <View style={styles.phoneEmailContainer}>
75
+ <Text>{data.payerPhoneNumber}</Text>
76
+ <Text>{data.payerEmail}</Text>
77
+ </View>
78
+ ),
79
+ },
80
+ ]}
81
+ />
82
+ }
83
+ right={
84
+ <SplitContainerItems
85
+ items={[
86
+ {
87
+ title: 'Invoice Issue Date',
88
+ value: format(data.createdAt, 'dd-MM-yyyy', {
89
+ in: tz(config.timezone),
90
+ }),
91
+ },
92
+ {
93
+ title: 'Payment Due Date',
94
+ value: format(data.date, 'dd-MM-yyyy', {
95
+ in: tz(config.timezone),
96
+ }),
97
+ },
98
+ {
99
+ title: 'Paid On',
100
+ value: data.paidAt
101
+ ? format(data.paidAt, 'dd-MM-yyyy', {
102
+ in: tz(config.timezone),
103
+ })
104
+ : '-',
105
+ },
106
+ {
107
+ title: 'Po No.',
108
+ value: data.eInvoice?.poNumber || '-',
109
+ },
110
+ {
111
+ title: 'Car Plate / Car Type',
112
+ value: data.subscriptionDetails?.vehicleModel || '-',
113
+ },
114
+ {
115
+ title: 'Sub ID',
116
+ value: data.subscriptionDetails?.subscriptionId || '-',
117
+ },
118
+ ]}
119
+ />
120
+ }
121
+ />
122
+ <Spacer height={12} />
123
+ <PlatformAndHostDetails data={data} />
124
+ <Spacer />
125
+ <InvoiceDetails
126
+ total={data.total}
127
+ paid={!!data.paidAt}
128
+ items={data.eInvoice.fluxDetails.lines}
129
+ />
130
+ <Spacer />
131
+ <InvoiceNotes />
132
+ </StandardPage>
133
+ )
134
+ }
@@ -0,0 +1,46 @@
1
+ import { StyleSheet, Text, View } from '@react-pdf/renderer'
2
+ import { colors } from './colors'
3
+
4
+ // Approximate footer height: line (0.6px) + gap (12px) + text (estimated 20-24px for wrapped text)
5
+ // Using a safe estimate of ~36px total
6
+ export const FOOTER_HEIGHT = 36
7
+
8
+ const styles = StyleSheet.create({
9
+ container: {
10
+ position: 'absolute',
11
+ bottom: 0,
12
+ left: 0,
13
+ right: 0,
14
+ display: 'flex',
15
+ flexDirection: 'column',
16
+ gap: 12,
17
+ width: '100%',
18
+ },
19
+ line: {
20
+ backgroundColor: colors.lightGrey,
21
+ width: '100%',
22
+ height: 0.6,
23
+ },
24
+ text: {
25
+ fontFamily: 'Gotham-Book',
26
+ fontSize: 6,
27
+ fontWeight: 400,
28
+ color: colors.darkGrey,
29
+ textAlign: 'left',
30
+ },
31
+ })
32
+
33
+ export const Footer = () => {
34
+ return (
35
+ <View style={styles.container}>
36
+ <View style={styles.line} />
37
+ <Text style={styles.text}>
38
+ This document is issued by FLUX Sdn. Bhd. for the purposes of compliance
39
+ with, inter alia the (i) E-Invoice Guideline under the Income Tax Act
40
+ 1967; (ii) Sales Tax on Low Value Goods Guideline under the Sales Tax
41
+ Act 2018; (iii) Logistics Service Guideline under the Service Tax Act
42
+ 2018.
43
+ </Text>
44
+ </View>
45
+ )
46
+ }
@@ -0,0 +1,134 @@
1
+ import { tz } from '@date-fns/tz'
2
+ import type { BillingAddress } from '@driveflux/db'
3
+ import { StyleSheet, Text, View } from '@react-pdf/renderer'
4
+ import { format } from 'date-fns/format'
5
+ import { config } from '../../config'
6
+ import { InvoiceDetails } from './invoice-details'
7
+ import { InvoiceNotes } from './invoice-notes'
8
+ import { LetterHead } from './letter-head'
9
+ import { PlatformAndHostDetails } from './platform-and-host-details'
10
+ import { Spacer } from './spacer'
11
+ import { SplitContainer } from './split-container'
12
+ import { SplitContainerItems } from './split-container-items'
13
+ import { StandardPage } from './standard-page'
14
+ import type { InvoiceForPDF } from './types'
15
+
16
+ export type HostInvoiceProps = {
17
+ data: {
18
+ eInvoice: Pick<InvoiceForPDF['eInvoice'], 'poNumber' | 'fluxDetails'> & {
19
+ hostDetails: NonNullable<InvoiceForPDF['eInvoice']['hostDetails']>
20
+ }
21
+ } & Pick<
22
+ InvoiceForPDF,
23
+ | 'payerName'
24
+ | 'billingAddress'
25
+ | 'payerPhoneNumber'
26
+ | 'payerEmail'
27
+ | 'date'
28
+ | 'total'
29
+ | 'paidAt'
30
+ | 'subscriptionDetails'
31
+ >
32
+ }
33
+
34
+ // Helper function to format billing address
35
+ const formatBillingAddress = (
36
+ address: BillingAddress | null | undefined,
37
+ ): string => {
38
+ if (!address) return '-'
39
+ const parts = [
40
+ address.street1,
41
+ address.street2,
42
+ address.city,
43
+ address.state,
44
+ address.postalCode,
45
+ ].filter(Boolean)
46
+ return parts.join(', ')
47
+ }
48
+
49
+ const styles = StyleSheet.create({
50
+ phoneEmailContainer: {
51
+ display: 'flex',
52
+ flexDirection: 'column',
53
+ gap: 4,
54
+ },
55
+ })
56
+
57
+ export const HostInvoice = ({ data }: HostInvoiceProps) => {
58
+ return (
59
+ <StandardPage
60
+ letterHead={
61
+ <LetterHead
62
+ purpose="Invoice"
63
+ companyName="FLUX Sdn. Bhd."
64
+ companyAddress="15-2 Jalan Solaris, Solaris Mont Kiara, 50480 Kuala Lumpur"
65
+ idLabel="Inv No"
66
+ idValue={data.eInvoice.hostDetails.invoiceNumber || '-'}
67
+ />
68
+ }
69
+ >
70
+ <SplitContainer
71
+ left={
72
+ <SplitContainerItems
73
+ items={[
74
+ {
75
+ title: 'Bill To',
76
+ value: data.payerName,
77
+ },
78
+ {
79
+ title: 'Address',
80
+ value: formatBillingAddress(data.billingAddress),
81
+ },
82
+ {
83
+ title: 'Tel / Email',
84
+ value: (
85
+ <View style={styles.phoneEmailContainer}>
86
+ <Text>{data.payerPhoneNumber}</Text>
87
+ <Text>{data.payerEmail}</Text>
88
+ </View>
89
+ ),
90
+ },
91
+ ]}
92
+ />
93
+ }
94
+ right={
95
+ <SplitContainerItems
96
+ items={[
97
+ {
98
+ title: 'Invoice Date',
99
+ value: format(data.date, 'dd-MM-yyyy', {
100
+ in: tz(config.timezone),
101
+ }),
102
+ },
103
+ {
104
+ title: 'Po No.',
105
+ value:
106
+ data.eInvoice.hostDetails?.poNumber ||
107
+ data.eInvoice.poNumber ||
108
+ '-',
109
+ },
110
+ {
111
+ title: 'Car Plate / Car Type',
112
+ value: data.subscriptionDetails?.vehicleModel || '-',
113
+ },
114
+ {
115
+ title: 'Sub ID',
116
+ value: data.subscriptionDetails?.subscriptionId || '-',
117
+ },
118
+ ]}
119
+ />
120
+ }
121
+ />
122
+ <Spacer height={12} />
123
+ <PlatformAndHostDetails data={data} />
124
+ <Spacer />
125
+ <InvoiceDetails
126
+ total={data.total}
127
+ paid={!!data.paidAt}
128
+ items={data.eInvoice.hostDetails.lines}
129
+ />
130
+ <Spacer />
131
+ <InvoiceNotes />
132
+ </StandardPage>
133
+ )
134
+ }
@@ -0,0 +1,41 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="91px" height="29px" viewBox="0 0 91 29" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
3
+ <!-- Generator: Sketch 50.2 (55047) - http://www.bohemiancoding.com/sketch -->
4
+ <title>Logo_Black</title>
5
+ <desc>Created with Sketch.</desc>
6
+ <defs>
7
+ <polygon id="path-1" points="0.0664201087 0.228952542 14.9793913 0.228952542 14.9793913 16.6193593 0.0664201087 16.6193593"></polygon>
8
+ <polygon id="path-3" points="0.379826087 0.399216949 6.40758696 0.399216949 6.40758696 6.38983051 0.379826087 6.38983051"></polygon>
9
+ </defs>
10
+ <g id="UI" stroke="none" stroke-width="1" fill="none" fillRule="evenodd">
11
+ <g id="Flux_W_Index_3" transform="translate(-49.000000, -23.000000)">
12
+ <g id="Header-Copy">
13
+ <g id="Logo_Black" transform="translate(49.000000, 23.000000)">
14
+ <polygon id="Fill-1" fill="#000000" points="23 7 35 7 35 8.91891081 24.8849846 8.91891081 24.8849846 14.5451328 33.1150154 14.5451328 33.1150154 16.4548672 24.8849846 16.4548672 24.8849846 24 23 24"></polygon>
15
+ <polygon id="Fill-2" fill="#000000" points="40 7 41.8375644 7 41.8375644 22.081599 51 22.081599 51 24 40 24"></polygon>
16
+ <g id="Group-19">
17
+ <path d="M56.7696082,16.3991966 L56.7696082,7.12706102 L58.6306571,7.12706102 L58.6306571,16.2822136 C58.6306571,19.8177559 60.5154451,21.8079424 63.6727495,21.8079424 C66.7118527,21.8079424 68.6436245,19.9819254 68.6436245,16.3991966 L68.6436245,7.12706102 L70.5051679,7.12706102 L70.5051679,16.2586203 C70.5051679,21.0352644 67.7484614,23.5174678 63.6252712,23.5174678 C59.5495592,23.5174678 56.7696082,21.0352644 56.7696082,16.3991966" id="Fill-3" fill="#000000"></path>
18
+ <g id="Group-7" transform="translate(75.668478, 6.898305)">
19
+ <mask id="mask-2" fill="white">
20
+ <use xlink:href="#path-1"></use>
21
+ </mask>
22
+ <g id="Clip-6"></g>
23
+ <polygon id="Fill-5" fill="#000000" mask="url(#mask-2)" points="6.40427337 8.25998644 0.302327717 0.228952542 2.49325163 0.228952542 7.55858859 6.92549492 12.5764473 0.228952542 14.7441266 0.228952542 8.64218098 8.23688475 14.9795397 16.6193593 12.7648766 16.6193593 7.48786576 9.57137627 2.21036033 16.6193593 0.0664201087 16.6193593"></polygon>
24
+ </g>
25
+ <path d="M0.883244022,16.4406407 C-0.294315761,15.2703186 -0.294315761,13.372539 0.883244022,12.2017254 L12.1410321,1.01362373 C13.3185918,-0.156698305 15.2281082,-0.156698305 16.4056679,1.01362373 C17.5837223,2.18394576 17.5837223,4.08172542 16.4056679,5.25204746 L5.14837446,16.4406407 C4.55934728,17.0260475 3.78782554,17.3185051 3.01580924,17.3185051 C2.24379293,17.3185051 1.4722712,17.0260475 0.883244022,16.4406407 Z" id="Fill-8" fill="#50C8E8" opacity="0.3"></path>
26
+ <path d="M6.51322609,22.0357729 C5.3356663,20.8649593 5.3356663,18.9676712 6.51322609,17.7968576 L12.1408837,12.2042814 C13.3184435,11.0334678 15.2279598,11.0334678 16.4060141,12.2042814 C17.5835739,13.3746034 17.5835739,15.2723831 16.4060141,16.4427051 L10.7783565,22.0357729 C10.1893293,22.6211797 9.41780761,22.9136373 8.6457913,22.9136373 C7.873775,22.9136373 7.10225326,22.6211797 6.51322609,22.0357729 Z" id="Fill-10" fill="#50C8E8" opacity="0.3"></path>
27
+ <g id="Group-14" transform="translate(10.880435, 22.118644)">
28
+ <mask id="mask-4" fill="white">
29
+ <use xlink:href="#path-3"></use>
30
+ </mask>
31
+ <g id="Clip-13"></g>
32
+ <path d="M6.40758696,3.39457288 C6.40758696,5.04904746 5.05841304,6.38992881 3.39370652,6.38992881 C1.72949457,6.38992881 0.379826087,5.04904746 0.379826087,3.39457288 C0.379826087,1.74058983 1.72949457,0.399216949 3.39370652,0.399216949 C5.05841304,0.399216949 6.40758696,1.74058983 6.40758696,3.39457288" id="Fill-12" fill="#50C8E8" mask="url(#mask-4)"></path>
33
+ </g>
34
+ <path d="M17.2880217,3.13155763 C17.2880217,4.7860322 15.9388478,6.12691356 14.2741413,6.12691356 C12.6099293,6.12691356 11.2602609,4.7860322 11.2602609,3.13155763 C11.2602609,1.47708305 12.6099293,0.136201695 14.2741413,0.136201695 C15.9388478,0.136201695 17.2880217,1.47708305 17.2880217,3.13155763" id="Fill-15" fill="#50C8E8"></path>
35
+ <path d="M17.2880217,14.3221169 C17.2880217,15.9765915 15.9388478,17.3174729 14.2741413,17.3174729 C12.6099293,17.3174729 11.2602609,15.9765915 11.2602609,14.3221169 C11.2602609,12.6676424 12.6099293,11.326761 14.2741413,11.326761 C15.9388478,11.326761 17.2880217,12.6676424 17.2880217,14.3221169" id="Fill-17" fill="#50C8E8"></path>
36
+ </g>
37
+ </g>
38
+ </g>
39
+ </g>
40
+ </g>
41
+ </svg>
@@ -0,0 +1,231 @@
1
+ import { StyleSheet, Text, View } from '@react-pdf/renderer'
2
+ import { colors } from './colors'
3
+
4
+ type InvoiceDetailsProps = {
5
+ showSST?: boolean
6
+ paid: boolean
7
+ total: number
8
+ items: {
9
+ description: string
10
+ amount: number
11
+ taxAmount?: number
12
+ total?: number
13
+ }[]
14
+ }
15
+
16
+ // Helper function to format numbers with commas and 2 decimal places
17
+ const formatCurrency = (value: number): string => {
18
+ return value.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
19
+ }
20
+
21
+ const styles = StyleSheet.create({
22
+ container: {
23
+ display: 'flex',
24
+ flexDirection: 'column',
25
+ alignSelf: 'stretch',
26
+ },
27
+ headerRow: {
28
+ display: 'flex',
29
+ flexDirection: 'row',
30
+ backgroundColor: '#ebfbff',
31
+ alignSelf: 'stretch',
32
+ },
33
+ headerCell: {
34
+ padding: 8,
35
+ display: 'flex',
36
+ alignItems: 'center',
37
+ },
38
+ headerCellText: {
39
+ fontFamily: 'Gotham-Medium',
40
+ fontSize: 8,
41
+ fontWeight: 500,
42
+ color: colors.primaryBlack,
43
+ },
44
+ headerCellNo: {
45
+ width: 24,
46
+ alignItems: 'flex-start',
47
+ },
48
+ headerCellDescription: {
49
+ flex: 1,
50
+ alignItems: 'flex-start',
51
+ },
52
+ headerCellAmount: {
53
+ width: 80,
54
+ alignItems: 'flex-end',
55
+ },
56
+ headerCellSST: {
57
+ width: 80,
58
+ alignItems: 'flex-end',
59
+ },
60
+ headerCellRM: {
61
+ width: 80,
62
+ alignItems: 'flex-end',
63
+ },
64
+ dataRow: {
65
+ display: 'flex',
66
+ flexDirection: 'row',
67
+ borderBottomWidth: 0.6,
68
+ borderBottomColor: colors.lightGrey,
69
+ borderBottomStyle: 'solid',
70
+ alignSelf: 'stretch',
71
+ },
72
+ dataCell: {
73
+ padding: 8,
74
+ display: 'flex',
75
+ },
76
+ dataCellText: {
77
+ fontFamily: 'Gotham-Book',
78
+ fontSize: 8,
79
+ fontWeight: 400,
80
+ color: colors.primaryBlack,
81
+ },
82
+ dataCellNo: {
83
+ width: 24,
84
+ justifyContent: 'center',
85
+ alignItems: 'flex-start',
86
+ },
87
+ dataCellDescription: {
88
+ flex: 1,
89
+ flexDirection: 'column',
90
+ alignItems: 'flex-start',
91
+ },
92
+ descriptionText: {
93
+ display: 'flex',
94
+ flexDirection: 'row',
95
+ gap: 4,
96
+ fontFamily: 'Gotham-Book',
97
+ fontSize: 8,
98
+ fontWeight: 400,
99
+ color: colors.primaryBlack,
100
+ },
101
+ dataCellAmount: {
102
+ width: 80,
103
+ alignItems: 'flex-end',
104
+ },
105
+ dataCellSST: {
106
+ width: 80,
107
+ alignItems: 'flex-end',
108
+ },
109
+ dataCellRM: {
110
+ width: 80,
111
+ alignItems: 'flex-end',
112
+ },
113
+ amountText: {
114
+ textAlign: 'right',
115
+ },
116
+ totalRow: {
117
+ display: 'flex',
118
+ flexDirection: 'row',
119
+ alignSelf: 'stretch',
120
+ },
121
+ totalLabel: {
122
+ flex: 1,
123
+ padding: 8,
124
+ display: 'flex',
125
+ alignItems: 'flex-end',
126
+ },
127
+ totalLabelText: {
128
+ fontFamily: 'Gotham-Medium',
129
+ fontSize: 10,
130
+ fontWeight: 500,
131
+ color: colors.primaryBlack,
132
+ },
133
+ totalValue: {
134
+ width: 80,
135
+ height: 30,
136
+ padding: 8,
137
+ display: 'flex',
138
+ justifyContent: 'flex-end',
139
+ alignItems: 'flex-end',
140
+ },
141
+ totalValueText: {
142
+ fontFamily: 'Gotham-Medium',
143
+ fontSize: 10,
144
+ fontWeight: 500,
145
+ color: colors.primaryBlack,
146
+ textAlign: 'right',
147
+ },
148
+ })
149
+
150
+ export const InvoiceDetails = ({
151
+ items,
152
+ total,
153
+ showSST,
154
+ paid,
155
+ }: InvoiceDetailsProps) => {
156
+ return (
157
+ <View style={styles.container}>
158
+ {/* Header Row */}
159
+ <View style={styles.headerRow}>
160
+ <View style={[styles.headerCell, styles.headerCellNo]}>
161
+ <Text style={styles.headerCellText}>No</Text>
162
+ </View>
163
+ <View style={[styles.headerCell, styles.headerCellDescription]}>
164
+ <Text style={styles.headerCellText}>Description</Text>
165
+ </View>
166
+ <View style={[styles.headerCell, styles.headerCellAmount]}>
167
+ <Text style={[styles.headerCellText, styles.amountText]}>Amount</Text>
168
+ </View>
169
+ {showSST && (
170
+ <View style={[styles.headerCell, styles.headerCellSST]}>
171
+ <Text style={[styles.headerCellText, styles.amountText]}>
172
+ Inc. SST (8%)
173
+ </Text>
174
+ </View>
175
+ )}
176
+ <View style={[styles.headerCell, styles.headerCellRM]}>
177
+ <Text style={[styles.headerCellText, styles.amountText]}>RM</Text>
178
+ </View>
179
+ </View>
180
+
181
+ {/* Data Rows */}
182
+ {items.map((item, index) => {
183
+ const rowNumber = index + 1
184
+ const taxAmount = item.taxAmount ?? 0
185
+ const itemTotal = item.total ?? item.amount + taxAmount
186
+
187
+ return (
188
+ <View key={`${item.description}-${index}`} style={styles.dataRow}>
189
+ <View style={[styles.dataCell, styles.dataCellNo]}>
190
+ <Text style={styles.dataCellText}>{rowNumber}</Text>
191
+ </View>
192
+ <View style={[styles.dataCell, styles.dataCellDescription]}>
193
+ <View style={styles.descriptionText}>
194
+ <Text style={styles.dataCellText}>{item.description}</Text>
195
+ </View>
196
+ </View>
197
+ <View style={[styles.dataCell, styles.dataCellAmount]}>
198
+ <Text style={[styles.dataCellText, styles.amountText]}>
199
+ {formatCurrency(item.amount)}
200
+ </Text>
201
+ </View>
202
+ {showSST && (
203
+ <View style={[styles.dataCell, styles.dataCellSST]}>
204
+ <Text style={[styles.dataCellText, styles.amountText]}>
205
+ {taxAmount > 0 ? formatCurrency(taxAmount) : '-'}
206
+ </Text>
207
+ </View>
208
+ )}
209
+ <View style={[styles.dataCell, styles.dataCellRM]}>
210
+ <Text style={[styles.dataCellText, styles.amountText]}>
211
+ {formatCurrency(itemTotal)}
212
+ </Text>
213
+ </View>
214
+ </View>
215
+ )
216
+ })}
217
+
218
+ {/* Total Row */}
219
+ <View style={styles.totalRow}>
220
+ <View style={styles.totalLabel}>
221
+ <Text style={styles.totalLabelText}>
222
+ {paid ? 'TOTAL PAID AMOUNT' : 'TOTAL AMOUNT'}
223
+ </Text>
224
+ </View>
225
+ <View style={styles.totalValue}>
226
+ <Text style={styles.totalValueText}>{formatCurrency(total)}</Text>
227
+ </View>
228
+ </View>
229
+ </View>
230
+ )
231
+ }
@@ -0,0 +1,74 @@
1
+ import { StyleSheet, Text, View } from '@react-pdf/renderer'
2
+ import { colors } from './colors'
3
+ import { Li } from './li'
4
+ import { Spacer } from './spacer'
5
+ import { Ul } from './ul'
6
+
7
+ const styles = StyleSheet.create({
8
+ container: {
9
+ display: 'flex',
10
+ flexDirection: 'column',
11
+ alignSelf: 'stretch',
12
+ gap: 4,
13
+ },
14
+ title: {
15
+ fontFamily: 'Gotham-Medium',
16
+ fontSize: 8,
17
+ fontWeight: 500,
18
+ color: colors.primaryBlack,
19
+ },
20
+ text: {
21
+ fontFamily: 'Gotham-Book',
22
+ fontSize: 8,
23
+ fontWeight: 400,
24
+ color: colors.primaryBlack,
25
+ },
26
+ disclaimer: {
27
+ fontStyle: 'italic',
28
+ fontFamily: 'Gotham-Light',
29
+ fontSize: 8,
30
+ fontWeight: 300,
31
+ color: colors.primaryBlack,
32
+ },
33
+ list: {
34
+ fontFamily: 'Gotham-Book',
35
+ fontSize: 8,
36
+ fontWeight: 400,
37
+ color: colors.primaryBlack,
38
+ },
39
+ })
40
+ export const InvoiceNotes = () => {
41
+ return (
42
+ <View style={styles.container}>
43
+ <Text style={styles.title}>Payment Processed By:</Text>
44
+ <Text style={styles.title}>FLUX Sdn. Bhd. (1375723-H)</Text>
45
+ <Text style={styles.text}>
46
+ 15-2 Jalan Solaris, Solaris Mont Kiara, 50480 Kuala Lumpur
47
+ </Text>
48
+ <Text style={styles.disclaimer}>
49
+ FLUX (the “Platform”) acts as a technology provider and a limited
50
+ payment collection agent for the Host. Completion of payment of the
51
+ Total Price to FLUX satisfies your financial obligation to your Host.
52
+ All refund requests are processed according to the Host's cancellation
53
+ policy (available on the Listing) or our general Rebooking and Refund
54
+ Policy Terms.
55
+ </Text>
56
+
57
+ <Spacer height={12} />
58
+
59
+ <Text style={styles.title}>Important Notice:</Text>
60
+
61
+ <Ul style={styles.list}>
62
+ <Li>We supports credit/debit card and payment link upon request.</Li>
63
+ <Li>
64
+ Payments made directly to Flux's bank account through online bank
65
+ transfer or cheque will incur an additional 10% surcharge. For direct
66
+ bank in, please include the Invoice ID in your payment reference. FLUX
67
+ is not responsible for any delays or misallocations due to missing or
68
+ incorrect references. Unidentified payments will not be treated as a
69
+ settlement until clarified.
70
+ </Li>
71
+ </Ul>
72
+ </View>
73
+ )
74
+ }