diff --git a/docx/main.ts b/docx/main.ts index 8fbdb83..ec57f4f 100644 --- a/docx/main.ts +++ b/docx/main.ts @@ -7,8 +7,10 @@ import { HorizontalPositionAlign, VerticalPositionAlign, TextRun, + AlignmentType, } from "docx"; import { join } from "path"; +import * as QR from "qrcode"; function cm(centimeters: number) { @@ -19,6 +21,10 @@ function cmToEmu(cm: number) { return Math.round(cm * 360000); } +function cmText(cm: number) { + return Math.round(cm * 567); +} + type ImgConfig = { name: string, height: number, @@ -64,6 +70,7 @@ const imgFondoDoc = new ImageRun({ relative: VerticalPositionRelativeFrom.TOP_MARGIN, offset: 0, }, + behindDocument: true, }, }); @@ -261,11 +268,11 @@ const imgEATE = new ImageRun({ const certificateName = new Paragraph({ frame: { position: { - x: cmToEmu(3.13), - y: cmToEmu(1.39), + x: cmText(3.13), + y: cmText(1.9), }, - width: cm(14.28) * 5, - height: cm(3.19) * 5, + width: cmText(14.28), + height: cmText(3.19), anchor: { horizontal: FrameAnchorType.MARGIN, vertical: FrameAnchorType.MARGIN, @@ -277,47 +284,281 @@ const certificateName = new Paragraph({ }, children: [ new TextRun({ - text: "sample text", + text: "CAPACITACIÓN EN MANEJO; MANIPULACIÓN Y TRANSPORTE DE MATERIALES Y RESIDUOS PELIGROSOS - MATPEL I - Advertencia".toUpperCase(), bold: true, font: "Arial", + size: 32, }), ], + alignment: AlignmentType.CENTER, +}); + +const certificatePersonName = new Paragraph({ + frame: { + position: { + x: cmText(0), + y: cmText(6.5), + }, + width: cmText(23), + height: cmText(1.5), + anchor: { + horizontal: FrameAnchorType.MARGIN, + vertical: FrameAnchorType.MARGIN, + }, + alignment: { + x: HorizontalPositionAlign.CENTER, + y: VerticalPositionAlign.TOP, + }, + }, + children: [ + new TextRun({ + text: "fernando enrique araoz morales".toUpperCase(), + bold: true, + font: "Arial", + allCaps: true, + size: 48, + }), + ], + alignment: AlignmentType.CENTER, +}); + +// "Se expide el presente certificado a:" +const certificateExpedite = new Paragraph({ + frame: { + position: { + x: cmText(2.85), + y: cmText(5.15), + }, + width: cmText(14.28), + height: cmText(1), + anchor: { + horizontal: FrameAnchorType.MARGIN, + vertical: FrameAnchorType.MARGIN, + }, + alignment: { + x: HorizontalPositionAlign.CENTER, + y: VerticalPositionAlign.TOP, + }, + }, + children: [ + new TextRun({ + text: "Se expide el presente certificado a:", + font: "Arial", + size: 22, + }), + ], + alignment: AlignmentType.CENTER, +}); + +// N° XXXX-202X-EEG +const certificateCode = new Paragraph({ + frame: { + position: { + x: cmText(17.1), + y: cmText(5.35), + }, + width: cmText(3.68), + height: cmText(0.7), + anchor: { + horizontal: FrameAnchorType.MARGIN, + vertical: FrameAnchorType.MARGIN, + }, + alignment: { + x: HorizontalPositionAlign.CENTER, + y: VerticalPositionAlign.TOP, + }, + }, + children: [ + new TextRun({ + text: "N° 0524-2023-EEG", + font: "Arial", + size: 20, + }), + ], + alignment: AlignmentType.CENTER, +}); + +// Identificado con dni ... +const certificateBody = new Paragraph({ + frame: { + position: { + x: cmText(1.51), + y: cmText(8.35), + }, + width: cmText(20.08), + height: cmText(3.7), + anchor: { + horizontal: FrameAnchorType.MARGIN, + vertical: FrameAnchorType.MARGIN, + }, + alignment: { + x: HorizontalPositionAlign.CENTER, + y: VerticalPositionAlign.TOP, + }, + }, + children: [ + new TextRun({ + text: "Identificado con DNI N° ", + font: "Arial", + size: 24, + }), + new TextRun({ + text: "74059695", + font: "Arial", + size: 24, + bold: true, + }), + new TextRun({ + text: ", al haber aprobado el curso de capacitación sobre ", + font: "Arial", + size: 24, + }), + new TextRun({ + text: "MANEJO DE MATERIALES Y RESIDUOS PELIGROSOS - MATPEL I - Advertencia", + font: "Arial", + size: 24, + bold: true, + }), + new TextRun({ + text: ", según lo estipulado en la Ley N°28256 (ley que regula el Transporte de Materiales y Residuos Peligrosos) y Decreto Supremo N° 021-2008-MTC (Reglamento Nacional de Transporte Terrestre de Materiales y Residuos Peligrosos) con una duración de 12 horas lectivas.\n", + font: "Arial", + size: 24, + }), + ], + alignment: AlignmentType.JUSTIFIED, +}); + +// Se expide certificado... +const certificateFinishLabel = new Paragraph({ + frame: { + position: { + x: cmText(1.52), + y: cmText(11.25), + }, + width: cmText(20.1), + height: cmText(0.8), + anchor: { + horizontal: FrameAnchorType.MARGIN, + vertical: FrameAnchorType.MARGIN, + }, + alignment: { + x: HorizontalPositionAlign.CENTER, + y: VerticalPositionAlign.TOP, + }, + }, + children: [ + new TextRun({ + text: "Se expide certificado para los fines que se estime conveniente.", + font: "Arial", + size: 24, + }), + ], + alignment: AlignmentType.CENTER, +}); + +// Fecha de Emision: ... +const certificateDate = new Paragraph({ + frame: { + position: { + x: cmText(16), + y: cmText(16.5), + }, + width: cmText(9), + height: cmText(1.4), + anchor: { + horizontal: FrameAnchorType.MARGIN, + vertical: FrameAnchorType.MARGIN, + }, + alignment: { + x: HorizontalPositionAlign.CENTER, + y: VerticalPositionAlign.TOP, + }, + }, + children: [ + new TextRun({ + text: "Fecha de Emisión:\t\t{fecha_emision}", + font: "Arial", + size: 20, + break: 1, + }), + new TextRun({ + text: "Fecha de Expiración:\t\t{fecha_expiracion}", + font: "Arial", + size: 20, + break: 1, + }), + ], + alignment: AlignmentType.LEFT, }); -const doc = new Document({ - sections: [ - { - properties: { - page: { - size: { - orientation: PageOrientation.LANDSCAPE, + +async function create() { + const qr = await QR.toDataURL(/* join(__dirname, "img", "qr.png"), */ `https://www.eegsac.com/alumnoscertificados.php?DNI=${"74059695"}`, {margin: 1}); + + const imgQR = new ImageRun({ + data: qr, // fs.readFileSync(join(__dirname, "img", "qr.png")), + transformation: { + height: cm(2.47), + width: cm(2.47), + }, + floating: { + zIndex: 1, + horizontalPosition: { + relative: HorizontalPositionRelativeFrom.LEFT_MARGIN, + offset: cmToEmu(26.3), + }, + verticalPosition: { + relative: VerticalPositionRelativeFrom.TOP_MARGIN, + offset: cmToEmu(16.48), + }, + }, + }); + + const doc = new Document({ + sections: [ + { + properties: { + page: { + size: { + orientation: PageOrientation.LANDSCAPE, + }, }, }, + children: [ + certificateName, + certificatePersonName, + certificateExpedite, + certificateCode, + certificateBody, + certificateFinishLabel, + certificateDate, + new Paragraph({ + children: [ + imgFondoDoc, + imgMatpel, + imgCIP, + imgCEE, + imgMTC, + imgEEG, + imgOSHA, + imgAguila, + imgMichigan, + imgCEEM, + imgEATE, + imgQR, + ], + }), + ], }, - children: [ - certificateName, - new Paragraph({ - children: [ - imgFondoDoc, - imgMatpel, - imgCIP, - imgCEE, - imgMTC, - imgEEG, - imgOSHA, - imgAguila, - imgMichigan, - imgCEEM, - imgEATE, - ], - }), - ], - }, - ], -}); + ], + }); -// Used to export the file into a .docx file -Packer.toBuffer(doc).then((buffer) => { - fs.writeFileSync("My Document.docx", buffer); -}); + // Used to export the file into a .docx file + Packer.toBuffer(doc).then((buffer) => { + fs.writeFileSync("My Document.docx", buffer); + // fs.rmSync(join(__dirname, "temp", "qr.png")); + }); +} + +create(); diff --git a/package.json b/package.json index 62539b0..db7899a 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@types/express": "^4.17.13", "@types/jest": "29.5.0", "@types/node": "18.15.11", + "@types/qrcode": "^1.5.0", "@types/supertest": "^2.0.11", "@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/parser": "^5.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 48ba978..4091ae7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,6 +72,9 @@ devDependencies: '@types/node': specifier: 18.15.11 version: 18.15.11 + '@types/qrcode': + specifier: ^1.5.0 + version: 1.5.0 '@types/supertest': specifier: ^2.0.11 version: 2.0.12 @@ -1735,6 +1738,12 @@ packages: resolution: {integrity: sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==} dev: true + /@types/qrcode@1.5.0: + resolution: {integrity: sha512-x5ilHXRxUPIMfjtM+1vf/GPTRWZ81nqscursm5gMznJeK9M0YnZ1c3bEvRLQ0zSSgedLx1J6MGL231ObQGGhaA==} + dependencies: + '@types/node': 18.15.11 + dev: true + /@types/qs@6.9.7: resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} dev: true diff --git a/src/app.module.ts b/src/app.module.ts index cc09119..5a7d70d 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -12,7 +12,7 @@ import { SubjectService } from "./controller/subject/subject.service"; import * as dotenv from "dotenv"; // Must be done before initializing DB. -dotenv.config(); +console.log(dotenv.config()); @Module({ imports: [ diff --git a/src/controller/certificate/certificate.template.ts b/src/controller/certificate/certificate.template.ts index 00d0c40..cf871bc 100644 --- a/src/controller/certificate/certificate.template.ts +++ b/src/controller/certificate/certificate.template.ts @@ -8,7 +8,7 @@ export function template(ssr: string): string { Registrar certificados - EEGSAC - + ${generateHydrationScript()} @@ -16,7 +16,7 @@ export function template(ssr: string): string { ${ssr} - + `; diff --git a/src/views/components/NewRegister.tsx b/src/views/components/NewRegister.tsx index 790c162..2862436 100644 --- a/src/views/components/NewRegister.tsx +++ b/src/views/components/NewRegister.tsx @@ -1,9 +1,8 @@ -import { createEffect, createSignal, onMount, Show } from "solid-js"; +import { createSignal, onMount, Show } from "solid-js"; import type { CursoGIE } from "../../model/CursoGIE/cursoGIE.entity"; import { SearchableSelect } from "./NewRegister/SearchableSelect"; import { JSX } from "solid-js/jsx-runtime"; import { Person } from "src/types/Person"; -import QR from "qrcode"; type HTMLEventFn = JSX.EventHandlerUnion void const [selectedSubject, setSelectedSubject] = createSignal(null); - const [qrBase64, setQrBase64] = createSignal(null); - // Update QR - createEffect(() => { - if (props.person !== null) { - QR.toDataURL(`https://www.eegsac.com/alumnosceertificados.php?DNI=${props.person.dni}`, (err, res) => { - if (err) { - console.error("Error creating QR code"); - return; - } - setQrBase64(res); - }); - } - }); + const datePicker = ( void disabled={loading()} /> -
- -
diff --git a/src/views/components/Search.tsx b/src/views/components/Search.tsx index 6398230..613d766 100644 --- a/src/views/components/Search.tsx +++ b/src/views/components/Search.tsx @@ -1,7 +1,8 @@ -import { createSignal, Show } from "solid-js"; +import { createEffect, createSignal, Show } from "solid-js"; import { JSX } from "solid-js/jsx-runtime"; import { Person } from "../../types/Person"; import { RegisterPerson } from "./Search/RegisterPerson"; +import QR from "qrcode"; type HTMLEventFn = JSX.EventHandlerUnion void}) { const [loading, setLoading] = createSignal(false); const [error, setError] = createSignal(""); const [warning, setWarning] = createSignal(""); + const [qrBase64, setQrBase64] = createSignal(null); + + // Update QR + createEffect(() => { + if (dni() !== "") { + QR.toDataURL(`https://www.eegsac.com/alumnoscertificados.php?DNI=${dni()}`, {margin: 1}, (err, res) => { + if (err) { + console.error("Error creating QR code"); + return; + } + + setQrBase64(res); + }); + } + }); /* Get the user data from the DB @@ -51,59 +67,64 @@ export function Search(props: {setPerson: (p: Person | null) => void}) { }; return ( -
-

1. Buscar persona

-
- -
- +
+

1. Buscar persona

+ + +
+ setDni(e.target.value)} - disabled={loading()} - /> -
-
- setDni(e.target.value)} + disabled={loading()} + /> +
+
+ - + type="submit" + value="Buscar" + disabled={loading()} + /> + -

+

Error: -
- {error()} -

+
+ {error()} +

-

+

Advertencia: -
- {warning()} -

+
+ {warning()} +

- - - + + + +
+
+ +
); }