Skip to content

Commit

Permalink
Merge branch 'ramakevin' pdf-generator
Browse files Browse the repository at this point in the history
  • Loading branch information
KevinStifel committed Oct 16, 2024
2 parents 6f00883 + 5dfea4b commit a0acdcb
Show file tree
Hide file tree
Showing 13 changed files with 254 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

# dependencies
/node_modules
!pdf-generator/node_modules/
/.pnp
.pnp.js
/package-lock.json
/yarn.lock

# testing
/coverage
Expand Down
18 changes: 18 additions & 0 deletions .serverless/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"unknown": {
"versionSfCore": null,
"versionFramework": "4.4.6",
"isWithinCompose": false,
"composeOrgName": null,
"composeServiceName": null,
"command": [],
"options": {},
"error": null,
"machineId": "55ce82351452d045dae40665b323edd6",
"serviceProviderAwsCfStackId": null,
"serviceProviderAwsCfStackCreated": null,
"serviceProviderAwsCfStackUpdated": null,
"serviceProviderAwsCfStackStatus": null,
"serviceProviderAwsCfStackOutputs": null
}
}
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "entrega1",
"private": true,
"type": "module",
"dependencies": {
"@auth0/auth0-react": "^2.2.4",
"@svgr/webpack": "^8.1.0",
Expand All @@ -10,9 +11,10 @@
"axios": "^1.7.7",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "^5.0.1",
"resolve-url-loader": "^5.0.0",
"svgo": "^3.3.2",
"react-scripts": "5.0.1",
"serverless": "^4.4.6",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
3 changes: 3 additions & 0 deletions pdf-generator/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
.serverless
/yarn.lock
76 changes: 76 additions & 0 deletions pdf-generator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<!--
title: 'Serverless Framework Node Express API on AWS'
description: 'This template demonstrates how to develop and deploy a simple Node Express API running on AWS Lambda using the Serverless Framework.'
layout: Doc
framework: v4
platform: AWS
language: nodeJS
priority: 1
authorLink: 'https://github.com/serverless'
authorName: 'Serverless, Inc.'
authorAvatar: 'https://avatars1.githubusercontent.com/u/13742415?s=200&v=4'
-->

# Serverless Framework Node Express API on AWS

This template demonstrates how to develop and deploy a simple Node Express API service running on AWS Lambda using the Serverless Framework.

This template configures a single function, `api`, which is responsible for handling all incoming requests using the `httpApi` event. To learn more about `httpApi` event configuration options, please refer to [httpApi event docs](https://www.serverless.com/framework/docs/providers/aws/events/http-api/). As the event is configured in a way to accept all incoming requests, the Express.js framework is responsible for routing and handling requests internally. This implementation uses the `serverless-http` package to transform the incoming event request payloads to payloads compatible with Express.js. To learn more about `serverless-http`, please refer to the [serverless-http README](https://github.com/dougmoscrop/serverless-http).

## Usage

### Deployment

Install dependencies with:

```
npm install
```

and then deploy with:

```
serverless deploy
```

After running deploy, you should see output similar to:

```
Deploying "aws-node-express-api" to stage "dev" (us-east-1)
✔ Service deployed to stack aws-node-express-api-dev (96s)
endpoint: ANY - https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com
functions:
api: aws-node-express-api-dev-api (2.3 kB)
```

_Note_: In current form, after deployment, your API is public and can be invoked by anyone. For production deployments, you might want to configure an authorizer. For details on how to do that, refer to [`httpApi` event docs](https://www.serverless.com/framework/docs/providers/aws/events/http-api/).

### Invocation

After successful deployment, you can call the created application via HTTP:

```
curl https://xxxxxxx.execute-api.us-east-1.amazonaws.com/
```

Which should result in the following response:

```json
{ "message": "Hello from root!" }
```

### Local development

The easiest way to develop and test your function is to use the `dev` command:

```
serverless dev
```

This will start a local emulator of AWS Lambda and tunnel your requests to and from AWS Lambda, allowing you to interact with your function as if it were running in the cloud.

Now you can invoke the function as before, but this time the function will be executed locally. Now you can develop your function locally, invoke it, and see the results immediately without having to re-deploy.

When you are done developing, don't forget to run `serverless deploy` to deploy the function to the cloud.
53 changes: 53 additions & 0 deletions pdf-generator/handler.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
const serverless = require("serverless-http");
const express = require("express");
const AWS = require("aws-sdk");
const { PDFDocument } = require("pdf-lib");

const app = express();
const S3 = new AWS.S3();

app.use(express.json());

app.post("/generate", async (req, res) => {
try {
const { userData, matchData } = req.body;

if (!userData || !matchData) {
return res.status(400).json({ message: "Datos incompletos" });
}

const { home, away } = matchData.teams;

const pdfDoc = await PDFDocument.create();
const page = pdfDoc.addPage([600, 400]);

page.drawText(`Usuario: ${userData.name}`, { x: 50, y: 330 });
page.drawText(`Correo: ${userData.email}`, { x: 50, y: 310 });
page.drawText(`Partido:`, { x: 50, y: 290 });
page.drawText(`Equipo Local: ${home.name}`, { x: 50, y: 270 });
page.drawText(`Equipo Visitante: ${away.name}`, { x: 50, y: 250 });
page.drawText(`Fecha del Partido: ${matchData.date}`, { x: 50, y: 230 });
page.drawText(`Monto de la compra: ${matchData.amount}`, { x: 50, y: 210 });

const pdfBytes = await pdfDoc.save();

const params = {
Bucket: 'node-craft',
Key: `boletas/${userData.name}_${Date.now()}.pdf`,
Body: Buffer.from(pdfBytes),
ContentType: 'application/pdf',
};

const data = await S3.upload(params).promise();

res.status(200).json({
message: "Boleta generada con éxito",
pdfUrl: data.Location
});
} catch (error) {
console.error("Error:", error);
res.status(500).json({ message: "Error generando la boleta", error });
}
});

module.exports.handler = serverless(app);
11 changes: 11 additions & 0 deletions pdf-generator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "pdf-generator",
"version": "1.0.0",
"description": "",
"dependencies": {
"aws-sdk": "^2.1691.0",
"express": "^4.19.2",
"pdf-lib": "^1.17.1",
"serverless-http": "^3.2.0"
}
}
22 changes: 22 additions & 0 deletions pdf-generator/serverless.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
org: kev123
service: pdf-generator

provider:
name: aws
runtime: nodejs20.x
region: us-east-1

iamRoleStatements:
- Effect: "Allow"
Action:
- "s3:PutObject"
- "s3:GetObject"
Resource: "arn:aws:s3:::node-craft/*"

functions:
api:
handler: handler.handler
events:
- httpApi:
path: /generate
method: post
1 change: 0 additions & 1 deletion src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

.App-header {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 20px;
Expand Down
26 changes: 23 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import './App.css';
import React, { useState, useEffect, useCallback } from 'react';
import axios from 'axios';
import { useAuth0 } from '@auth0/auth0-react';
import { generateInvoice } from './services/invoiceService.js';

function App() {
const { loginWithRedirect, logout, isAuthenticated, user, getAccessTokenSilently } = useAuth0();
Expand Down Expand Up @@ -187,9 +188,28 @@ function App() {
if (response.data.error) {
alert(response.data.error);
} else {
alert('Compra exitosa. Ubicación de la solicitud: ' + response.data.location.city);
fetchUser();
fetchFixtures();

// Agregado generación de boleta post compra
const userData = {
name: user.nickname,
email: user.email
};

const matchData = {
teams: fixture.teams,
date: fixture.date,
amount: cost // El valor depende de la cantidad
};

// Se genera el URL de la boleta y además se informa la ubicación
try {
const pdfUrl = await generateInvoice(userData, matchData);
alert(`Compra exitosa. Descarga tu boleta aquí: ${pdfUrl}. Ubicación: ${response.data.location.city}`);
fetchUser();
fetchFixtures();
} catch (error) {
alert('Error generando la boleta.');
}
}
} catch (error) {
setShowProcessingModal(false);
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ root.render(
domain={process.env.REACT_APP_AUTH0_DOMAIN}
clientId={process.env.REACT_APP_AUTH0_CLIENT_ID}
redirectUri={window.location.origin}
audience="https://api.nodecraft.me"
>
<App />
</Auth0Provider>
Expand Down
40 changes: 40 additions & 0 deletions src/services/invoiceService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import axios from 'axios';

export const generateInvoice = async (userData, matchData) => {
try {

const response = await axios.post('https://axp8mrrbk1.execute-api.us-east-1.amazonaws.com/generate', {
userData: {
name: userData.name,
email: userData.email
},
matchData: {
teams: {
home: {
id: matchData.teams.home.id,
name: matchData.teams.home.name,
logo: matchData.teams.home.logo,
winner: matchData.teams.home.winner
},
away: {
id: matchData.teams.away.id,
name: matchData.teams.away.name,
logo: matchData.teams.away.logo,
winner: matchData.teams.away.winner
}
},
date: matchData.date,
amount: matchData.amount
}
});

if (response.data && response.data.pdfUrl) {
return response.data.pdfUrl;
} else {
throw new Error('Error generando la boleta');
}
} catch (error) {
console.error('Error generando la boleta:', error);
throw error;
}
};
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10301,3 +10301,4 @@ yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==

0 comments on commit a0acdcb

Please sign in to comment.