@appcorp/fusion-storybook 0.3.50 → 0.3.52

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.
@@ -14,7 +14,7 @@ import { ADMISSION_STATUS, GENDER, } from "../../../type";
14
14
  import { ADMISSION_API_ROUTES, DISCOUNT_CODE_API_ROUTES, } from "../../../constants";
15
15
  import { admissionFormValidation } from "../validate";
16
16
  import { getCachedWorkspaceSync } from "../../workspace/cache";
17
- import { generateAdmissionReceiptPDF, } from "../../../utils/admission-pdf";
17
+ import { downloadAdmissionFormPDF, } from "../../../utils/admission-pdf";
18
18
  import { normalizeIdNumber } from "../../../utils/id-number";
19
19
  import { toE164Phone } from "../../../utils/to-e164-phone";
20
20
  import { formatPhoneDisplay } from "@react-pakistan/util-functions/general/format-phone-display";
@@ -469,7 +469,7 @@ export const useAdmissionModule = () => {
469
469
  admissionStatus: admissionDetails.admissionStatus,
470
470
  logo: logoBase64.base64,
471
471
  };
472
- await generateAdmissionReceiptPDF(pdfData);
472
+ await downloadAdmissionFormPDF(pdfData);
473
473
  }
474
474
  catch (_h) {
475
475
  showToast(t("messagesPrintFailed"), TOAST_VARIANT.ERROR);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appcorp/fusion-storybook",
3
- "version": "0.3.50",
3
+ "version": "0.3.52",
4
4
  "scripts": {
5
5
  "build-storybook": "storybook build",
6
6
  "build:next": "next build",
@@ -37,29 +37,25 @@
37
37
  ]
38
38
  },
39
39
  "devDependencies": {
40
- "@appcorp/app-corp-vista": "^1.0.0",
41
- "@appcorp/shadcn": "^1.1.99",
40
+ "@appcorp/shadcn": "^2.0.2",
42
41
  "@chromatic-com/storybook": "^5.1.2",
43
42
  "@commitlint/cli": "^20.5.0",
44
43
  "@commitlint/config-conventional": "^20.5.0",
45
- "@pdfme/common": "^6",
46
- "@pdfme/generator": "^6",
47
- "@pdfme/schemas": "^6",
48
44
  "@playwright/test": "^1.59.1",
49
- "@radix-ui/react-avatar": "^1.1.11",
50
- "@radix-ui/react-checkbox": "^1.3.3",
51
- "@radix-ui/react-dialog": "^1.1.15",
52
- "@radix-ui/react-dropdown-menu": "^2.1.16",
45
+ "@radix-ui/react-avatar": "^1.2.3",
46
+ "@radix-ui/react-checkbox": "^1.3.8",
47
+ "@radix-ui/react-dialog": "^1.1.20",
48
+ "@radix-ui/react-dropdown-menu": "^2.1.21",
53
49
  "@radix-ui/react-icons": "^1.3.2",
54
- "@radix-ui/react-label": "^2.1.8",
55
- "@radix-ui/react-popover": "^1.1.15",
56
- "@radix-ui/react-radio-group": "^1.3.8",
57
- "@radix-ui/react-select": "^2.2.6",
58
- "@radix-ui/react-separator": "^1.1.8",
59
- "@radix-ui/react-slider": "^1.3.6",
60
- "@radix-ui/react-slot": "^1.2.4",
61
- "@radix-ui/react-toast": "^1.2.15",
62
- "@react-pakistan/util-functions": "^2.0.2",
50
+ "@radix-ui/react-label": "^2.1.12",
51
+ "@radix-ui/react-popover": "^1.1.20",
52
+ "@radix-ui/react-radio-group": "^1.4.4",
53
+ "@radix-ui/react-select": "^2.3.4",
54
+ "@radix-ui/react-separator": "^1.1.12",
55
+ "@radix-ui/react-slider": "^1.4.4",
56
+ "@radix-ui/react-slot": "^1.3.0",
57
+ "@radix-ui/react-toast": "^1.2.20",
58
+ "@react-pakistan/util-functions": "^3.0.1",
63
59
  "@storybook/addon-a11y": "^10.3.4",
64
60
  "@storybook/addon-docs": "^10.3.4",
65
61
  "@storybook/addon-onboarding": "^10.3.4",
@@ -0,0 +1,37 @@
1
+ export interface AdmissionPDFData {
2
+ firstName: string;
3
+ lastName: string;
4
+ studentIdNumber: string;
5
+ gender: string;
6
+ dob: string;
7
+ registrationCode: string;
8
+ discountCode?: string;
9
+ fatherFirstName: string;
10
+ fatherLastName: string;
11
+ fatherIdNumber: string;
12
+ fatherMobile: string;
13
+ fatherOccupation?: string;
14
+ fatherOrganization?: string;
15
+ motherFirstName: string;
16
+ motherLastName: string;
17
+ motherIdNumber: string;
18
+ motherMobile: string;
19
+ address: string;
20
+ city: string;
21
+ state: string;
22
+ country: string;
23
+ classForAdmission: string;
24
+ previousSchool?: string;
25
+ siblings?: string;
26
+ notes?: string;
27
+ admissionNotes?: string;
28
+ schoolName?: string;
29
+ schoolAddress?: string;
30
+ schoolPhone?: string;
31
+ schoolEmail?: string;
32
+ submissionDate?: string;
33
+ admissionStatus?: string;
34
+ logo?: string;
35
+ emergencyContact?: string;
36
+ }
37
+ export declare function buildAdmissionFormHtml(data: AdmissionPDFData): string;
@@ -0,0 +1,321 @@
1
+ function escapeHtml(str) {
2
+ if (str == null)
3
+ return "";
4
+ return String(str)
5
+ .replace(/&/g, "&")
6
+ .replace(/</g, "&lt;")
7
+ .replace(/>/g, "&gt;")
8
+ .replace(/"/g, "&quot;");
9
+ }
10
+ function fmt(val) {
11
+ if (val == null || val === "")
12
+ return "—";
13
+ return escapeHtml(val);
14
+ }
15
+ function section(title, content) {
16
+ return `
17
+ <div class="section">
18
+ <div class="section-title">${escapeHtml(title)}</div>
19
+ <div class="section-body">${content}</div>
20
+ </div>`;
21
+ }
22
+ function row(label, value) {
23
+ return `
24
+ <div class="field-row">
25
+ <span class="field-label">${escapeHtml(label)}:</span>
26
+ <span class="field-value">${value}</span>
27
+ </div>`;
28
+ }
29
+ export function buildAdmissionFormHtml(data) {
30
+ const studentName = `${escapeHtml(data.firstName)} ${escapeHtml(data.lastName)}`;
31
+ const fatherName = `${escapeHtml(data.fatherFirstName)} ${escapeHtml(data.fatherLastName)}`;
32
+ const motherName = `${escapeHtml(data.motherFirstName)} ${escapeHtml(data.motherLastName)}`;
33
+ const homeAddress = `${fmt(data.address)}, ${fmt(data.city)}, ${fmt(data.state)}, ${fmt(data.country)}`;
34
+ const date = data.submissionDate || new Date().toLocaleDateString();
35
+ const emergencyContact = data.emergencyContact === "Mother" ? "Mother" : "Father";
36
+ const logoHtml = data.logo
37
+ ? `<img src="${data.logo.startsWith("data:") ? escapeHtml(data.logo) : `data:image/png;base64,${escapeHtml(data.logo)}`}" alt="School Logo" class="logo" />`
38
+ : "";
39
+ const html = `<!DOCTYPE html>
40
+ <html>
41
+ <head>
42
+ <meta charset="utf-8">
43
+ <title>Admission Form - ${escapeHtml(data.registrationCode)}</title>
44
+ <style>
45
+ @import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;600;700&display=swap");
46
+
47
+ @page { margin: 12mm 15mm; size: A4 portrait; }
48
+
49
+ *, *::before, *::after {
50
+ font-family: "Roboto", system-ui, -apple-system, sans-serif;
51
+ box-sizing: border-box;
52
+ }
53
+
54
+ body {
55
+ margin: 0;
56
+ padding: 0;
57
+ font-size: 10pt;
58
+ color: #1f2937;
59
+ line-height: 1.5;
60
+ }
61
+
62
+ .header {
63
+ display: flex;
64
+ align-items: center;
65
+ gap: 14px;
66
+ padding-bottom: 12px;
67
+ margin-bottom: 16px;
68
+ border-bottom: 2px solid #2563eb;
69
+ }
70
+
71
+ .logo {
72
+ width: 64px;
73
+ height: 64px;
74
+ object-fit: contain;
75
+ }
76
+
77
+ .school-info h1 {
78
+ margin: 0;
79
+ font-size: 14pt;
80
+ font-weight: 700;
81
+ color: #1e3a5f;
82
+ }
83
+
84
+ .school-info p {
85
+ margin: 2px 0 0;
86
+ font-size: 8.5pt;
87
+ color: #6b7280;
88
+ }
89
+
90
+ .form-title {
91
+ text-align: center;
92
+ font-size: 16pt;
93
+ font-weight: 700;
94
+ color: #1e3a5f;
95
+ margin: 0 0 16px;
96
+ text-transform: uppercase;
97
+ letter-spacing: 1px;
98
+ }
99
+
100
+ .reg-row {
101
+ display: flex;
102
+ justify-content: space-between;
103
+ font-size: 9pt;
104
+ color: #374151;
105
+ margin-bottom: 14px;
106
+ padding: 6px 10px;
107
+ background: #f9fafb;
108
+ border: 1px solid #e5e7eb;
109
+ border-radius: 4px;
110
+ }
111
+
112
+ .section {
113
+ margin-bottom: 12px;
114
+ }
115
+
116
+ .section-title {
117
+ font-size: 10pt;
118
+ font-weight: 700;
119
+ color: #1e3a5f;
120
+ border-bottom: 2px solid #d1d5db;
121
+ padding-bottom: 3px;
122
+ margin-bottom: 6px;
123
+ text-transform: uppercase;
124
+ letter-spacing: 0.5px;
125
+ }
126
+
127
+ .section-body {
128
+ padding: 2px 0;
129
+ }
130
+
131
+ .field-row {
132
+ display: flex;
133
+ padding: 2px 0;
134
+ font-size: 9.5pt;
135
+ }
136
+
137
+ .field-label {
138
+ font-weight: 600;
139
+ min-width: 140px;
140
+ color: #374151;
141
+ flex-shrink: 0;
142
+ }
143
+
144
+ .field-value {
145
+ color: #111827;
146
+ }
147
+
148
+ .two-col {
149
+ display: grid;
150
+ grid-template-columns: 1fr 1fr;
151
+ gap: 0 16px;
152
+ }
153
+
154
+ .three-col {
155
+ display: grid;
156
+ grid-template-columns: 1fr 1fr 1fr;
157
+ gap: 0 16px;
158
+ }
159
+
160
+ .parent-subsection {
161
+ margin-bottom: 4px;
162
+ }
163
+
164
+ .parent-subsection h4 {
165
+ margin: 4px 0 2px;
166
+ font-size: 9.5pt;
167
+ font-weight: 600;
168
+ color: #4b5563;
169
+ }
170
+
171
+ .terms {
172
+ margin-top: 18px;
173
+ padding: 10px 12px;
174
+ background: #f9fafb;
175
+ border: 1px solid #e5e7eb;
176
+ border-radius: 4px;
177
+ font-size: 8.5pt;
178
+ color: #4b5563;
179
+ line-height: 1.6;
180
+ }
181
+
182
+ .terms p {
183
+ margin: 0;
184
+ }
185
+ .terms p + p {
186
+ margin-top: 4px;
187
+ }
188
+
189
+ .signature-area {
190
+ display: flex;
191
+ justify-content: space-between;
192
+ margin-top: 28px;
193
+ padding-top: 8px;
194
+ border-top: 1px solid #d1d5db;
195
+ }
196
+
197
+ .signature-block {
198
+ text-align: center;
199
+ min-width: 120px;
200
+ }
201
+
202
+ .signature-block .label {
203
+ font-size: 9pt;
204
+ font-weight: 700;
205
+ color: #374151;
206
+ text-transform: uppercase;
207
+ letter-spacing: 0.5px;
208
+ }
209
+
210
+ .signature-line {
211
+ margin-top: 32px;
212
+ border-top: 1px solid #9ca3af;
213
+ width: 160px;
214
+ }
215
+
216
+ .signature-block .hint {
217
+ font-size: 7.5pt;
218
+ color: #9ca3af;
219
+ margin-top: 2px;
220
+ }
221
+
222
+ .no-break {
223
+ break-inside: avoid;
224
+ }
225
+ </style>
226
+ </head>
227
+ <body>
228
+ <div class="header">
229
+ ${logoHtml}
230
+ <div class="school-info">
231
+ <h1>${fmt(data.schoolName || "School Name")}</h1>
232
+ <p>${fmt(data.schoolAddress)}${data.schoolPhone ? ` &bull; ${fmt(data.schoolPhone)}` : ""}${data.schoolEmail ? ` &bull; ${fmt(data.schoolEmail)}` : ""}</p>
233
+ </div>
234
+ </div>
235
+
236
+ <h2 class="form-title">Admission Form</h2>
237
+
238
+ <div class="reg-row">
239
+ <span><strong>Registration Code:</strong> ${fmt(data.registrationCode)}</span>
240
+ <span><strong>Date:</strong> ${fmt(date)}</span>
241
+ </div>
242
+
243
+ ${section("Student Details", `
244
+ <div class="two-col">
245
+ ${row("Student Name", studentName)}
246
+ ${row("Class for Admission", fmt(data.classForAdmission))}
247
+ ${row("Government ID", fmt(data.studentIdNumber))}
248
+ <div class="field-row">
249
+ <span class="field-label">Gender:</span>
250
+ <span class="field-value">${fmt(data.gender)}</span>
251
+ </div>
252
+ </div>
253
+ <div class="two-col">
254
+ ${row("Date of Birth", fmt(data.dob))}
255
+ ${data.discountCode ? row("Discount Code", fmt(data.discountCode)) : ""}
256
+ </div>
257
+ `)}
258
+
259
+ ${section("Parent Details", `
260
+ <div class="parent-subsection">
261
+ <h4>Father</h4>
262
+ <div class="two-col">
263
+ ${row("Name", fatherName)}
264
+ ${row("ID / CNIC", fmt(data.fatherIdNumber))}
265
+ ${row("Occupation", fmt(data.fatherOccupation))}
266
+ ${row("Organization", fmt(data.fatherOrganization))}
267
+ </div>
268
+ ${row("Mobile", fmt(data.fatherMobile))}
269
+ </div>
270
+ <div class="parent-subsection">
271
+ <h4>Mother</h4>
272
+ <div class="two-col">
273
+ ${row("Name", motherName)}
274
+ ${row("ID / CNIC", fmt(data.motherIdNumber))}
275
+ ${row("Mobile", fmt(data.motherMobile))}
276
+ </div>
277
+ </div>
278
+ `)}
279
+
280
+ ${section("Home Address", `
281
+ <div class="field-row">
282
+ <span class="field-value">${homeAddress}</span>
283
+ </div>
284
+ `)}
285
+
286
+ ${section("Emergency Details", `
287
+ <div class="two-col">
288
+ ${row("Emergency Contact", emergencyContact)}
289
+ ${data.notes ? row("Notes", fmt(data.notes)) : ""}
290
+ </div>
291
+ `)}
292
+
293
+ ${section("Admission Details", `
294
+ <div class="two-col">
295
+ ${row("Student Name", studentName)}
296
+ ${row("Start Date", fmt(date))}
297
+ ${row("Section", "—")}
298
+ </div>
299
+ `)}
300
+
301
+ <div class="terms">
302
+ <p><strong>Terms &amp; Conditions:</strong></p>
303
+ <p>I confirm that the information provided above is true and correct to the best of my knowledge. I agree to abide by the rules and regulations of the institution. The management reserves the right to cancel admission if any information is found to be incorrect or incomplete.</p>
304
+ </div>
305
+
306
+ <div class="signature-area">
307
+ <div class="signature-block">
308
+ <div class="label">Principal</div>
309
+ <div class="signature-line"></div>
310
+ <div class="hint">Signature</div>
311
+ </div>
312
+ <div class="signature-block">
313
+ <div class="label">Parent / Guardian</div>
314
+ <div class="signature-line"></div>
315
+ <div class="hint">Signature</div>
316
+ </div>
317
+ </div>
318
+ </body>
319
+ </html>`;
320
+ return html;
321
+ }