diff --git a/day10/app.js b/day10/app.js index 97a1728..0ae488b 100644 --- a/day10/app.js +++ b/day10/app.js @@ -1,11 +1,12 @@ -var createError = require('http-errors'); -var express = require('express'); -var path = require('path'); -var cookieParser = require('cookie-parser'); -var logger = require('morgan'); +var createError = require("http-errors"); +var express = require("express"); +var path = require("path"); +var cookieParser = require("cookie-parser"); +var logger = require("morgan"); -var indexRouter = require('./routes/index'); -var usersRouter = require('./routes/users'); +var indexRouter = require("./routes/index"); +var usersRouter = require("./routes/users"); +const codeRouter = require("./routes/code"); const db = require("./models"); var cors = require("cors"); @@ -13,17 +14,18 @@ var cors = require("cors"); var app = express(); app.set("db", db); // view engine setup -app.set('views', path.join(__dirname, 'views')); -app.set('view engine', 'jade'); +app.set("views", path.join(__dirname, "views")); +app.set("view engine", "jade"); app.use(cors()); -app.use(logger('dev')); +app.use(logger("dev")); app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); -app.use(express.static(path.join(__dirname, 'public'))); +app.use(express.static(path.join(__dirname, "public"))); -app.use('/', indexRouter); -app.use('/users', usersRouter); +app.use("/", indexRouter); +app.use("/users", usersRouter); +app.use("/api/v1/code", codeRouter); // catch 404 and forward to error handler app.use(function (req, res, next) { @@ -34,11 +36,11 @@ app.use(function (req, res, next) { app.use(function (err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; - res.locals.error = req.app.get('env') === 'development' ? err : {}; + res.locals.error = req.app.get("env") === "development" ? err : {}; // render the error page res.status(err.status || 500); - res.render('error'); + res.render("error"); }); module.exports = app; diff --git a/day10/bin/www b/day10/bin/www index cd1a62f..7742167 100755 --- a/day10/bin/www +++ b/day10/bin/www @@ -4,16 +4,16 @@ * Module dependencies. */ -var app = require('../app'); -var debug = require('debug')('day-1:server'); -var http = require('http'); +var app = require("../app"); +var debug = require("debug")("day-1:server"); +var http = require("http"); /** * Get port from environment and store in Express. */ -var port = normalizePort(process.env.PORT || '3000'); -app.set('port', port); +var port = normalizePort(process.env.PORT || "3000"); +app.set("port", port); /** * Create HTTP server. @@ -26,8 +26,8 @@ var server = http.createServer(app); */ server.listen(port); -server.on('error', onError); -server.on('listening', onListening); +server.on("error", onError); +server.on("listening", onListening); /** * Normalize a port into a number, string, or false. @@ -54,22 +54,20 @@ function normalizePort(val) { */ function onError(error) { - if (error.syscall !== 'listen') { + if (error.syscall !== "listen") { throw error; } - var bind = typeof port === 'string' - ? 'Pipe ' + port - : 'Port ' + port; + var bind = typeof port === "string" ? "Pipe " + port : "Port " + port; // handle specific listen errors with friendly messages switch (error.code) { - case 'EACCES': - console.error(bind + ' requires elevated privileges'); + case "EACCES": + console.error(bind + " requires elevated privileges"); process.exit(1); break; - case 'EADDRINUSE': - console.error(bind + ' is already in use'); + case "EADDRINUSE": + console.error(bind + " is already in use"); process.exit(1); break; default: @@ -83,8 +81,7 @@ function onError(error) { function onListening() { var addr = server.address(); - var bind = typeof addr === 'string' - ? 'pipe ' + addr - : 'port ' + addr.port; - debug('Listening on ' + bind); + var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port; + debug("Listening on " + bind); + console.log("Server listening on:", bind); } diff --git a/day10/invoice.html b/day10/invoice.html new file mode 100644 index 0000000..0a9e163 --- /dev/null +++ b/day10/invoice.html @@ -0,0 +1,191 @@ + + + + + A simple, clean, and responsive HTML invoice template + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+ + + Invoice #: 123
+ Created: January 1, 2023
+ Due: February 1, 2023 +
+
+ + + + + + +
+ Sparksuite, Inc.
+ 12345 Sunny Road
+ Sunnyville, CA 12345 +
+ Acme Corp.
+ John Doe
+ john@example.com +
+
Payment MethodCheck #
Check1000
ItemPrice
Website design$300.00
Total: $385.00
+
+ + diff --git a/day10/package.json b/day10/package.json index b96eef4..fe13f20 100644 --- a/day10/package.json +++ b/day10/package.json @@ -3,18 +3,22 @@ "version": "0.0.0", "private": true, "scripts": { - "start": "node ./bin/www" + "start": "node ./bin/www", + "dev": "node --watch --env-file=.env ./bin/www" }, "dependencies": { "cookie-parser": "~1.4.4", "cors": "^2.8.5", "debug": "~2.6.9", "express": "~4.16.1", + "html-pdf-node": "^1.0.8", "http-errors": "~1.6.3", "jade": "~1.11.0", "jsonwebtoken": "^8.5.1", "morgan": "~1.9.1", "mysql2": "^2.3.3", + "node-input-validator": "^4.5.1", + "qrcode": "^1.5.4", "sequelize": "^6.15.1" } } diff --git a/day10/routes/code.js b/day10/routes/code.js new file mode 100644 index 0000000..55bb79b --- /dev/null +++ b/day10/routes/code.js @@ -0,0 +1,29 @@ +const express = require("express"); +const router = express.Router(); +const fs = require("fs"); +const path = require("path"); +const pdf = require("html-pdf-node"); + +router.get("/:code", async (req, res) => { + const { amount = 1, service = "software service" } = req.query; + + // Read the invoice template + const templatePath = path.join(__dirname, "../invoice.html"); + let html = fs.readFileSync(templatePath, "utf8"); + + // Replace placeholders in the template + html = html + .replace("Website design", service) + .replace("$300.00", `$${amount}.00`) + .replace("Total: $385.00", `Total: $${amount}.00`); + + // Generate PDF + let file = { content: html }; + pdf.generatePdf(file, { format: "A4" }).then((pdfBuffer) => { + res.setHeader("Content-Type", "application/pdf"); + res.setHeader("Content-Disposition", "attachment; filename=invoice.pdf"); + res.send(pdfBuffer); + }); +}); + +module.exports = router; diff --git a/day10/routes/index.js b/day10/routes/index.js index ecca96a..4ef9866 100644 --- a/day10/routes/index.js +++ b/day10/routes/index.js @@ -1,9 +1,22 @@ -var express = require('express'); +var express = require("express"); var router = express.Router(); +const QRCode = require("qrcode"); /* GET home page. */ -router.get('/', function(req, res, next) { - res.render('index', { title: 'Express' }); +router.get("/", function (req, res, next) { + res.render("index", { title: "Express" }); +}); + +router.get("/code", async function (req, res, next) { + const code = Math.random().toString(36).substring(2, 8); // random code + const qrUrl = `/api/v1/code/${code}?amount=1&service=software%20service`; + const qrData = await QRCode.toDataURL( + `http://localhost:${process.env.PORT || 3000}${qrUrl}` + ); + res.render("code", { + qrData, + qrUrl: `http://localhost:${process.env.PORT || 3000}${qrUrl}`, + }); }); module.exports = router; diff --git a/day10/views/code.jade b/day10/views/code.jade new file mode 100644 index 0000000..3ff3419 --- /dev/null +++ b/day10/views/code.jade @@ -0,0 +1,6 @@ +extends layout + +block content + h1 QR Code + img(src=qrData) + p Link: #{qrUrl} \ No newline at end of file