@driveflux/pdf 1.0.14 → 1.1.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 (100) hide show
  1. package/dist/__mocks__/quotation.d.ts +1 -1
  2. package/dist/__mocks__/quotation.d.ts.map +1 -1
  3. package/dist/__mocks__/subscription.d.ts +1 -1
  4. package/dist/__mocks__/subscription.d.ts.map +1 -1
  5. package/dist/templates/QuotationPdf/CustomerSubscriptionSection.d.ts.map +1 -1
  6. package/dist/templates/QuotationPdf/CustomerSubscriptionSection.js +2 -2
  7. package/dist/templates/QuotationPdf/index.d.ts +1 -1
  8. package/dist/templates/QuotationPdf/index.d.ts.map +1 -1
  9. package/dist/templates/QuotationPdf/utils.d.ts +2 -3
  10. package/dist/templates/QuotationPdf/utils.d.ts.map +1 -1
  11. package/dist/templates/QuotationPdf/utils.js +0 -14
  12. package/dist/templates/SubscriptionAgreement/index.d.ts +1 -1
  13. package/dist/templates/SubscriptionAgreement/index.d.ts.map +1 -1
  14. package/dist/templates/SubscriptionAgreement/translations.d.ts.map +1 -1
  15. package/dist/templates/SubscriptionAgreement/utils.d.ts +1 -1
  16. package/dist/templates/SubscriptionAgreement/utils.d.ts.map +1 -1
  17. package/dist/theme/colors.d.ts.map +1 -1
  18. package/dist/theme/colors.js +36 -36
  19. package/dist/utils.d.ts +2 -8
  20. package/dist/utils.d.ts.map +1 -1
  21. package/dist/utils.js +7 -31
  22. package/package.json +23 -20
  23. package/.eslintrc +0 -3
  24. package/.swcrc +0 -14
  25. package/.turbo/turbo-build.log +0 -6
  26. package/CHANGELOG.md +0 -179
  27. package/dist/cjs/__mocks__/quotation.js +0 -69
  28. package/dist/cjs/__mocks__/subscription.js +0 -1079
  29. package/dist/cjs/components/FluxLogo.js +0 -76
  30. package/dist/cjs/components/StandardPage.js +0 -129
  31. package/dist/cjs/debug.js +0 -234
  32. package/dist/cjs/index.js +0 -20
  33. package/dist/cjs/templates/QuotationPdf/CustomerSubscriptionSection.js +0 -147
  34. package/dist/cjs/templates/QuotationPdf/GFV.js +0 -57
  35. package/dist/cjs/templates/QuotationPdf/Header.js +0 -86
  36. package/dist/cjs/templates/QuotationPdf/Pricing.js +0 -430
  37. package/dist/cjs/templates/QuotationPdf/QuotationPdfPage.js +0 -45
  38. package/dist/cjs/templates/QuotationPdf/SectionBoxNew.js +0 -43
  39. package/dist/cjs/templates/QuotationPdf/TermsSection.js +0 -60
  40. package/dist/cjs/templates/QuotationPdf/index.js +0 -208
  41. package/dist/cjs/templates/QuotationPdf/translations.js +0 -103
  42. package/dist/cjs/templates/QuotationPdf/utils.js +0 -108
  43. package/dist/cjs/templates/SubscriptionAgreement/Confirmation.js +0 -95
  44. package/dist/cjs/templates/SubscriptionAgreement/CoverPage.js +0 -110
  45. package/dist/cjs/templates/SubscriptionAgreement/CoverPageSection.js +0 -35
  46. package/dist/cjs/templates/SubscriptionAgreement/Details.js +0 -161
  47. package/dist/cjs/templates/SubscriptionAgreement/Footer.js +0 -68
  48. package/dist/cjs/templates/SubscriptionAgreement/Header.js +0 -61
  49. package/dist/cjs/templates/SubscriptionAgreement/LabelValue.js +0 -39
  50. package/dist/cjs/templates/SubscriptionAgreement/SubscriptionAgreementPage.js +0 -48
  51. package/dist/cjs/templates/SubscriptionAgreement/TermsOfUse.js +0 -72
  52. package/dist/cjs/templates/SubscriptionAgreement/TermsOfUseSubSection.js +0 -108
  53. package/dist/cjs/templates/SubscriptionAgreement/index.js +0 -276
  54. package/dist/cjs/templates/SubscriptionAgreement/translations.js +0 -666
  55. package/dist/cjs/templates/SubscriptionAgreement/utils.js +0 -14
  56. package/dist/cjs/templates/index.js +0 -19
  57. package/dist/cjs/theme/colors.js +0 -147
  58. package/dist/cjs/theme/index.js +0 -18
  59. package/dist/cjs/types.js +0 -4
  60. package/dist/cjs/utils.js +0 -184
  61. package/dist/cjs/watch.js +0 -20
  62. package/index.cjs +0 -1
  63. package/index.d.ts +0 -1
  64. package/src/__mocks__/quotation.ts +0 -62
  65. package/src/__mocks__/subscription.ts +0 -803
  66. package/src/components/FluxLogo.tsx +0 -52
  67. package/src/components/StandardPage.tsx +0 -32
  68. package/src/debug.ts +0 -45
  69. package/src/index.ts +0 -3
  70. package/src/templates/QuotationPdf/CustomerSubscriptionSection.tsx +0 -68
  71. package/src/templates/QuotationPdf/GFV.tsx +0 -29
  72. package/src/templates/QuotationPdf/Header.tsx +0 -31
  73. package/src/templates/QuotationPdf/Pricing.tsx +0 -214
  74. package/src/templates/QuotationPdf/QuotationPdfPage.tsx +0 -25
  75. package/src/templates/QuotationPdf/SectionBoxNew.tsx +0 -20
  76. package/src/templates/QuotationPdf/TermsSection.tsx +0 -28
  77. package/src/templates/QuotationPdf/index.tsx +0 -46
  78. package/src/templates/QuotationPdf/translations.ts +0 -82
  79. package/src/templates/QuotationPdf/utils.ts +0 -59
  80. package/src/templates/SubscriptionAgreement/Confirmation.tsx +0 -49
  81. package/src/templates/SubscriptionAgreement/CoverPage.tsx +0 -52
  82. package/src/templates/SubscriptionAgreement/CoverPageSection.tsx +0 -25
  83. package/src/templates/SubscriptionAgreement/Details.tsx +0 -127
  84. package/src/templates/SubscriptionAgreement/Footer.tsx +0 -37
  85. package/src/templates/SubscriptionAgreement/Header.tsx +0 -37
  86. package/src/templates/SubscriptionAgreement/LabelValue.tsx +0 -19
  87. package/src/templates/SubscriptionAgreement/SubscriptionAgreementPage.tsx +0 -24
  88. package/src/templates/SubscriptionAgreement/TermsOfUse.tsx +0 -30
  89. package/src/templates/SubscriptionAgreement/TermsOfUseSubSection.tsx +0 -44
  90. package/src/templates/SubscriptionAgreement/index.tsx +0 -66
  91. package/src/templates/SubscriptionAgreement/translations.ts +0 -664
  92. package/src/templates/SubscriptionAgreement/utils.ts +0 -7
  93. package/src/templates/index.ts +0 -2
  94. package/src/theme/colors.ts +0 -180
  95. package/src/theme/index.ts +0 -1
  96. package/src/types.ts +0 -1
  97. package/src/utils.ts +0 -27
  98. package/src/watch.ts +0 -16
  99. package/tsconfig.json +0 -13
  100. package/tsconfig.tsbuildinfo +0 -1
@@ -1,82 +0,0 @@
1
- const enTranslation = {
2
- quotation: `Quotation`,
3
- date: 'Date',
4
- customer: {
5
- title: `Customer`,
6
- name: `Name`,
7
- email: `Email`,
8
- address: `Address`
9
- },
10
- subscription: {
11
- title: `Subscription`,
12
- vehicleName: `Vehicle`,
13
- plan: `Subscription Plan`,
14
- mileagePackage: `Mileage Package`
15
- },
16
- subIncludes: {
17
- title: `What's Included:`,
18
- content: [
19
- `Comprehensive insurance`,
20
- `Road tax`,
21
- `Regularly scheduled maintenance`,
22
- `Selective wear & tear`,
23
- `Ability to swap vehicles`,
24
- `Doorstep delivery`,
25
- `24/7 nationwide roadside assistance`,
26
- `Theft recovery services`,
27
- `Independently rated vehicle inspection`,
28
- `Option to purchase the vehicle at the end of the subscription`
29
- ]
30
- },
31
- pricing: {
32
- title: `Pricing`,
33
- fees: {
34
- upfront: {
35
- title: `Upfront Fees`,
36
- content: [
37
- { title: `Booking Fee`, key: 'reservationFee' },
38
- { title: `Activation Fee`, key: 'startFee' },
39
- { title: `Refundable Deposit`, key: 'deposit' }
40
- ]
41
- },
42
- monthly: {
43
- title: `Monthly Fees`,
44
- content: [{ title: `Subscription Fee`, key: 'subscriptionFee' }]
45
- },
46
- dueToday: {
47
- title: `Due Today`,
48
- description: `Grand Total is due before your subscription start. Monthly fee is due on the first day of every cycle period.`,
49
- subTotal: `Upfront Fees + Monthly Fee`,
50
- serviceFee: `Service Fee (8%)`,
51
- grandTotal: `Grand Total`
52
- },
53
- extraCharge: `Extra Charge`,
54
- promo: `Promo`,
55
- gfv: {
56
- title: `Guaranteed Future Value (GFV)`
57
- }
58
- }
59
- },
60
- terms: {
61
- title: `Terms`,
62
- content: [
63
- `This quotation is valid for 7 days.`,
64
- `All vehicles proposed are unique and are available to our customers on a first come first served basis.`,
65
- `The Mileage Package is the monthly mileage cap for the vehicle. If you exceed this cap for any given month, excess mileage charges will be incurred.`,
66
- `Initial payment to be made within 7 days of the invoice date.`,
67
- `Subscription starts on the date of the car delivery.`,
68
- `The upfront fees are billed one-time per subscription, before the subscription starts.`,
69
- `All monthly recurring fees are billed on the same date as the delivery of the vehicle.`,
70
- `Scheduling delivery will only commence Grand Total is fully paid, 7 - 30+ days after payment and subject to vehicle availability.`
71
- ]
72
- }
73
- }
74
-
75
- export type QuotationPdfTranslation = typeof enTranslation
76
-
77
- export const useTranslations = (locale: 'en'): QuotationPdfTranslation => {
78
- const translation = {
79
- en: enTranslation
80
- }
81
- return translation[locale]
82
- }
@@ -1,59 +0,0 @@
1
- import { MileagePackage, PlanType } from '@driveflux/db'
2
- import { Address } from '@driveflux/db/types'
3
-
4
- export const formatAddress = (originalAddress: Address) => {
5
- const { coordinates, metadata, ...address } = originalAddress
6
- return (Object.keys(address) as Array<keyof typeof address>)
7
- .filter((key) => key !== 'name' && !!address[key])
8
- .map((a) => address[a])
9
- .join(', ')
10
- }
11
-
12
- export const getSimplifiedPlanTranslation = (plan: PlanType) => {
13
- switch (plan) {
14
- case 'plan60':
15
- return `60 Months`
16
- case 'plan36':
17
- return `36 Months`
18
- case 'plan24':
19
- return `24 Months`
20
- case 'plan12':
21
- return `12 Months`
22
- case 'plan1':
23
- return `Monthly`
24
- case 'planWeekly':
25
- return `Weekly`
26
- default:
27
- return `Unknown Plan`
28
- }
29
- }
30
-
31
- export const getMileagePackageTranslation = (mileagePackage?: MileagePackage) => {
32
- switch (mileagePackage) {
33
- case 'lite':
34
- return `Lite`
35
- case 'standard':
36
- return `Standard`
37
- case 'plus':
38
- return `Plus`
39
- case 'unlimited':
40
- return `Unlimited`
41
- default:
42
- return `Unknown Mileage Package`
43
- }
44
- }
45
-
46
- export const getFullMileagePackageTranslation = (plan?: MileagePackage | null) => {
47
- switch (plan) {
48
- case 'lite':
49
- return `Lite - 1,250KM`
50
- case 'standard':
51
- return `Standard - 2,000KM`
52
- case 'plus':
53
- return `Plus - 2,750KM`
54
- case 'unlimited':
55
- return `Unlimited`
56
- default:
57
- return `Unknown Mileage Package`
58
- }
59
- }
@@ -1,49 +0,0 @@
1
- import { userName } from '@driveflux/db/models/user'
2
- import { SubscriptionWithUser, SubscriptionWithVehicle } from '@driveflux/db/types'
3
- import { Image, Text, View } from '@react-pdf/renderer'
4
- import { format } from 'date-fns'
5
- import { FC } from 'react'
6
- import { colors } from '../../theme/index.js'
7
- import LabelValue from './LabelValue.js'
8
- import { SubscriptionAgreementTranslation } from './translations.js'
9
-
10
- type Props = {
11
- tConfirmation: SubscriptionAgreementTranslation['confirmation']
12
- subscription: SubscriptionWithUser & SubscriptionWithVehicle
13
- }
14
-
15
- const Confirmation: FC<Props> = ({ tConfirmation, subscription }) => {
16
- if (!subscription.signature?.signature) {
17
- throw new Error('Missing signature')
18
- }
19
-
20
- const border = `1px solid ${colors.primary2}`
21
-
22
- return (
23
- <View style={{ borderLeft: border, borderRight: border, borderBottom: border }}>
24
- <View style={{ backgroundColor: colors.primary1, borderTop: border, padding: 8 }}>
25
- <Text style={{ fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: 1 }}>{tConfirmation.title}</Text>
26
- </View>
27
- <View style={{ padding: 8, paddingBottom: 16, rowGap: 8, borderTop: border }}>
28
- <Text>{tConfirmation.agreementText(subscription.businessId ? 'business' : 'member')}</Text>
29
- <View style={{ height: 160, alignItems: 'flex-start' }}>
30
- <Image src={subscription.signature.signature} />
31
- </View>
32
- <View style={{ rowGap: 8 }}>
33
- <LabelValue label={tConfirmation.name} value={userName(subscription.user)} />
34
- <LabelValue label={tConfirmation.idOrPassportNo} value={subscription.user.identification?.number} />
35
- <LabelValue
36
- label={tConfirmation.date}
37
- value={
38
- subscription.signature.signedAt
39
- ? format(subscription.signature.signedAt, 'dd-MM-yyyy hh:mm a')
40
- : undefined
41
- }
42
- />
43
- </View>
44
- </View>
45
- </View>
46
- )
47
- }
48
-
49
- export default Confirmation
@@ -1,52 +0,0 @@
1
- import { User } from '@driveflux/db'
2
- import { userName } from '@driveflux/db/models/user'
3
- import { Text, View } from '@react-pdf/renderer'
4
- import { format } from 'date-fns'
5
- import { FC } from 'react'
6
- import { colors } from '../../theme/colors.js'
7
- import CoverPageSection from './CoverPageSection.js'
8
- import LabelValue from './LabelValue.js'
9
- import { SubscriptionAgreementTranslation } from './translations.js'
10
-
11
- type Props = {
12
- tTitle: SubscriptionAgreementTranslation['title']
13
- tCover: SubscriptionAgreementTranslation['cover']
14
- signedAt: Date
15
- user: User
16
- }
17
-
18
- const CoverPage: FC<Props> = ({ tTitle, tCover, signedAt, user }) => {
19
- return (
20
- <View style={{ flex: 1, paddingVertical: 80, justifyContent: 'space-between' }}>
21
- <Text style={{ fontWeight: 'bold', fontSize: 40, textTransform: 'uppercase', flex: 1 }}>{tTitle}</Text>
22
- <View style={{ padding: 16, rowGap: 32, border: `1px solid ${colors.primary2}`, fontSize: 10 }}>
23
- <CoverPageSection title={tCover.effectiveDate}>
24
- <View style={{ flexDirection: 'row', columnGap: 4 }}>
25
- <Text style={{ textDecoration: 'underline' }}>{format(signedAt, 'do')}</Text>
26
- <Text>{tCover.of}</Text>
27
- <Text style={{ textDecoration: 'underline' }}>{format(signedAt, 'MMM')}</Text>
28
- <Text>{format(signedAt, 'yyyy')}</Text>
29
- </View>
30
- </CoverPageSection>
31
- <CoverPageSection title={tCover.agreementBetween}>
32
- <LabelValue label={tCover.name} value={userName(user)} />
33
- <LabelValue label={tCover.idOrPassportNo} value={user.identification?.number} />
34
- </CoverPageSection>
35
- <Text
36
- style={{
37
- fontSize: 8,
38
- fontWeight: 'bold',
39
- color: colors.primary3,
40
- textTransform: 'uppercase',
41
- letterSpacing: 1
42
- }}
43
- >
44
- {tCover.and}
45
- </Text>
46
- <Text>FLUX Sdn Bhd (1264766-H)</Text>
47
- </View>
48
- </View>
49
- )
50
- }
51
-
52
- export default CoverPage
@@ -1,25 +0,0 @@
1
- import { Text, View } from '@react-pdf/renderer'
2
- import { FC, PropsWithChildren } from 'react'
3
- import { colors } from '../../theme/colors.js'
4
-
5
- type Props = {
6
- title: string
7
- }
8
- const CoverPageSection: FC<PropsWithChildren<Props>> = ({ title, children }) => {
9
- return (
10
- <View style={{ rowGap: 16 }}>
11
- <Text
12
- style={{
13
- fontSize: 8,
14
- fontWeight: 'bold',
15
- color: colors.primary3,
16
- textTransform: 'uppercase',
17
- letterSpacing: 1
18
- }}
19
- >{`${title}:`}</Text>
20
- {children}
21
- </View>
22
- )
23
- }
24
-
25
- export default CoverPageSection
@@ -1,127 +0,0 @@
1
- import { MileagePackage, PlanType, VehicleType } from '@driveflux/db'
2
- import { userName } from '@driveflux/db/models/user'
3
- import { format } from '@driveflux/time'
4
- import { Text, View } from '@react-pdf/renderer'
5
- import { FC, useMemo } from 'react'
6
- import { colors } from '../../theme/index.js'
7
- import LabelValue from './LabelValue.js'
8
- import { SubscriptionForAgreement } from './index.js'
9
- import { SubscriptionAgreementTranslation } from './translations.js'
10
-
11
- type Props = {
12
- tDetails: SubscriptionAgreementTranslation['details']
13
- subscription: SubscriptionForAgreement
14
- }
15
-
16
- const Details: FC<Props> = ({ tDetails, subscription }) => {
17
- const details = useMemo(
18
- () => ({
19
- member: [
20
- {
21
- key: tDetails.member.name,
22
- value: userName(subscription.user)
23
- },
24
- {
25
- key: tDetails.member.idOrPassportNo,
26
- value: subscription.user.identification?.number
27
- }
28
- ],
29
- vehicle: [
30
- {
31
- key: tDetails.vehicle.make,
32
- value: subscription.vehicle?.make
33
- },
34
- {
35
- key: tDetails.vehicle.model,
36
- value: subscription.vehicle?.vehicleModel
37
- },
38
- {
39
- key: tDetails.vehicle.year,
40
- value: subscription.vehicle?.year
41
- },
42
- {
43
- key: tDetails.vehicle.plateNo,
44
- value: subscription.vehicle?.registrationNumber
45
- }
46
- ],
47
- subscription: [
48
- {
49
- key: tDetails.subscription.subscriptionPlan,
50
- value: getPlanTranslation(subscription.plan)
51
- },
52
- {
53
- key: tDetails.subscription.mileagePackage,
54
- value: getFullMileagePackageTranslation(subscription.mileagePackage)
55
- },
56
- {
57
- key: tDetails.subscription.startDate,
58
- value: subscription.startedAt ? format(subscription.startedAt, 'dd-MM-yyyy') : undefined
59
- },
60
- {
61
- key: tDetails.subscription.endDate,
62
- value: subscription.endedAt
63
- ? format(subscription.endedAt, 'dd-MM-yyyy')
64
- : subscription.schedule?.endAt
65
- ? format(subscription.schedule?.endAt, 'dd-MM-yyyy')
66
- : undefined
67
- }
68
- ]
69
- }),
70
- []
71
- )
72
-
73
- const border = `1px solid ${colors.primary2}`
74
-
75
- return (
76
- <View style={{ borderLeft: border, borderRight: border }}>
77
- <View style={{ backgroundColor: colors.primary1, borderTop: border, padding: 8 }}>
78
- <Text style={{ fontWeight: 'bold', textTransform: 'uppercase', letterSpacing: 1 }}>{tDetails.agreement}</Text>
79
- </View>
80
- {Object.keys(details).map((key, i) => (
81
- <View key={key} style={{ padding: 8, paddingBottom: 16, rowGap: 8, borderTop: border }}>
82
- <Text style={{ textTransform: 'uppercase', color: colors.primary2, fontSize: 8, letterSpacing: 1 }}>{`${key} details`}</Text>
83
- {details[key as keyof typeof details].map((line) => (
84
- <LabelValue label={line.key} value={line.value} key={line.key} />
85
- ))}
86
- </View>
87
- ))}
88
- </View>
89
- )
90
- }
91
-
92
- export default Details
93
-
94
- // TODO: replace this with dump's once the package is ready
95
- const getPlanTranslation = (plan?: PlanType | null, vehicleType?: VehicleType) => {
96
- switch (plan) {
97
- case 'plan60':
98
- return vehicleType === 'motorcycle' ? '60 Months' : '60 Months (Basic)'
99
- case 'plan36':
100
- return '36 Months'
101
- case 'plan24':
102
- return '24 Months'
103
- case 'plan12':
104
- return '12 Months'
105
- case 'plan1':
106
- return 'Monthly (Ultra)'
107
- case 'planWeekly':
108
- return 'Weekly'
109
- default:
110
- return 'Unknown Plan'
111
- }
112
- }
113
-
114
- const getFullMileagePackageTranslation = (plan?: MileagePackage | null) => {
115
- switch (plan) {
116
- case 'lite':
117
- return 'Lite - 1,250KM'
118
- case 'standard':
119
- return 'Standard - 2,000KM'
120
- case 'plus':
121
- return 'Plus - 2,750KM'
122
- case 'unlimited':
123
- return 'Unlimited'
124
- default:
125
- return 'Unknown Mileage Package'
126
- }
127
- }
@@ -1,37 +0,0 @@
1
- import { Text, View } from '@react-pdf/renderer'
2
- import { FC } from 'react'
3
- import { colors } from '../../theme/colors.js'
4
- import { SubscriptionAgreementTranslation } from './translations.js'
5
-
6
- type Props = {
7
- tComputerGenerated: SubscriptionAgreementTranslation['computerGenerated']
8
- tPage: SubscriptionAgreementTranslation['page']
9
- tOf: SubscriptionAgreementTranslation['of']
10
- }
11
-
12
- const Footer: FC<Props> = ({ tComputerGenerated, tPage, tOf }) => {
13
- return (
14
- <View
15
- fixed
16
- style={{
17
- justifyContent: 'space-between',
18
- flexDirection: 'row',
19
- paddingTop: 16,
20
- marginTop: 16,
21
- borderTop: `1px solid ${colors.links}`,
22
- color: colors.primary2,
23
- fontSize: 8,
24
- }}
25
- >
26
- <Text>{tComputerGenerated}</Text>
27
- <View style={{ flexDirection: 'row', columnGap: 4 }}>
28
- <Text>{tPage}</Text>
29
- <Text style={{ fontWeight: 'bold', color: colors.black }} render={({ pageNumber }) => `${pageNumber}`} />
30
- <Text>{tOf}</Text>
31
- <Text style={{ fontWeight: 'bold', color: colors.black }} render={({ totalPages }) => `${totalPages}`} />
32
- </View>
33
- </View>
34
- )
35
- }
36
-
37
- export default Footer
@@ -1,37 +0,0 @@
1
- import { Link, Text, View } from '@react-pdf/renderer'
2
- import { FC } from 'react'
3
- import FluxLogo from '../../components/FluxLogo.js'
4
- import { colors } from '../../theme/colors.js'
5
- import { SubscriptionAgreementTranslation } from './translations.js'
6
-
7
- type Props = {
8
- tTitle: SubscriptionAgreementTranslation['title']
9
- userId: string
10
- subscriptionId: string
11
- }
12
-
13
- const Header: FC<Props> = ({ tTitle, userId, subscriptionId }) => {
14
- return (
15
- <View
16
- fixed
17
- style={{
18
- flexDirection: 'row',
19
- justifyContent: 'space-between',
20
- alignItems: 'center',
21
- paddingBottom: 40,
22
- // to not get pushed by the content
23
- minHeight: 69
24
- }}
25
- >
26
- <Link src="https://driveflux.com">
27
- <FluxLogo />
28
- </Link>
29
- <View style={{ rowGap: 4, fontSize: 8, alignItems: 'flex-end' }}>
30
- <Text style={{ fontWeight: 'bold' }}>{tTitle}</Text>
31
- <Text style={{ color: colors.primary2 }}>{`FLUX-${userId}-${subscriptionId}`}</Text>
32
- </View>
33
- </View>
34
- )
35
- }
36
-
37
- export default Header
@@ -1,19 +0,0 @@
1
- import { Text, View } from '@react-pdf/renderer'
2
- import { FC } from 'react'
3
-
4
- type Props = {
5
- label: string
6
- value?: string | number | boolean | null
7
- }
8
-
9
- const LabelValue: FC<Props> = ({ label, value }) => {
10
- return (
11
- <View style={{ flexDirection: 'row' }}>
12
- <Text style={{ minWidth: 120, textTransform: 'capitalize' }}>{label}</Text>
13
- <Text>{`:`}</Text>
14
- <Text style={{ paddingLeft: 16 }}>{!!value ? `${value}` : '-'}</Text>
15
- </View>
16
- )
17
- }
18
-
19
- export default LabelValue
@@ -1,24 +0,0 @@
1
- import { View } from '@react-pdf/renderer'
2
- import { FC, PropsWithChildren } from 'react'
3
- import StandardPage from '../../components/StandardPage.js'
4
- import Footer from './Footer.js'
5
- import Header from './Header.js'
6
- import { SubscriptionAgreementTranslation } from './translations.js'
7
-
8
- type Props = {
9
- t: SubscriptionAgreementTranslation
10
- userId: string
11
- subscriptionId: string
12
- }
13
-
14
- const SubscriptionAgreementPage: FC<PropsWithChildren<Props>> = ({ t, userId, subscriptionId, children }) => {
15
- return (
16
- <StandardPage style={{ padding: 40, fontSize: 10 }}>
17
- <Header tTitle={t.title} userId={userId} subscriptionId={subscriptionId} />
18
- <View style={{ flex: 1 }}>{children}</View>
19
- <Footer tComputerGenerated={t.computerGenerated} tPage={t.page} tOf={t.of} />
20
- </StandardPage>
21
- )
22
- }
23
-
24
- export default SubscriptionAgreementPage
@@ -1,30 +0,0 @@
1
- import { Text, View } from '@react-pdf/renderer'
2
- import { FC } from 'react'
3
- import TermsOfUseSubSection from './TermsOfUseSubSection.js'
4
- import { SubscriptionAgreementTranslation } from './translations.js'
5
-
6
- type Props = {
7
- t: SubscriptionAgreementTranslation['termsOfUse']
8
- }
9
-
10
- const TermsOfUse: FC<Props> = ({ t }) => {
11
- return (
12
- <View style={{ rowGap: 16 }}>
13
- <Text style={{ fontWeight: 'bold', textTransform: 'uppercase' }}>{t.title}</Text>
14
- <View style={{ rowGap: 16, lineHeight: 1.4 }}>
15
- {t.content.map((section, i) => (
16
- <View key={section.title} style={{ rowGap: 16 }}>
17
- <Text style={{ fontWeight: 'bold' }}>{`${i + 1} ${section.title}`}</Text>
18
- <View style={{ rowGap: 16, paddingLeft: 16 }}>
19
- {section.subSections.map((subSection, j) => (
20
- <TermsOfUseSubSection indices={[i + 1, j + 1]} subSection={subSection} key={`${i + 1}.${j}`} />
21
- ))}
22
- </View>
23
- </View>
24
- ))}
25
- </View>
26
- </View>
27
- )
28
- }
29
-
30
- export default TermsOfUse
@@ -1,44 +0,0 @@
1
- import { Text, View } from '@react-pdf/renderer'
2
- import type { FC } from 'react'
3
- import { useMemo } from 'react'
4
-
5
- type TermsOfUseSubSectionType =
6
- | string
7
- | {
8
- paragraph: string
9
- subSections: TermsOfUseSubSectionType[]
10
- }
11
-
12
- type Props = {
13
- indices: number[]
14
- subSection: TermsOfUseSubSectionType
15
- }
16
-
17
- const TermsOfUseSubSection: FC<Props> = ({ indices, subSection }) => {
18
- const { indicesString, paddingLeft } = useMemo(
19
- () => ({
20
- indicesString: indices.reduce((prev, curr, i) => `${prev}${curr}${i === indices.length - 1 ? '' : '.'}`, ''),
21
- paddingLeft: Math.max(indices.length - 2, 0) * 16
22
- }),
23
- []
24
- )
25
-
26
- return typeof subSection === 'string' ? (
27
- <View style={{ flexDirection: 'row', paddingLeft, columnGap: 16 }} key={indicesString}>
28
- <Text style={{ fontWeight: 'bold' }}>{indicesString}</Text>
29
- <Text style={{ textAlign: 'justify', flex: 1 }}>{subSection}</Text>
30
- </View>
31
- ) : 'subSections' in subSection ? (
32
- <View key={indicesString} style={{ gap: 16 }}>
33
- <View style={{ flexDirection: 'row', paddingLeft, columnGap: 16 }} key={indicesString}>
34
- <Text style={{ fontWeight: 'bold' }}>{indicesString}</Text>
35
- <Text style={{ textAlign: 'justify', flex: 1 }}>{subSection.paragraph}</Text>
36
- </View>
37
- {subSection.subSections.map((subSection, i) => (
38
- <TermsOfUseSubSection key={`${indices}.${i}`} indices={[...indices, i + 1]} subSection={subSection} />
39
- ))}
40
- </View>
41
- ) : null
42
- }
43
-
44
- export default TermsOfUseSubSection
@@ -1,66 +0,0 @@
1
- import { SignatureDetails, Subscription, SubscriptionSchedule, User, Vehicle } from '@driveflux/db'
2
- import { Document } from '@react-pdf/renderer'
3
- import { FC, useMemo } from 'react'
4
- import { PdfTemplatesSupportedLocales } from '../../types.js'
5
- import { toPdf } from '../../utils.js'
6
- import Confirmation from './Confirmation.js'
7
- import CoverPage from './CoverPage.js'
8
- import Details from './Details.js'
9
- import SubscriptionAgreementPage from './SubscriptionAgreementPage.js'
10
- import TermsOfUse from './TermsOfUse.js'
11
- import { useTranslations } from './translations.js'
12
-
13
- export type SubscriptionForAgreement = Subscription & {
14
- user: User
15
- vehicle: Vehicle
16
- schedule?: SubscriptionSchedule | null
17
- }
18
-
19
- type Options = {
20
- locale?: PdfTemplatesSupportedLocales
21
- subscription: SubscriptionForAgreement
22
- }
23
- export const generateSubscriptionAgreementPdf = async ({ locale = 'en', subscription }: Options, fileName?: string) => {
24
- if (!subscription.signature) {
25
- throw new Error('Signature not found')
26
- }
27
- return await toPdf(
28
- <SubscriptionAgreement locale={locale} signature={subscription.signature} subscription={subscription} />,
29
- fileName
30
- )
31
- }
32
-
33
- type Props = {
34
- locale?: PdfTemplatesSupportedLocales
35
- signature: SignatureDetails
36
- subscription: SubscriptionForAgreement
37
- }
38
- const SubscriptionAgreement: FC<Props> = ({ locale = 'en', signature, subscription }) => {
39
- if (!signature.signedAt) {
40
- throw new Error(`Missing 'signature.signedAt'`)
41
- }
42
-
43
- const pageProps = useMemo(() => {
44
- return {
45
- t: useTranslations(locale),
46
- userId: subscription.userId,
47
- subscriptionId: subscription.id
48
- }
49
- }, [])
50
- const { t } = pageProps
51
-
52
- return (
53
- <Document title={t.title} language={locale}>
54
- <SubscriptionAgreementPage {...pageProps}>
55
- <CoverPage tTitle={t.title} tCover={t.cover} signedAt={signature.signedAt} user={subscription.user} />
56
- </SubscriptionAgreementPage>
57
- <SubscriptionAgreementPage {...pageProps}>
58
- <TermsOfUse t={t.termsOfUse} />
59
- </SubscriptionAgreementPage>
60
- <SubscriptionAgreementPage {...pageProps}>
61
- <Details tDetails={t.details} subscription={subscription} />
62
- <Confirmation tConfirmation={t.confirmation} subscription={subscription} />
63
- </SubscriptionAgreementPage>
64
- </Document>
65
- )
66
- }