├── LICENSE ├── README.md ├── README_PAGES.md ├── certificate ├── .eslintrc.js ├── .gitignore ├── .prettierrc.js ├── README.md ├── debug.log ├── netlify.toml ├── package-lock.json ├── package.json ├── public │ ├── erro404.gif │ ├── estrelas.png │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── logo_texto_cinza.png │ ├── manifest.json │ ├── robots.txt │ ├── stars.png │ ├── start.png │ └── wallpaper-certificate.png ├── src │ ├── App.js │ ├── App.test.js │ ├── assets │ │ ├── img │ │ │ ├── erro404.gif │ │ │ ├── logo_negativo.png │ │ │ ├── logo_texto_branco.png │ │ │ ├── logo_texto_cinza.png │ │ │ ├── logo_texto_preto.png │ │ │ ├── wallpaper-home.jpg │ │ │ └── womakerscode-oficina.jpg │ │ ├── model_certificate.png │ │ ├── stars.png │ │ ├── wallpaper-certificate.png │ │ ├── wallpaper-info-event.jpg │ │ ├── wallpaper-info-event.png │ │ ├── wallpaper-section.jpg │ │ └── wallpaper-section.jpg.png │ ├── components │ │ ├── cards │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── footer │ │ │ ├── footer.css │ │ │ └── index.js │ │ ├── form-login │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── form-register │ │ │ ├── index.js │ │ │ ├── style-google.css │ │ │ └── styles.css │ │ ├── header │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── info-event │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── list-events │ │ │ ├── index.js │ │ │ ├── style-digital-assinature.css │ │ │ ├── style-form-event.css │ │ │ ├── styles-events.css │ │ │ └── styles.css │ │ ├── list-presents │ │ │ ├── index.js │ │ │ ├── style-certificate.css │ │ │ ├── style-spinkit.css │ │ │ └── style.css │ │ ├── menu-1-header │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── menu-1 │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── message-alert │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── model-certificate-home │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── profile-card │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── section │ │ │ ├── index.js │ │ │ └── style.css │ │ └── steps │ │ │ ├── index.js │ │ │ └── style.css │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── pages │ │ ├── home │ │ │ └── index.js │ │ ├── list-of-events │ │ │ └── index.js │ │ ├── page-confirmation │ │ │ └── index.js │ │ ├── page-not-found │ │ │ ├── index.js │ │ │ └── style.css │ │ ├── profile │ │ │ └── index.js │ │ ├── sign-in │ │ │ └── index.js │ │ └── sign-up │ │ │ ├── index.js │ │ │ └── styles.css │ ├── routes.js │ ├── serviceWorker.js │ ├── services │ │ ├── events.json │ │ ├── participantes.json │ │ └── users.json │ ├── setupTests.js │ └── style │ │ └── App.css └── yarn.lock └── layout.pptx /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 React-Bootcamp-WoMarkersCode 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |

4 | 5 | ## Desenvolvedoras :octocat: 6 | 7 | [
Bee Bones](https://github.com/beebones) |[
Chaiana Hermes](https://github.com/chaihermes) | [
Diana Regina](https://github.com/Diana-ops) | [
Rose Ahakawa](https://github.com/ahakawa) | 8 | | :---: | :---: | :---: | :---: 9 | 10 | > Status do Projeto: Concluido :heavy_check_mark: 11 | 12 | ### Tópicos 13 | 14 | :small_blue_diamond: [Descrição do projeto](#descrição-do-projeto-star) 15 | 16 | :small_blue_diamond: [O que a plataforma é capaz de fazer](#o-que-a-plataforma-é-capaz-de-fazer-checkered_flag) 17 | 18 | :small_blue_diamond: [Deploy da Aplicação com Netlify](#deploy-da-aplicação-com-netlify-dash) 19 | 20 | :small_blue_diamond: [Pré-requesitos](#pré-requesitos) 21 | 22 | :small_blue_diamond: [Como rodar a aplicação](#como-rodar-a-aplicação-arrow_forward) 23 | 24 | :small_blue_diamond: [JSON](#json-floppy_disk) 25 | 26 | :small_blue_diamond: [Páginas](#páginas) 27 | 28 | :small_blue_diamond: [CRUD](#crud) 29 | 30 | :small_blue_diamond: [Linguagens, dependencias e libs utilizadas ](#linguagens-dependencias-e-libs-utilizadas-books) 31 | 32 | :small_blue_diamond: [Dependência externa](#dependência-externa-incoming_envelope) 33 | 34 | ## Descrição do projeto :star: 35 | 36 |

37 | Desenvolver uma plataforma capaz de gerar certificados em PDF de eventos e cursos para enviá-los por e-mail aos participantes. 38 |

39 | 40 |

41 | 42 |

43 | 44 | ## O que a plataforma é capaz de fazer :checkered_flag: 45 | 46 | :trophy: Gerar PDF do certificado com as informações preenchidas no formulário para cada participantes para envio de e-mail 47 | 48 | :trophy: Check-list de participantes, permitindo selecionar quem irá receber os certificados 49 | 50 | :trophy: Permite que o organizador do evento escreva sua assinatura digital dentro da plataforma 51 | 52 | :trophy: Oferece layout responsivo 53 | 54 | :trophy: Cadastrar organizadores 55 | 56 | :trophy: Cadastrar eventos 57 | 58 | :trophy: Cadastrar participantes para cada evento 59 | 60 | ## Deploy da Aplicação com Netlify :dash: 61 | 62 | > https://certificates-for-everyone-womakerscode.netlify.app/ 63 | 64 | ## Pré-requesitos 65 | 66 | :warning: [Node](https://nodejs.org/en/download/) 67 | 68 | :warning: [Yarn](https://classic.yarnpkg.com/pt-BR/docs/install/#windows-stable) 69 | 70 | ## Como rodar a aplicação :arrow_forward: 71 | 72 | No terminal, clone o projeto: 73 | 74 | ``` 75 | git clone https://github.com/React-Bootcamp-WoMarkersCode/certificate-generator 76 | ``` 77 | 78 | Entre na pasta do projeto: 79 | 80 | ``` 81 | cd certificate-generator 82 | ``` 83 | 84 | Instale as dependecias: 85 | 86 | ``` 87 | yarn install 88 | ``` 89 | 90 | Execute a aplicação: 91 | 92 | ``` 93 | yarn start 94 | ``` 95 | 96 | Pronto, agora é possível acessar a aplicação a partir da rota http://localhost:3000/ 97 | 98 | ## JSON :floppy_disk: 99 | 100 | A nossa simulação de banco de dados foi feita com JSON. Foram separados um para [usuarios](https://github.com/React-Bootcamp-WoMarkersCode/certificate-generator/blob/DianaRegina/certificate/src/services/users.json), [participantes](https://github.com/React-Bootcamp-WoMarkersCode/certificate-generator/blob/DianaRegina/certificate/src/services/participantes.json) e [eventos](https://github.com/React-Bootcamp-WoMarkersCode/certificate-generator/blob/DianaRegina/certificate/src/services/events.json): 101 | 102 | ### Usuário: 103 | 104 | |name|email|password|token|avatar| 105 | | -------- |-------- |-------- |-------- |-------- | 106 | |Lais Lima|laislima98@hotmail.com|lais123|true|https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcS9-U_HbQAipum9lWln3APcBIwng7T46hdBA42EJv8Hf6Z4fDT3&usqp=CAU| 107 | 108 | ### Evento: 109 | 110 | |user|company|course|startDate|finishDate|workload|logo| 111 | | -------- |-------- |-------- |-------- |-------- |-------- |-------- | 112 | |Lais Lima|WomakersCode|Bootcamp React|01/02/2020|28/03/2020|56|https://miro.medium.com/max/478/1*jriufqYKgJTW4DKrBizU5w.png|https://upload.wikimedia.org/wikipedia/commons/7/7f/Assinatura_Jos%C3%A9_Saramago.png| 113 | 114 | ### Participante: 115 | 116 | |name|email|present|receiveCertificate|course| 117 | | -------- |-------- |-------- |-------- |-------- | 118 | |Chaiana Hermes|chaiana_hermes@yahoo.com.br|true|false|Bootcamp React| 119 | 120 | ## Páginas 121 | 122 | [Aqui](https://github.com/React-Bootcamp-WoMarkersCode/certificate-generator/blob/DianaRegina/README_PAGES.md) é possível visualizar a **proposta** de layout do projeto. 123 | 124 | ## CRUD 125 | 126 | ### Usuários 127 | 128 | :heavy_check_mark: O usuário pode ser **criado** na pagina Sign-up a partir de um formulário ou com uma conta existente no Google. 129 | 130 | :heavy_check_mark: Os dados do usuário podem ser **acessados** em Login e perfil. 131 | 132 | :heavy_check_mark: Os dados do usuário podem ser **atualizados** em seu perfil a partir de um formulário. 133 | 134 | :heavy_check_mark: A conta do usuário pode ser **deletada** em seu perfil. 135 | 136 | ### Eventos 137 | 138 | :heavy_check_mark: Podem ser **criados** a partir de um formulário na lista de eventos. 139 | 140 | :heavy_check_mark: Podem ser **acessados** na lista de eventos 141 | 142 | :heavy_check_mark: Podem ser **atualizados** na lista de eventos a partir de um formulário. 143 | 144 | :heavy_check_mark: Podem ser **deletados** na lista de eventos 145 | 146 | ### Participantes 147 | 148 | :heavy_check_mark: Podem ser **criados** a partir de um formulário na lista de participantes. 149 | 150 | :heavy_check_mark: Podem ser **acessados** em uma lista na lista de participantes. 151 | 152 | :heavy_check_mark: Podem ser **atualizados**, indicando se aquele participante poderá ou não receber um certificado na lista de participantes. 153 | 154 | :heavy_check_mark: Podem ser **deletados** na lista de participantes. 155 | 156 | ## Linguagens, dependencias e libs utilizadas :books: 157 | 158 | - [React](https://pt-br.reactjs.org/docs/create-a-new-react-app.html) 159 | - [React PDF](https://react-pdf.org/) 160 | - [React Router](https://reacttraining.com/react-router/web/guides/quick-start) 161 | 162 | Framework para layouts prontos: 163 | - [AntDesign](https://ant.design/docs/react/introduce) 164 | 165 | Autenticação com Google 166 | - [Login com Google](https://www.npmjs.com/package/react-google-login) 167 | 168 | Para mandar PDF por email 169 | - [jspdf](https://www.npmjs.com/package/jspdf) 170 | 171 | Para inserir HTML no corpo do email 172 | - [html2canvas](https://www.npmjs.com/package/html2canvas) 173 | 174 | Para desenvolver a assinatura digital: 175 | 176 | - [Reactjs-Popup](https://react-popup.elazizi.com/getting-started/) 177 | - [react-signature-canvas](https://www.npmjs.com/package/react-signature-canvas) 178 | 179 | Permite visualizar uma animação enquanto o usuário espera o e-mail ser enviado: 180 | - [React-Spinkit](https://github.com/KyleAMathews/react-spinkit) 181 | 182 | ## Dependência externa :incoming_envelope: 183 | [Server Mailjet](https://github.com/beebones/server-mailjet) - Back-end feito em **Golang** utiizado para consumir api **mailjet** e enviar os emails com o certificado. 184 |
185 | -------------------------------------------------------------------------------- /README_PAGES.md: -------------------------------------------------------------------------------- 1 | ### Reference and Inspiration: [Site WoMakersCode](https://womakerscode.org/) and [Generate Certificate](https://geradordecertificados.com/) 2 | 3 | ## Pages 4 | 5 | - [ ] **Home:** Show the user a step by step on how to use the application, generate the certificate and send it to participants 6 | 7 | ### Layout 8 | 9 | ![layoutHome](https://user-images.githubusercontent.com/46378210/77123261-66886780-6a1e-11ea-91a5-2e1d699a76a8.png) 10 | 11 | ### Thinking in Components 12 | 13 | ![componentsHome](https://user-images.githubusercontent.com/46378210/77124294-38f0ed80-6a21-11ea-9a90-95dd0fe5590f.png) 14 | 15 | - [ ] **SingUp:** Page for the registration of users representing an institution (example: WoMakersCode). A form will be presented asking for information regarding the event: 16 | 17 | - email 18 | - password 19 | 20 | ### Layout and Thinking in Components 21 | 22 | ![singUp](https://user-images.githubusercontent.com/46378210/77124311-47d7a000-6a21-11ea-9c43-789e40d135f1.png) 23 | 24 | - [ ] **SingIn:** User login 25 | 26 | - email 27 | - password 28 | 29 | ### Layout and Thinking in Components 30 | 31 | ![layoutSingIn](https://user-images.githubusercontent.com/46378210/77126143-db5f9f80-6a26-11ea-89b0-614ac6d3ec38.png) 32 | 33 | - [ ] **Profile:** list of user information, on this page he will have access: 34 | 35 | - edit and delete profile 36 | - return to your events 37 | 38 | ### Layout and Thinking in Components 39 | 40 | ![layoutProfile](https://user-images.githubusercontent.com/46378210/77126137-d6025500-6a26-11ea-9bbb-9b265a9331e6.png) 41 | 42 | - [ ] **Edit profile:** the user can edit his information 43 | 44 | ### Layout and Thinking in Components 45 | 46 | ![layoutProfileEdit](https://user-images.githubusercontent.com/46378210/77126141-d7cc1880-6a26-11ea-9d97-48ba244157da.png) 47 | 48 | - [ ] **List of Events:** the list of events will be presented, on this page he will have access: 49 | 50 | - the event CRUD (list, create, edit and delete) 51 | - go to your profile 52 | - send certificates 53 | - update the list of participants 54 | 55 | ### Layout and Thinking in Components 56 | 57 | ![layoutListEvents](https://user-images.githubusercontent.com/46378210/77126066-9cc9e500-6a26-11ea-871d-339c5f7bb2f5.png) 58 | 59 | - [ ] **Create event:** a form will be presented asking for information regarding the event: 60 | 61 | - name of the institution 62 | - company logo 63 | - workload 64 | - start and end date 65 | - uploading the list of participants 66 | - digital signature 67 | 68 | ### Layout and Thinking in Components 69 | 70 | ![layoutFormEvent](https://user-images.githubusercontent.com/46378210/77126059-989dc780-6a26-11ea-8531-d8e795e4cb7f.png) 71 | 72 | - [ ] **Edit event:** the user can edit information about some event 73 | 74 | ### Layout and Thinking in Components 75 | 76 | ![layoutEditForm](https://user-images.githubusercontent.com/46378210/77126941-85d8c200-6a29-11ea-9268-9a01ac7af683.png) 77 | 78 | - [ ] **List Presents**: To show the list of participants of each event, with an option to check your present in event by user 79 | 80 | ### Layout and Thinking in Components 81 | 82 | ![listPresents](https://user-images.githubusercontent.com/46378210/77265884-ae0c2f00-6c7c-11ea-8a22-0a18e6cf040a.png) 83 | 84 | - [ ] **Confirm certificate to send:** The certificate template and a button will be shown so that it can confirm that it can be sent to participants 85 | 86 | ### Layout and Thinking in Components 87 | 88 | ![layoutModelCertificate](https://user-images.githubusercontent.com/46378210/77126510-11515380-6a28-11ea-925c-d123740ef839.png) 89 | 90 | - [ ] **Page of confirmation:** A confirmation message will be shown to the user to let them know that their action has been successfully performed for all participants 91 | 92 | ### Layout and Thinking in Components 93 | 94 | ![layoutMsg1](https://user-images.githubusercontent.com/46378210/77126076-a2272f80-6a26-11ea-896e-eb6ef38b59b9.png) 95 | 96 | - [ ] **Page not found:** if he tries to access a different page through the url, we could show an alert message 97 | 98 | ### Layout and Thinking in Components 99 | 100 | ![layoutMsg3](https://user-images.githubusercontent.com/46378210/77126128-cb47c000-6a26-11ea-90c6-27c2f334127f.png) 101 | -------------------------------------------------------------------------------- /certificate/.eslintrc.js: -------------------------------------------------------------------------------- 1 | 2 | //Path: /.eslintrc.js 3 | 4 | module.exports = { 5 | extends: ['airbnb'], 6 | rules: { 7 | 'react/jsx-filename-extension': 'off', 8 | }, 9 | }; -------------------------------------------------------------------------------- /certificate/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /certificate/.prettierrc.js: -------------------------------------------------------------------------------- 1 | 2 | //Path: /.prettierrc.js 3 | 4 | module.exports = { 5 | bracketSpacing: true, 6 | jsxBracketSameLine: true, 7 | singleQuote: true, 8 | trailingComma: 'all', 9 | }; -------------------------------------------------------------------------------- /certificate/README.md: -------------------------------------------------------------------------------- 1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 2 | 3 | ## Available Scripts 4 | 5 | In the project directory, you can run: 6 | 7 | ### `yarn start` 8 | 9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 11 | 12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console. 14 | 15 | ### `yarn test` 16 | 17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. 19 | 20 | ### `yarn build` 21 | 22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance. 24 | 25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed! 27 | 28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. 29 | 30 | ### `yarn eject` 31 | 32 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!** 33 | 34 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. 35 | 36 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. 37 | 38 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. 39 | 40 | ## Learn More 41 | 42 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 43 | 44 | To learn React, check out the [React documentation](https://reactjs.org/). 45 | 46 | ### Code Splitting 47 | 48 | This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting 49 | 50 | ### Analyzing the Bundle Size 51 | 52 | This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size 53 | 54 | ### Making a Progressive Web App 55 | 56 | This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app 57 | 58 | ### Advanced Configuration 59 | 60 | This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration 61 | 62 | ### Deployment 63 | 64 | This section has moved here: https://facebook.github.io/create-react-app/docs/deployment 65 | 66 | ### `yarn build` fails to minify 67 | 68 | This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify 69 | -------------------------------------------------------------------------------- /certificate/debug.log: -------------------------------------------------------------------------------- 1 | [0404/170300.775:ERROR:settings.cc(320)] Settings magic is not 1129342067 2 | [0415/192638.171:ERROR:settings.cc(320)] Settings magic is not 1129342067 3 | -------------------------------------------------------------------------------- /certificate/netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "yarn build" # the command you run to build this file 3 | functions = "built-lambda" # netlify-lambda builds to this folder AND Netlify reads functions from here 4 | publish = "build" # create-react-app builds to this folder, Netlify should serve all these files statically -------------------------------------------------------------------------------- /certificate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "certificate", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@react-pdf/renderer": "^1.6.8", 7 | "@testing-library/jest-dom": "^4.2.4", 8 | "@testing-library/react": "^9.3.2", 9 | "@testing-library/user-event": "^7.1.2", 10 | "antd": "^4.1.2", 11 | "formik": "^2.1.4", 12 | "html2canvas": "^1.0.0-rc.5", 13 | "jspdf": "^1.5.3", 14 | "netlify-cli": "^2.46.0", 15 | "react": "^16.13.1", 16 | "react-dom": "^16.13.1", 17 | "react-google-login": "^5.1.3", 18 | "react-router-dom": "^5.1.2", 19 | "react-scripts": "3.4.0", 20 | "react-signature-canvas": "^1.0.3", 21 | "react-spinkit": "^3.0.0", 22 | "reactjs-popup": "^1.5.0", 23 | "tachyon": "^0.0.11", 24 | "yup": "^0.28.3" 25 | }, 26 | "scripts": { 27 | "start": "react-scripts start", 28 | "build": "run-p build:**", 29 | "test": "react-scripts test", 30 | "eject": "react-scripts eject", 31 | "start:lambda": "netlify-lambda serve src/lambda", 32 | "build:app": "react-scripts build", 33 | "build:lambda": "netlify-lambda build src/lambda" 34 | }, 35 | "eslintConfig": { 36 | "extends": "react-app" 37 | }, 38 | "browserslist": { 39 | "production": [ 40 | ">0.2%", 41 | "not dead", 42 | "not ie <= 11", 43 | "not op_mini all" 44 | ], 45 | "development": [ 46 | "last 1 chrome version", 47 | "last 1 firefox version", 48 | "last 1 safari version" 49 | ] 50 | }, 51 | "devDependencies": { 52 | "eslint": "^6.8.0", 53 | "eslint-config-airbnb": "^18.1.0", 54 | "husky": "^4.2.5", 55 | "lint-staged": "^10.1.3", 56 | "prettier": "^2.0.4", 57 | "react-redux": "^7.2.0", 58 | "redux": "^4.0.5", 59 | "tachyons": "^4.10.0", 60 | "netlify-lambda": "^1.4.5", 61 | "npm-run-all": "^4.1.5" 62 | }, 63 | "husky": { 64 | "hooks": { 65 | "pre-commit": "lint-staged" 66 | } 67 | }, 68 | "lint-staged": { 69 | "./src/*.{js,jsx,ts,tsx}": [ 70 | "npx prettier --write", 71 | "eslint src/*.js --fix-dry-run" 72 | ] 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /certificate/public/erro404.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/public/erro404.gif -------------------------------------------------------------------------------- /certificate/public/estrelas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/public/estrelas.png -------------------------------------------------------------------------------- /certificate/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/public/favicon.ico -------------------------------------------------------------------------------- /certificate/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Certificates for Everyone 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /certificate/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/public/logo192.png -------------------------------------------------------------------------------- /certificate/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/public/logo512.png -------------------------------------------------------------------------------- /certificate/public/logo_texto_cinza.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/public/logo_texto_cinza.png -------------------------------------------------------------------------------- /certificate/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /certificate/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /certificate/public/stars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/public/stars.png -------------------------------------------------------------------------------- /certificate/public/start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/public/start.png -------------------------------------------------------------------------------- /certificate/public/wallpaper-certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/public/wallpaper-certificate.png -------------------------------------------------------------------------------- /certificate/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './style/App.css'; 3 | import Routes from './routes' 4 | 5 | //Importado a biblioteca ant design 6 | import 'antd/dist/antd.css'; 7 | 8 | //Importado a biblioteca tachyons 9 | import 'tachyons'; 10 | 11 | 12 | function App() { 13 | 14 | return 15 | } 16 | 17 | export default App; 18 | -------------------------------------------------------------------------------- /certificate/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /certificate/src/assets/img/erro404.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/img/erro404.gif -------------------------------------------------------------------------------- /certificate/src/assets/img/logo_negativo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/img/logo_negativo.png -------------------------------------------------------------------------------- /certificate/src/assets/img/logo_texto_branco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/img/logo_texto_branco.png -------------------------------------------------------------------------------- /certificate/src/assets/img/logo_texto_cinza.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/img/logo_texto_cinza.png -------------------------------------------------------------------------------- /certificate/src/assets/img/logo_texto_preto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/img/logo_texto_preto.png -------------------------------------------------------------------------------- /certificate/src/assets/img/wallpaper-home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/img/wallpaper-home.jpg -------------------------------------------------------------------------------- /certificate/src/assets/img/womakerscode-oficina.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/img/womakerscode-oficina.jpg -------------------------------------------------------------------------------- /certificate/src/assets/model_certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/model_certificate.png -------------------------------------------------------------------------------- /certificate/src/assets/stars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/stars.png -------------------------------------------------------------------------------- /certificate/src/assets/wallpaper-certificate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/wallpaper-certificate.png -------------------------------------------------------------------------------- /certificate/src/assets/wallpaper-info-event.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/wallpaper-info-event.jpg -------------------------------------------------------------------------------- /certificate/src/assets/wallpaper-info-event.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/wallpaper-info-event.png -------------------------------------------------------------------------------- /certificate/src/assets/wallpaper-section.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/wallpaper-section.jpg -------------------------------------------------------------------------------- /certificate/src/assets/wallpaper-section.jpg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/certificate/src/assets/wallpaper-section.jpg.png -------------------------------------------------------------------------------- /certificate/src/components/cards/index.js: -------------------------------------------------------------------------------- 1 | /*Este componente está destinado a construção dos 6 cards da pagina Home*/ 2 | /*Estou usando o Antd para me auxiliar na construção e layout*/ 3 | 4 | import React from 'react' 5 | import { Card } from 'antd'; 6 | import 'antd/dist/antd.css'; 7 | import './style.css' 8 | 9 | function Cards(props) { 10 | 11 | return ( 12 |
13 |

Descubra o que o nosso Gerador de Certificados pode fazer por você

14 | 15 |
16 | 17 | 18 | Envie quantos certificados você precisar. 19 | 20 | 21 | 22 | Envie o certificado de cada participante por e-mail. 23 | 24 | 25 | 26 | Cadastre seus participantes para cada evento e selecione quem irá receber os certificados em nosso check-list. 27 | 28 | 29 | 30 | Escreva sua assinatura digital em nosso Pad para os seus certificados. 31 | 32 | 33 | 34 | Crie uma conta para você ou sua comunidade e gere certificados para seus eventos e cursos. 35 | 36 | 37 | Registre seus eventos/cursos e gere os certificados quando for melhor para você e envie a hora que quiser. 38 | 39 | 40 |
41 |
42 | ); 43 | } 44 | 45 | export default Cards; 46 | -------------------------------------------------------------------------------- /certificate/src/components/cards/style.css: -------------------------------------------------------------------------------- 1 | /*Titulos e textos*/ 2 | .title-1 { 3 | text-align: center; 4 | font-family: 'Raleway', sans-serif; 5 | font-weight: 400; 6 | } 7 | 8 | /*Descubra .. (h1)*/ 9 | /*Linha rosa em cima da palavra*/ 10 | .sub-title-1 { 11 | border-color: #c6255a; 12 | border-top-style: solid; 13 | border-top-width: 7px; 14 | color: black; 15 | padding-top: 10px; 16 | } 17 | 18 | /*Gerador de certificados (h1)*/ 19 | .sub2-title-1{ 20 | color: #c6255a; 21 | font-weight: 800; 22 | } 23 | 24 | 25 | /*Estilização dos cards e do componente Card*/ 26 | 27 | /*Para cada card*/ 28 | .card { 29 | margin: 3%; 30 | } 31 | 32 | .card:hover { 33 | box-shadow: 4px 4px 8px gray; 34 | transition: 0.5s; 35 | } 36 | 37 | /*Div que agrupa todos os cards*/ 38 | .site-card-wrapper { 39 | 40 | display: grid; 41 | grid-template-columns: repeat(3, 1fr); 42 | padding: 30px; 43 | margin-bottom: 3%; 44 | 45 | text-align: center; 46 | justify-content: center; 47 | } 48 | 49 | /*Div do componente inteiro*/ 50 | .div-cards { 51 | background-color: rgb(242, 242, 242); 52 | padding: 3%; 53 | } 54 | 55 | /*Quando a tela diminuir em lagura, as colunas dos cards vão se ajustando*/ 56 | @media screen and (max-width: 600px) { 57 | .site-card-wrapper { 58 | grid-template-columns: repeat(1, 1fr); 59 | } 60 | } 61 | 62 | @media screen and (min-width: 600px) and (max-width: 1000px){ 63 | .site-card-wrapper { 64 | grid-template-columns: repeat(2, 1fr); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /certificate/src/components/footer/footer.css: -------------------------------------------------------------------------------- 1 | * { 2 | font-family: 'Raleway', sans-serif; 3 | font-weight: '200', '400', ou '800' (light, regular, bold); 4 | } 5 | 6 | .footer { 7 | background-color: rgb(17, 17, 17); 8 | 9 | margin-top: 35%; 10 | width: 100%; 11 | } 12 | 13 | /*Lista de desenvolvedoras*/ 14 | .footer-1 { 15 | display: grid; 16 | grid-template-columns: repeat(2, 300px); 17 | padding: 2%; 18 | } 19 | 20 | .footer-1 h3 { 21 | font-size: 1.3rem; 22 | font-weight: bold; 23 | color: white; 24 | } 25 | 26 | /*Licença*/ 27 | .footer-2 { 28 | display: flex; 29 | align-items: center; 30 | justify-content: center; 31 | background-color: #16181b; 32 | width: 100%; 33 | height: 10vh; 34 | } 35 | 36 | .footer-2 h4 { 37 | color: white; 38 | } 39 | 40 | ol, li { 41 | list-style: none; 42 | } 43 | 44 | a:hover { 45 | color: #c6255a; 46 | } 47 | 48 | .footer-link { 49 | color: white; 50 | line-height: 1.5; 51 | text-decoration: none; 52 | font-size: 1.2rem; 53 | } 54 | 55 | @media screen and (max-width: 660px) { 56 | .footer-1 { 57 | grid-template-columns: repeat(1, 300px); 58 | } 59 | 60 | .footer-link { 61 | font-size: 1rem; 62 | } 63 | 64 | .footer-1 h3 { 65 | font-size: 1rem; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /certificate/src/components/footer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import { Row, Col } from 'antd'; 4 | import 'antd/dist/antd.css'; 5 | import './footer.css'; 6 | import '../../pages/sign-in/index'; 7 | import '../../pages/sign-up/index'; 8 | import '../../style/App.css'; 9 | 10 | function Footer(props) { 11 | 12 | return ( 13 | 14 |
15 | 16 |
17 |
    18 |

    Nossas Desenvolvedoras

    19 |
  1. 20 | Chaiana 21 |
  2. 22 |
  3. 23 | Diana 24 |
  4. 25 |
  5. 26 | Grasiele 27 |
  6. 28 |
  7. 29 | Rosemeire 30 |
  8. 31 |
32 |
    33 |

    Gerador de Certificados

    34 |
  1. 35 | Sign In 36 |
  2. 37 |
  3. 38 | Sign Up 39 |
  4. 40 |
  5. 41 | Começar 42 |
  6. 43 |
44 |
45 | 46 |
47 |

Licença MIT - Copyright - 2020 - Certificates for Everyone

48 |
49 |
50 | ); 51 | } 52 | 53 | export default Footer; -------------------------------------------------------------------------------- /certificate/src/components/form-login/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { useFormik } from "formik"; 3 | import GoogleLogin from 'react-google-login'; 4 | import * as Yup from "yup"; 5 | 6 | /*Importando lista de participantes*/ 7 | import users from '../../services/users.json' 8 | 9 | import ListEvents from '../../components/list-events/index' 10 | 11 | /*Estilos*/ 12 | import { Form, Input, Button, message } from "antd"; 13 | import { UserOutlined, LockOutlined } from "@ant-design/icons"; 14 | import './style.css' 15 | import '../form-register/style-google.css' 16 | 17 | 18 | const FormLogin = () => { 19 | 20 | /*Verifica se o acesso foi aprovado*/ 21 | const [ acessAproved, setAproved ] = useState(false) 22 | 23 | /*JSON dos usuários*/ 24 | const [ user, setUser ] = useState(users) 25 | 26 | /*Organizador do evento*/ 27 | const [ organizador, setOrganizador ] = useState('') 28 | 29 | //Coloquei onFinish pois no site do Antd está dizendo p/ usar onFinish ao invés de onSubmit 30 | // link de referência: https://ant.design/components/form/v3 31 | 32 | const onFinish = () => { 33 | 34 | /*Verificando campos*/ 35 | 36 | if(!values.email || !values.password) { 37 | message.warning('Por favor, preencha todos os campos') 38 | 39 | } else { 40 | 41 | /*Verificando se já existe um usuário cadastrado*/ 42 | let listEmails = [] 43 | 44 | user.map(itemJson => { 45 | listEmails.push(itemJson.email) 46 | }) 47 | 48 | console.log(listEmails) 49 | 50 | if(!listEmails.includes(values.email)) { 51 | message.warning('Sua conta ainda não existe, crie uma com o nosso formulário ou Google') 52 | 53 | } else { 54 | 55 | /*Verificando existencia da conta*/ 56 | user.map(itemJson => { 57 | 58 | let emailExistent = (itemJson.email === values.email) 59 | let passwordExistent = (itemJson.password === values.password) 60 | 61 | if( emailExistent && passwordExistent) { 62 | 63 | setOrganizador(itemJson.name) 64 | setAproved(true) 65 | message.loading('Acesso aprovado! Voce será redirecionado para a lista de eventos') 66 | 67 | /*Atualizando o token do usuário para true, registrando que ee está logado na plataforma*/ 68 | setUser( 69 | user.map(item => { 70 | 71 | /*Buscando usuário ativo*/ 72 | if(item.email === itemJson.email){ 73 | item['token'] = true 74 | 75 | return item 76 | } else { 77 | 78 | return item 79 | } 80 | }) 81 | ) 82 | 83 | } 84 | }) 85 | 86 | 87 | /*Se o acesso não for aprovado*/ 88 | if(acessAproved === false) { 89 | message.error('E-mail ou senha estão incorretos, tente novamente!', 1) 90 | } 91 | } 92 | } 93 | } 94 | 95 | const formik = useFormik({ 96 | initialValues: { 97 | email: "certificadowomakerscode@gmail.com", 98 | password: "certificado123" 99 | }, 100 | validationSchema: Yup.object({ 101 | email: Yup.string().email("Email inválido").required("Campo obrigatório"), 102 | password: Yup.string().min(4).required("Campo obrigatório") 103 | }) 104 | 105 | }); 106 | 107 | const addNewUser = (name, email, password, avatar) => { 108 | 109 | setUser([ 110 | ...user, { 111 | name: name, 112 | email: email, 113 | password: password, 114 | token: true, 115 | avatar: avatar 116 | } 117 | ]) 118 | 119 | setAproved(true) 120 | setOrganizador(name) 121 | message.success('Conta criada com sucesso') 122 | } 123 | 124 | const responseGoogle = response => { 125 | 126 | /*Verificando se já existe um usuário cadastrado*/ 127 | let listEmails = [] 128 | 129 | user.map(itemJson => { 130 | listEmails.push(itemJson.email) 131 | 132 | }) 133 | 134 | if(!listEmails.includes(response.profileObj.email)) { 135 | addNewUser(response.profileObj.name, response.profileObj.email, true, response.profileObj.imageUrl) 136 | 137 | } else { 138 | message.warning('Este usuário já está cadastrado') 139 | } 140 | } 141 | 142 | const { handleSubmit, values } = formik 143 | 144 | //O article está sendo utilizado do tachyons para colocar na formatação dos campos e a centralização na tela e a sombra 145 | return ( 146 |
147 |
148 |

Digite seus dados e acesse sua conta

149 |
150 | ( 153 | 156 | )} 157 | buttonText="Cadastrar com o Google" 158 | onSuccess={responseGoogle} 159 | onFailure={responseGoogle} 160 | /> 161 |
162 | 163 |

OU

164 |
165 | 166 | 167 | } 170 | placeholder="Email" 171 | {...formik.getFieldProps("email")} 172 | /> 173 | {formik.touched.email && formik.errors.email ? ( 174 |
{formik.errors.email}
175 | ) : null} 176 |
177 | 178 | 179 | } 182 | type="password" 183 | placeholder="Senha" 184 | {...formik.getFieldProps("password")} 185 | /> 186 | {formik.touched.password && formik.errors.password ? ( 187 |
{formik.errors.password}
188 | ) : null} 189 |
190 | 191 | 192 | 206 | 207 | 208 |
209 |
210 | 211 | {/*Renderizando a pagina de lista de eventos*/} 212 | { acessAproved && } 213 |
214 | ); 215 | }; 216 | 217 | export default FormLogin; 218 | -------------------------------------------------------------------------------- /certificate/src/components/form-login/style.css: -------------------------------------------------------------------------------- 1 | .button-form-login { 2 | background-color: pink; 3 | border-color: pink; 4 | margin-right: 15%; 5 | } 6 | 7 | 8 | .article { 9 | width: 40%; 10 | margin-right: auto; 11 | margin-left: auto; 12 | } 13 | 14 | .title-login { 15 | color: #c6255a; 16 | text-align: center; 17 | } 18 | 19 | .login-form { 20 | margin-bottom: -20%; 21 | } 22 | 23 | @media screen and (max-width: 900px) { 24 | .article { 25 | width: 70%; 26 | } 27 | 28 | .loginBtn.loginBtn-google { 29 | margin-left: 10%; 30 | } 31 | } 32 | 33 | @media screen and (max-width: 700px) { 34 | .article { 35 | width: 70%; 36 | } 37 | } 38 | 39 | @media screen and (min-width: 700px) { 40 | .login-form { 41 | margin-bottom: -30%; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /certificate/src/components/form-register/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import { useFormik, FormikProvider, Form, Field, ErrorMessage } from 'formik'; 3 | import { message, Button, Input } from 'antd'; 4 | import { UserOutlined, LockOutlined, ScheduleOutlined } from "@ant-design/icons"; 5 | import GoogleLogin from 'react-google-login'; 6 | import * as Yup from 'yup'; 7 | import './styles.css'; 8 | import './style-google.css' 9 | 10 | /*Importando lista de participantes*/ 11 | import users from '../../services/users.json' 12 | 13 | import ListEvents from '../../components/list-events/index' 14 | 15 | const FormRegister = (props) => { 16 | 17 | /*Verifica se o acesso foi aprovado*/ 18 | const [ acessAproved, setAproved ] = useState(false) 19 | 20 | /*Organizador do evento*/ 21 | const [ organizador, setOrganizador ] = useState('') 22 | 23 | const formik = useFormik({ 24 | initialValues: { 25 | name: "", 26 | email: "", 27 | password: "", 28 | remember: true, 29 | }, 30 | validationSchema: Yup.object().shape({ 31 | name: Yup.string().required('Digite seu nome'), 32 | email: Yup.string().email('E-mail inválido').required('Digite seu e-mail'), 33 | password: Yup.string().min(4).required('Digite uma senha') 34 | }) 35 | }) 36 | 37 | const { handleSubmit, values } = formik 38 | 39 | /*JSON dos usuários*/ 40 | const [ user, setUser ] = useState(users) 41 | 42 | const addNewUser = (name, email, password, avatar) => { 43 | 44 | setUser([ 45 | ...user, { 46 | name: name, 47 | email: email, 48 | password: password, 49 | token: true, 50 | avatar: avatar 51 | } 52 | ]) 53 | 54 | setAproved(true) 55 | setOrganizador(name) 56 | message.success('Conta criada com sucesso') 57 | } 58 | 59 | /*Função acionada após criar a conta com o formulário*/ 60 | const actionButton = () => { 61 | 62 | if(!values.name || !values.email || !values.password) { 63 | message.warning('Por favor, preencha todos os campos') 64 | 65 | } else { 66 | 67 | /*Verificando se já existe um usuário cadastrado*/ 68 | let listEmails = [] 69 | 70 | user.map(itemJson => { 71 | listEmails.push(itemJson.email) 72 | }) 73 | 74 | /*Se o e-mail digitado pelo usuário pelo usuário ainda não está no JSON de usuários*/ 75 | if(!listEmails.includes(values.email)) { 76 | addNewUser(values.name, values.email, values.password, " ") 77 | 78 | } else { 79 | message.warning('Esta conta já existe') 80 | } 81 | } 82 | } 83 | 84 | /*Função acionada após o login com o Google*/ 85 | const responseGoogle = response => { 86 | 87 | /*Verificando se já existe um usuário cadastrado*/ 88 | let listEmails = [] 89 | 90 | user.map(itemJson => { 91 | listEmails.push(itemJson.email) 92 | }) 93 | 94 | /*Se o e-mail digitado pelo usuário pelo usuário ainda não está no JSON de usuários*/ 95 | if(!listEmails.includes(response.profileObj.email)) { 96 | addNewUser(response.profileObj.name, response.profileObj.email, true, response.profileObj.imageUrl) 97 | 98 | } else { 99 | message.warning('Esta conta já existe') 100 | } 101 | } 102 | 103 | return ( 104 | <> 105 |
106 |

Cadastre uma conta já, é simples e rápido

107 |
108 | ( 111 | 114 | )} 115 | buttonText="Cadastrar com o Google" 116 | onSuccess={responseGoogle} 117 | onFailure={responseGoogle} 118 | /> 119 |
120 | 121 |

OU

122 | 123 | 124 |
125 | 126 | } 131 | placeholder="Digite seu nome" 132 | /> 133 |

{msg}

} 135 | name="name" /> 136 | 137 | 138 | } 143 | placeholder="Digite seu e-mail" 144 | 145 | /> 146 |

{msg}

} 148 | name="email" /> 149 | 150 | 151 | } 157 | /> 158 |

{msg}

} 160 | name="password" /> 161 | 162 | 168 | 169 |
170 |
171 | {/*Renderizando a pagina de lista de eventos*/} 172 | { acessAproved && } 173 | 174 | ); 175 | } 176 | 177 | export default FormRegister; -------------------------------------------------------------------------------- /certificate/src/components/form-register/style-google.css: -------------------------------------------------------------------------------- 1 | .loginBtn.loginBtn-google { 2 | margin-left: -5%; 3 | } 4 | 5 | .ou { 6 | display: flex; 7 | justify-content: center; 8 | margin-top: 3%; 9 | } 10 | 11 | 12 | @media screen and (max-width: 700px){ 13 | .loginBtn.loginBtn-google { 14 | margin-left: -10%; 15 | } 16 | } -------------------------------------------------------------------------------- /certificate/src/components/form-register/styles.css: -------------------------------------------------------------------------------- 1 | *{ 2 | font-family: 'Raleway', sans-serif; 3 | font-weight: "200", "400", ou "800" (light, regular, bold) 4 | } 5 | 6 | .form { 7 | width: 70%; 8 | height: 50vh; 9 | display: block; 10 | padding: 1em; 11 | margin-left: auto; 12 | margin-right: auto; 13 | margin-bottom: -10%; 14 | margin-top: 5%; 15 | } 16 | 17 | /*Inputs - Label*/ 18 | .form-label{ 19 | font-family: 'Raleway', sans-serif; 20 | font-weight: light; 21 | font-size: 1.2em; 22 | font-weight: bold; 23 | display: flex; 24 | justify-content: center; 25 | padding: 0.5em; 26 | 27 | } 28 | 29 | .title-cadastre { 30 | color: orange; 31 | text-align: center; 32 | } 33 | 34 | /*Inputs - Field*/ 35 | .form-field { 36 | display: block; 37 | margin-left: auto; 38 | margin-right: auto; 39 | font-size: 15px; 40 | width: 60%; 41 | margin-bottom: 2%; 42 | padding: 1%; 43 | border-color: transparent; 44 | border-bottom-color: #d3d3d3; 45 | border-width: 0.5px; 46 | 47 | } 48 | 49 | .form-upload{ 50 | display: block; 51 | margin-left: 28%; 52 | margin-right: auto; 53 | margin-top: 20px; 54 | margin-bottom: 40px; 55 | border-color: rgb(255, 102, 0); 56 | color: rgb(255, 102, 0); 57 | font-weight: bold; 58 | } 59 | 60 | .button { 61 | background-color: orange; 62 | border-color: transparent; 63 | margin-left: 20%; 64 | color: #ffffff; 65 | width: 60%; 66 | } 67 | 68 | .button:hover { 69 | border-color: rgb(255, 102, 0); 70 | color: rgb(255, 102, 0); 71 | background-color: white; 72 | transition: 1s; 73 | } 74 | 75 | /*Mensagem de erro: preencha os campos*/ 76 | .msg-error { 77 | color: red; 78 | display: flex; 79 | justify-content: center; 80 | } 81 | 82 | @media screen and (max-width: 600px){ 83 | .form{ 84 | width: 90%; 85 | height: 60vh; 86 | } 87 | 88 | .form-upload{ 89 | margin-left: 15px; 90 | } 91 | 92 | .button{ 93 | width: 100%; 94 | margin-left: auto; 95 | margin-right: auto; 96 | } 97 | 98 | .form-field { 99 | width: 100%; 100 | margin-bottom: 5%; 101 | } 102 | } 103 | 104 | @media screen and (min-width: 600px) and (max-width: 1000px){ 105 | .form{ 106 | width: 65%; 107 | height: 60vh; 108 | } 109 | 110 | .form-upload{ 111 | margin-left: 22%; 112 | } 113 | 114 | .button{ 115 | width: 100%; 116 | margin-left: auto; 117 | margin-right: auto; 118 | } 119 | 120 | .form-field { 121 | width: 100%; 122 | margin-bottom: 5%; 123 | } 124 | } -------------------------------------------------------------------------------- /certificate/src/components/header/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Menu1Header from "../menu-1-header/index"; 3 | import "./style.css"; 4 | 5 | function Header() { 6 | return ( 7 |
8 | 9 | 10 |

11 | Certificates for Everyone 12 |

13 |
14 | ); 15 | } 16 | 17 | export default Header; 18 | -------------------------------------------------------------------------------- /certificate/src/components/header/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Gochi+Hand&display=swap'); 2 | @import url('https://fonts.googleapis.com/css2?family=Homemade+Apple&display=swap'); 3 | @import url('https://fonts.googleapis.com/css2?family=Pacifico&display=swap'); 4 | 5 | /* Inserido a foto como imagem de fundo */ 6 | .div-header { 7 | margin-top: 0; 8 | padding-bottom: 15%; 9 | background-image: url('../../assets/img/womakerscode-oficina.jpg'); 10 | background-repeat: no-repeat; 11 | background-size: cover; 12 | } 13 | 14 | /* Espaçamento do começo do texto em relação ao topo, tamanho e espaçamento das letras */ 15 | .h2-header { 16 | width: 100%; 17 | color: #ff1493; 18 | margin-top: 0%; 19 | padding-top: 10%; 20 | padding-left: 20%; 21 | 22 | font-size: 4rem; 23 | /*font-family: 'Gochi Hand', cursive;*/ 24 | /*font-family: 'Homemade Apple', cursive;*/ 25 | font-family: 'Pacifico', cursive; 26 | font-weight: 790; 27 | 28 | word-spacing: 1.5rem; 29 | letter-spacing: 0.2rem; 30 | } 31 | 32 | 33 | 34 | @media screen and (max-width: 800px) { 35 | .h2-header { 36 | width: 100%; 37 | font-size: 3.8rem; 38 | margin-top: 20%; 39 | padding-top: 5%; 40 | text-align: center; 41 | padding-left: 0%; 42 | 43 | } 44 | 45 | 46 | .div-header { 47 | padding-bottom: 30%; 48 | 49 | margin-bottom: -13%; 50 | } 51 | } 52 | 53 | 54 | @media screen and (min-width: 800px) and (max-width: 1200px){ 55 | .h2-header { 56 | width: 100%; 57 | font-size: 3.8rem; 58 | margin-top: 20%; 59 | padding-top: 5%; 60 | text-align: center; 61 | padding-left: 10%; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /certificate/src/components/info-event/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { List, Typography, Divider, Tag } from 'antd'; 3 | import './style.css' 4 | 5 | function InfoEvent(props) { 6 | 7 | const { evento } = props 8 | 9 | const dataEvent = [ 10 | 11 | { 12 | data: evento.company, 13 | description: "Comunidade" 14 | }, 15 | { 16 | data: evento.startDate, 17 | description: "Data de Inicio" 18 | }, 19 | { 20 | data: evento.finishDate, 21 | description: "Data de Encerramento" 22 | }, 23 | { 24 | data: evento.workload, 25 | description: "Carga Horária" 26 | }, 27 | 28 | ]; 29 | 30 | return ( 31 | <> 32 |
33 | 34 |
35 |
36 | {evento.course} 37 | Informações do evento
} 39 | bordered 40 | dataSource={dataEvent} 41 | renderItem={dataEvent => ( 42 | 43 | {dataEvent.description}{dataEvent.data} 44 | 45 | )} 46 | /> 47 | 48 | 49 | ); 50 | } 51 | 52 | export default InfoEvent; -------------------------------------------------------------------------------- /certificate/src/components/info-event/style.css: -------------------------------------------------------------------------------- 1 | /*Wallpaper*/ 2 | .up-info { 3 | background-image: url("../../assets/wallpaper-info-event.png"); 4 | background-repeat: no-repeat; 5 | background-size: cover; 6 | width: 100%; 7 | height: 60vh; 8 | margin-top: -10%; 9 | } 10 | 11 | /*Lista com as informações do evento*/ 12 | .list-info { 13 | width: 70%; 14 | margin-left: auto; 15 | margin-right: auto; 16 | margin-top: 5%; 17 | 18 | } -------------------------------------------------------------------------------- /certificate/src/components/list-events/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useRef } from 'react'; 2 | 3 | /*Estilos*/ 4 | import 'antd/dist/antd.css'; 5 | import { Button, Form, Card, 6 | Avatar, message, DatePicker, 7 | Input, Popover, Empty, InputNumber, Popconfirm } from 'antd'; 8 | 9 | import { LeftOutlined, HeartOutlined, 10 | FormOutlined, TeamOutlined, CloseOutlined, 11 | UsergroupAddOutlined, UserOutlined } from '@ant-design/icons'; 12 | 13 | import './styles.css'; 14 | import './styles-events.css'; 15 | import './style-form-event.css' 16 | import './style-digital-assinature.css' 17 | 18 | /*Importando os dados do evento*/ 19 | import eventosData from '../../services/events.json'; 20 | 21 | /*Componentes*/ 22 | import ProfileCard from '../../components/profile-card/index' 23 | import ListOfPresents from '../../components/list-presents/index' 24 | import InfoEvent from '../../components/info-event/index' 25 | 26 | /*Assinatura digital*/ 27 | import SignaturePad from 'react-signature-canvas' 28 | import Popup from 'reactjs-popup' 29 | 30 | function ListEvents(props) { 31 | 32 | const { Meta } = Card; 33 | /*Recebe o organizador e o JSON de organizadores*/ 34 | const { organizador, users } = props 35 | 36 | /*Trabalham para trocar a tela da lista de eventos com o formulário de edição/criação*/ 37 | const [ toEditFormEvent, setToEditFormEvent] = useState(false); 38 | const [ toCreateFormEvent, setToCreateFormEvent] = useState(false); 39 | const [ toProfile, setProfile] = useState(false); 40 | const [ toList, setList] = useState(false); 41 | const [ toSeeEvents, setSeeEvents] = useState(false); 42 | 43 | /*Esta variavel guarda o evento referente quando o botão check participantes for acionado*/ 44 | const [ eventChecked, setEventChecked] = useState(''); 45 | 46 | /*JSON dos eventos*/ 47 | const [ eventos, setEventos ] = useState(eventosData) 48 | 49 | /*Vaiável para saber qual evento foi editado*/ 50 | const [ eventEdited, setEventEdited ] = useState('') 51 | 52 | //Dados do evento: 53 | //Serão usados para editar no formulário 54 | const [ company, setCompany] = useState(''); 55 | const [ course, setCourse ] = useState(''); 56 | const [ startDate, setStartDate ] = useState(''); 57 | const [ finishDate, setFinishDate ] = useState(''); 58 | const [ workload, setWorkload ] = useState(''); 59 | 60 | /*---------- Assinatura Digital ----------*/ 61 | const [ imageURL, setImageURL ] = useState(null) 62 | 63 | const sigCanvas = useRef({}) 64 | 65 | const clear = () => sigCanvas.current.clear(); 66 | 67 | const save = () => { 68 | setImageURL(sigCanvas.current.getTrimmedCanvas().toDataURL("image/png")) 69 | } 70 | 71 | /*--------- Formulário para criar evento ---------*/ 72 | const { RangePicker } = DatePicker; 73 | 74 | /*Constroi o layout do input de datas*/ 75 | const formItemLayout = { 76 | labelCol: { 77 | xs: { 78 | span: 24, 79 | }, 80 | sm: { 81 | span: 8, 82 | }, 83 | }, 84 | wrapperCol: { 85 | xs: { 86 | span: 24, 87 | }, 88 | sm: { 89 | span: 16, 90 | }, 91 | }, 92 | }; 93 | 94 | /*Constroi o layout do input de name/curso*/ 95 | const formInputLayout = { 96 | labelCol: { 97 | span: 4, 98 | }, 99 | wrapperCol: { 100 | span: 8, 101 | }, 102 | }; 103 | 104 | /*Define as regras para que a data seja aceita */ 105 | const rangeConfig = { 106 | rules: [ 107 | { 108 | type: 'array', 109 | required: true, 110 | message: 'Este campo é obrigatório!', 111 | }, 112 | ], 113 | }; 114 | 115 | /*Define as regras para que os inputs de texto sejam aceitos */ 116 | const rangeInputs = { 117 | rules: [ 118 | { 119 | required: true, 120 | message: 'Por favor, preencha esse campo', 121 | }, 122 | ], 123 | }; 124 | 125 | /*Função acionada quando um evento for ser criado*/ 126 | /*Ela não é chamada caso os campos não forem preeenchidos*/ 127 | const onFinish = fieldsValue => { 128 | 129 | /*Dados do calendário*/ 130 | const rangeValue = fieldsValue['range-picker']; 131 | 132 | if(imageURL === null) { 133 | message.error('Por favor, escreva sua assinatura digital') 134 | } else { 135 | setEventos([ 136 | ...eventos, { 137 | user: organizador, 138 | company: fieldsValue.company, 139 | course: fieldsValue.course, 140 | startDate: rangeValue[0].format('DD-MM-YYYY'), 141 | finishDate: rangeValue[1].format('DD-MM-YYYY'), 142 | workload: fieldsValue.workload, 143 | logo: "https://miro.medium.com/max/478/1*jriufqYKgJTW4DKrBizU5w.png", 144 | digitalSignature: imageURL 145 | } 146 | ]) 147 | 148 | message.success('Evento criado com sucesso') 149 | 150 | /*Retira o componente do formulário de eventos e volta para a lista*/ 151 | setToCreateFormEvent(false) 152 | } 153 | }; 154 | 155 | /*Buscando os eventos do organizador*/ 156 | 157 | let eventsOfOrganizer = [] 158 | 159 | eventos.map(evento => { 160 | if(evento.user === organizador) { 161 | eventsOfOrganizer.push(evento) 162 | } 163 | }) 164 | 165 | /*Verifica se existem eventos cadastrados para mostrar elemento do Antd 'No Data'*/ 166 | let noEvents = true 167 | 168 | /* ------------- Deletando Eventos ---------------*/ 169 | const deleteEvent = (eventToBeDeleted) => { 170 | 171 | message.success('O evento foi excluido') 172 | 173 | setEventos( eventsOfOrganizer.filter(evento => { 174 | if(evento.course !== eventToBeDeleted) { 175 | return evento 176 | } 177 | })) 178 | } 179 | 180 | /* -------------- Editando eventos ----------------*/ 181 | const beforeEdit = () => { 182 | 183 | if( !company || !course || !startDate || !finishDate || ! workload || !imageURL){ 184 | message.error('Por favor, não deixe seus dados vazios.') 185 | //quando o formulário aparece na tela, essa mensagem aparece, caso o campo não tenha sido preenchido. 186 | } else { 187 | setToEditFormEvent(!toEditFormEvent) 188 | } 189 | } 190 | 191 | //Ao salvar as informações editadas: 192 | const saveEditFormEvent = (e) => { 193 | e.preventDefault(); 194 | //Os campos que devem ser preenchidos: 195 | if( !company || !course || !startDate || !finishDate || ! workload || !imageURL){ 196 | message.error('Por favor, preencha todos os campos do formulário.') 197 | //quando o formulário aparece na tela, essa mensagem aparece, caso o campo não tenha sido preenchido. 198 | 199 | } else { 200 | /*Atualizando o evento do organizador*/ 201 | setEventos(eventsOfOrganizer.map(evento => { 202 | 203 | /*Mudando somente o evento requerido*/ 204 | if(eventEdited === evento.course) { 205 | evento['company'] = company 206 | evento['course'] = course 207 | evento['startDate'] = startDate 208 | evento['finishDate'] = finishDate 209 | evento['workload'] = workload 210 | evento['digitalSignature'] = imageURL 211 | 212 | return evento; 213 | } else { 214 | return evento; 215 | } 216 | 217 | }) ) 218 | 219 | message.success('Os dados do evento foram atualizados com sucesso!') 220 | 221 | /*Voltando para a lista de eventos*/ 222 | //setToEditFormEvent(!toEditFormEvent) 223 | } 224 | 225 | } 226 | 227 | const clickEditFormEvent = (eventToBeEdit) => { 228 | 229 | /*Trocando a lista de eventos pelo formulário de edição*/ 230 | setToEditFormEvent(!toEditFormEvent) 231 | 232 | /*Guardando qual evento será editado*/ 233 | setEventEdited(eventToBeEdit.course) 234 | 235 | setCompany(eventToBeEdit.company) 236 | setCourse(eventToBeEdit.course) 237 | setStartDate(eventToBeEdit.startDate) 238 | setFinishDate(eventToBeEdit.finishDate) 239 | setWorkload(eventToBeEdit.workload) 240 | } 241 | 242 | /*Esta função é acionada quando o botão para o check list é acionado*/ 243 | const saveEventToList = (eventToList) => { 244 | setList(true) 245 | setEventChecked(eventToList) 246 | } 247 | 248 | /*Esta função é acionada quando o botão para mais infomações do evento*/ 249 | const seeEvents = (eventToList) => { 250 | setSeeEvents(true) 251 | setEventChecked(eventToList) 252 | } 253 | 254 | return( 255 | <> 256 | 257 |
258 | 259 |

setProfile(true)}/> {organizador}

260 | 261 | 262 | 263 |
264 |

Eventos Cadastrados

265 |
266 | { 267 | eventos.map(eventoJson => { 268 | 269 | if(eventoJson.user === organizador ){ 270 | noEvents = false 271 | return( 272 | 279 | } 280 | actions={[ 281 | <> 282 | Ver mais info. do evento}> 283 | 284 | 285 | 286 | Editar evento}> 287 | 288 | 289 | 290 | Participantes}> 291 | 292 | 293 | 294 | deleteEvent(eventoJson.course) } 297 | okText="Sim" 298 | cancelText="Não" 299 | > 300 | 301 | 302 | 303 | ]} 304 | > 305 | } 307 | title={

{eventoJson.course}

} 308 | description={ 309 | <> 310 |
Inicio:  {eventoJson.startDate}
311 | 312 |
Encerramento:  {eventoJson.finishDate}
313 | 314 | } 315 | /> 316 |
317 | ) 318 | } 319 | }) 320 | } 321 | { noEvents && } 322 |
323 | 324 |
325 | {toEditFormEvent && 326 | // Mostra na tela o formulário com os campos para serem editados 327 | //o value está trazendo as informações do último cadastrado "Lucas...." 328 | //quando eu troco o nome do course (Evento), altera o nome dos 3 eventos que estão sendo mostrados na tela 329 |
331 | 332 |

Edite os dados do seu evento:

333 |

Comunidade:

334 | setCompany(newValue.target.value) } /> 339 |
340 |

Evento:

341 | setCourse(newValue.target.value) }/> 346 |
347 |

Data de Inicio:

348 | setStartDate(newValue.target.value) }/> 353 |
354 |

Data de Encerramento:

355 | setFinishDate(newValue.target.value) }/> 360 |
361 |

Carga Horaria:

362 | setWorkload(newValue.target.value) }/> 367 |
368 |

Assinatura Digital:

369 |
370 | Abrir Pad para assinar}> 371 | { close => ( 372 | <> 373 | 378 | 379 | 380 | 381 | 382 | )} 383 | 384 |
385 |
386 | { imageURL ? ( 387 | Minha assinatura Digital 393 | ) : null } 394 |
395 | 396 | 399 |
400 | 401 | 402 |
403 | } 404 | 405 | { toCreateFormEvent && 406 | <> 407 | 408 |
409 |
410 |

Criando um novo evento

411 | 417 | 418 | 419 | 420 | 421 | 427 | 428 | 429 | 430 | 435 | 436 | 437 | 438 | 443 | 444 | 445 | 446 |
447 |

Assinatura Digital:

448 |
449 | Abrir Pad para assinar}> 450 | { close => ( 451 | <> 452 | 457 | 458 | 459 | 460 | 461 | )} 462 | 463 |
464 |
465 | { imageURL ? ( 466 | Minha assinatura Digital 471 | ) :

Sem assinatura

} 472 |
473 |
474 | 475 | 476 | 477 | 480 |
481 |
482 | 483 | 484 |
485 |
486 | 492 | 493 | } 494 | 495 | { toProfile && 496 | <> 497 | 498 | 504 | 505 | } 506 | 507 | { toList && 508 | <> 509 | 510 | 513 | 514 | } 515 | 516 | { 517 | toSeeEvents && 518 | <> 519 | 520 | 526 | 527 | } 528 | 529 | 530 | ); 531 | } 532 | 533 | export default ListEvents; -------------------------------------------------------------------------------- /certificate/src/components/list-events/style-digital-assinature.css: -------------------------------------------------------------------------------- 1 | 2 | /*Pad para assinar*/ 3 | .signatureCanvas { 4 | border: 1px solid black; 5 | width: 100%; 6 | min-height: 500px; 7 | } 8 | 9 | 10 | /*Assinatura gerada*/ 11 | .buttons-pad { 12 | display: block; 13 | margin: 0 auto; 14 | margin-left: 0%; 15 | border: 1px slid black; 16 | width: 150px; 17 | } 18 | 19 | .button-open-pad { 20 | color: orange; 21 | border-color: orange; 22 | } 23 | 24 | .button-save, .button-close { 25 | border-color: transparent; 26 | color: white; 27 | } 28 | 29 | .button-save { 30 | background-color: rgb(255, 91, 91); 31 | } 32 | 33 | .button-save:hover { 34 | background-color: white; 35 | border-color: rgb(255, 91, 91); 36 | color: rgb(255, 91, 91); 37 | transition: 0.5; 38 | } 39 | 40 | .button-close { 41 | background-color: black; 42 | } 43 | 44 | .button-close:hover { 45 | background-color: white; 46 | border-color: black; 47 | color: black; 48 | transition: 0.5; 49 | } 50 | -------------------------------------------------------------------------------- /certificate/src/components/list-events/style-form-event.css: -------------------------------------------------------------------------------- 1 | .h1-form-event { 2 | color: orange; 3 | } 4 | .h3-form-event { 5 | color: black; 6 | font-family: 'Raleway', sans-serif; 7 | font-weight: 400; 8 | font-size: 15px; 9 | } 10 | 11 | /*Fomulário para criar eventos*/ 12 | .inputs-event { 13 | margin-left: 20%; 14 | padding: 2%; 15 | } 16 | 17 | /*Carga horária e Datas*/ 18 | .input-3-event, .input-4-event { 19 | display: block; 20 | } 21 | 22 | .input-1-event { 23 | display: block; 24 | } 25 | 26 | .input-2-event { 27 | display: block; 28 | } 29 | 30 | .input-2-event { 31 | width: 100%; 32 | } 33 | 34 | /*Div em volta do pad da assinatura digital*/ 35 | .upload-assinature { 36 | display: block; 37 | } 38 | 39 | /*Botão para criar novo evento*/ 40 | .button-events { 41 | margin-left: 0%; 42 | margin-top: 3%; 43 | background-color: orange; 44 | border-color: orange; 45 | } 46 | 47 | .button-events:hover { 48 | background-color: white; 49 | border-color: orange; 50 | color: orange; 51 | transition: 1s; 52 | } 53 | 54 | /*Botão para voltar a lista de eventos dentro do form. para criar eventos*/ 55 | .button-back-from-create { 56 | display: flex; 57 | margin-left: 22%; 58 | margin-bottom: -30%; 59 | 60 | background-color: #616cd0; 61 | color: white; 62 | border-color: #616cd0; 63 | } 64 | 65 | .button-back-from-create:hover { 66 | background-color: white; 67 | color: #616cd0; 68 | border-color: #616cd0; 69 | transition: 0.5s; 70 | } 71 | 72 | 73 | @media screen and (max-width: 600px){ 74 | /*Carga horária e Datas*/ 75 | .input-3-event, .input-4-event { 76 | margin-left: 0%; 77 | } 78 | .h1-form-event, .inputs-event { 79 | margin-left: 0; 80 | } 81 | 82 | .button-back-from-create { 83 | margin-left: 2.5%; 84 | } 85 | } 86 | 87 | @media screen and (min-width: 600px) and (max-width: 1000px){ 88 | .inputs-event { 89 | margin-left: 3%; 90 | } 91 | 92 | .button-back-from-create { 93 | margin-left: 5%; 94 | } 95 | } -------------------------------------------------------------------------------- /certificate/src/components/list-events/styles-events.css: -------------------------------------------------------------------------------- 1 | /*Lista de eventos - div*/ 2 | .listEvents { 3 | display: grid; 4 | grid-template-columns: repeat(3, 1fr); 5 | margin-bottom: -30%; 6 | margin-right: auto; 7 | margin-left: 5%; 8 | } 9 | 10 | /*Para cada um dos eventos*/ 11 | .each-event { 12 | 13 | flex-direction: row; 14 | display: flex; 15 | width: 100%; 16 | margin-bottom: 3%; 17 | } 18 | 19 | /*Nome do evento*/ 20 | .course{ 21 | display: flex; 22 | justify-content: center; 23 | align-items: center; 24 | margin: 0; 25 | margin-right: 3%; 26 | font-weight: bold; 27 | } 28 | 29 | .button-check { 30 | border-color: transparent; 31 | color: gray; 32 | } 33 | 34 | .button-check:hover{ 35 | border-color: transparent; 36 | color: #C6255A; 37 | transition: 0.2s; 38 | } 39 | 40 | /*Titulo do evento dentro do card de info.*/ 41 | .h4-list-event { 42 | color: pink; 43 | font-weight: bold; 44 | } 45 | 46 | /*Informações do evento dentro do card de info.*/ 47 | .span-list-event { 48 | color: pink; 49 | } 50 | 51 | .button-info { 52 | margin-right: 3%; 53 | border-color: transparent; 54 | color: gray; 55 | } 56 | 57 | .button-info:hover { 58 | border-color: pink; 59 | color: pink; 60 | transition: 0.2s; 61 | } 62 | .button-edit { 63 | margin-right: 1%; 64 | background-color: #d6815b; 65 | border-color: #d6815b; 66 | color: white; 67 | } 68 | 69 | .button-edit:hover { 70 | background-color: white; 71 | border-color: #d6815b; 72 | color: #d6815b; 73 | transition: 0.5s; 74 | } 75 | 76 | .button-delete { 77 | background-color: #cc0000; 78 | border-color: #cc0000; 79 | color: white; 80 | } 81 | 82 | .button-delete:hover { 83 | background-color: white; 84 | border-color: #cc0000; 85 | color: #cc0000; 86 | transition: 0.5s; 87 | } 88 | 89 | /*Formulário de edição do evento*/ 90 | 91 | /*Form inteiro*/ 92 | .edit-event { 93 | display: flex; 94 | margin: 5% auto; 95 | width: 50%; 96 | margin-bottom: -30%; 97 | } 98 | 99 | /*Titulo: edite seus dados*/ 100 | .edit-event-title{ 101 | display: flex; 102 | justify-content: center; 103 | } 104 | 105 | /*Inputs do formulário*/ 106 | .edit-event-input{ 107 | width: 100%; 108 | margin-bottom: 2%; 109 | } 110 | 111 | /*Botão para atualizar os dados*/ 112 | .button-edit-event { 113 | background-color: orange; 114 | color: white; 115 | border-color: orange; 116 | width: 50%; 117 | text-align: center; 118 | margin-bottom: 2%; 119 | 120 | margin-left: 25%; 121 | } 122 | 123 | .button-edit-event:hover { 124 | background-color: white; 125 | color: orange; 126 | border-color: orange; 127 | transition: 0.5s; 128 | } 129 | 130 | /*Botão para voltar do formulário de edição para a lista de eventos*/ 131 | .back-edit-event { 132 | background-color: #616cd0; 133 | color: white; 134 | border-color: #616cd0; 135 | width: 50%; 136 | margin-left: 25%; 137 | } 138 | 139 | .back-edit-event:hover { 140 | background-color: white; 141 | color: #616cd0; 142 | border-color: #616cd0; 143 | transition: 0.5s; 144 | } 145 | 146 | 147 | @media screen and (max-width: 800px) { 148 | .edit-event, .back-edit-event, .button-edit-event { 149 | width: 80%; 150 | } 151 | 152 | .back-edit-event, .button-edit-event { 153 | margin-left: auto; 154 | margin-right: auto; 155 | } 156 | .each-event { 157 | display: block; 158 | } 159 | 160 | .listEvents { 161 | grid-template-columns: repeat(1, 1fr); 162 | margin-left: 20%; 163 | } 164 | 165 | .title{ 166 | margin-left: 22%; 167 | } 168 | 169 | .title-2-list-events { 170 | margin-left: 75%; 171 | } 172 | } 173 | 174 | @media screen and (min-width: 600px) and (max-width: 1000px){ 175 | .edit-event, .back-edit-event, .button-edit-event { 176 | width: 70%; 177 | } 178 | 179 | .back-edit-event, .button-edit-event { 180 | margin-left: 15%; 181 | } 182 | } 183 | 184 | @media screen and (min-width: 800px) and (max-width: 1000px){ 185 | .listEvents { 186 | grid-template-columns: repeat(2, 1fr); 187 | } 188 | } 189 | 190 | -------------------------------------------------------------------------------- /certificate/src/components/list-events/styles.css: -------------------------------------------------------------------------------- 1 | /*Bem vindo organizador*/ 2 | .title-2-list-events { 3 | margin-left: 85%; 4 | margin-top: -7%; 5 | font-size: 15px; 6 | } 7 | 8 | /*Lista de eventos*/ 9 | .title{ 10 | display: flex; 11 | margin-left: 5%; 12 | color: #C6255A; 13 | } 14 | 15 | 16 | .button-add{ 17 | border-color: rgb(0, 176, 240); 18 | background-color: rgb(0, 176, 240); 19 | color: #ffffff; 20 | border-radius: 5px; 21 | border-width: 0.2em; 22 | font-size: 15px; 23 | height: 50px; 24 | margin-left: 5%; 25 | margin-bottom: 2%; 26 | } 27 | 28 | .button-add:hover { 29 | border-color: rgb(0, 176, 240); 30 | color: rgb(0, 176, 240); 31 | transition: 0.3s; 32 | } 33 | 34 | .button-profile { 35 | border-color: #c6255a; 36 | background-color: #c6255a; 37 | color: #ffffff; 38 | border-radius: 5px; 39 | border-width: 0.2em; 40 | font-size: 15px; 41 | height: 50px; 42 | margin-left: 5%; 43 | margin-bottom: 5%; 44 | } 45 | 46 | .button-profile:hover { 47 | border-color: #c6255a; 48 | color: #c6255a; 49 | transition: 0.3s; 50 | } 51 | 52 | /*Botão para voltar para a lista de eventos dentro do perfil*/ 53 | .button-back-of-profile { 54 | display: flex; 55 | margin-left: 10%; 56 | margin-top: 5%; 57 | margin-bottom: -30%; 58 | 59 | background-color: #616cd0; 60 | color: white; 61 | border-color: #616cd0; 62 | } 63 | 64 | .button-back-of-profile:hover { 65 | background-color: white; 66 | color: #616cd0; 67 | border-color: #616cd0; 68 | transition: 0.5s; 69 | } 70 | 71 | /*Botão para volta a lista de eventos estando na lista de participantes*/ 72 | .button-back-from-list { 73 | display: flex; 74 | background-color: #616cd0; 75 | color: white; 76 | border-color: #616cd0; 77 | margin-left: auto; 78 | margin-right: auto; 79 | margin-bottom: -30%; 80 | } 81 | 82 | .button-back-from-list:hover { 83 | background-color: white; 84 | color: #616cd0; 85 | border-color: #616cd0; 86 | transition: 0.5s; 87 | } 88 | 89 | /*Botão para voltar para a lista de eventos*/ 90 | .button-back-of-event { 91 | background-color: pink; 92 | margin-top: -20%; 93 | } -------------------------------------------------------------------------------- /certificate/src/components/list-presents/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import jsPDF from 'jspdf'; 3 | import html2canvas from 'html2canvas'; 4 | 5 | /*Estilos*/ 6 | import './style.css' 7 | import './style-certificate.css' 8 | import 'antd/dist/antd.css'; 9 | import { Checkbox, Button, Input, message, Table, Tag, Popover, Popconfirm } from 'antd'; 10 | 11 | import { UserAddOutlined } from '@ant-design/icons'; 12 | 13 | /*Animação de tela enquanto o e-mail é enviado*/ 14 | import Spinner from 'react-spinkit' 15 | import './style-spinkit.css' 16 | 17 | /*Importando lista de participantes*/ 18 | import participantesData from '../../services/participantes.json' 19 | 20 | import stars from '../../assets/stars.png' 21 | import logo from '../../assets/img/logo_texto_preto.png' 22 | 23 | function ListOfPresents(props) { 24 | 25 | /*Recebe o evento selecionado pelo organizador*/ 26 | const { evento } = props 27 | 28 | /*Nome do novo participante no input*/ 29 | const [ name, setName ] = useState('') 30 | 31 | /*E-mail do novo participante no input*/ 32 | const [ email, setEmail ] = useState('') 33 | 34 | /*JSON dos participantes*/ 35 | const [ participantes, setParticipantes ] = useState(participantesData) 36 | 37 | /*Variavel que troca a lista de participants pelos certificados*/ 38 | const [ visible, setVisible ] = useState(true) 39 | 40 | /*Variavel que troca a lista de participants pelos formulário*/ 41 | const [ visibleForm, setVisibleForm ] = useState(false) 42 | 43 | /*Participante selecionado*/ 44 | const [ thisParticipante, setThisParticipante ] = useState('') 45 | 46 | /*Variavel que mostrará uma animação enquanto o e-mail é enviado*/ 47 | const [ loadingEmail, setLoadingEmail] = useState(false) 48 | 49 | /*------- Informações adicionais sobre o evento ------*/ 50 | let numeroDeParticipantes = 0 51 | let certificadosEvenviados = 0 52 | let participantesConfirmados = 0 53 | 54 | const showModal = (participante) => { 55 | setVisible(false) 56 | setThisParticipante(participante) 57 | } 58 | 59 | /*Valida os campos de input*/ 60 | const verificarCampos = () => { 61 | if(!name || !email ) { 62 | message.error('Por favor, preencha todos os campos') 63 | 64 | } else { 65 | 66 | /*Verificando se o e-mail é valido */ 67 | if( !email.includes('@') || !email.includes('.') ){ 68 | message.error('E-mail invalido!') 69 | 70 | } else { 71 | 72 | /*Verificando se já existe um participante cadastrado*/ 73 | let listEmails = [] 74 | 75 | participantes.map(itemJson => { 76 | 77 | if(itemJson.course === evento.course) { 78 | listEmails.push(itemJson.email) 79 | } 80 | }) 81 | 82 | if(!listEmails.includes(email)) { 83 | 84 | setParticipantes([ 85 | ...participantes, { 86 | name: name, 87 | email: email, 88 | present: true, 89 | receiveCertificate: false, 90 | course: evento.course 91 | } 92 | ]) 93 | 94 | /*Volta para a lista de participntes*/ 95 | setVisibleForm(false) 96 | message.success('Participante criado com sucesso') 97 | setName('') 98 | setEmail('') 99 | 100 | } else { 101 | 102 | message.warning('Este participante já está na sua lista') 103 | } 104 | } 105 | } 106 | } 107 | 108 | /* ------------- Deletando Participantes ---------------*/ 109 | const deleteParticipant = (participantToBeDeleted) => { 110 | 111 | setParticipantes( participantes.filter(participante => { 112 | if(participante.name !== participantToBeDeleted) { 113 | return participante 114 | } 115 | })) 116 | } 117 | 118 | /*Na mudança de check do participante*/ 119 | const onChange = (participante) => { 120 | 121 | setParticipantes(participantes.map(itemParticipante => { 122 | 123 | if(itemParticipante.name === participante.name) { 124 | itemParticipante['present'] = !participante.present 125 | 126 | if(participante.present) { 127 | message.success('Este participante receberá certificado') 128 | 129 | } else { 130 | message.info('Este participante não receberá certificado') 131 | } 132 | 133 | return itemParticipante; 134 | } else { 135 | 136 | return itemParticipante; 137 | } 138 | 139 | })) 140 | } 141 | 142 | /*Função destinada ao envio de e-mail, recebe o e-mail do participante*/ 143 | const sendEmail = (to) =>{ 144 | 145 | /*Este e-mail enviará os certificados*/ 146 | let from = "certificadowomakerscode@gmail.com" 147 | 148 | setLoadingEmail(true) 149 | const input = document.getElementsByClassName('certificate-background')[0]; 150 | window.scrollTo(0,0); 151 | html2canvas(input, { 152 | windowWidth: input.scrollWidth, 153 | windowHeight: input.scrollHeight 154 | }) 155 | .then((canvas) => { 156 | const imgData = canvas.toDataURL('image/png'); 157 | const pdf = new jsPDF('l', 'mm', 'a4', true); 158 | 159 | pdf.addImage(imgData, 'PNG', 3, 3, 380, 265, '', 'SLOW'); 160 | var formData = new FormData(); 161 | formData.append('file', new Blob([pdf.output('blob')], {type: 'application/pdf'}), "certificado.pdf"); 162 | formData.append('from', from); 163 | formData.append('to', to); 164 | 165 | fetch('http://localhost:8080/send-mail', { 166 | method: 'POST', 167 | body: formData, 168 | }) 169 | .then(success => message.success("Email enviado com sucesso!")) 170 | .then(before => setLoadingEmail(false)) 171 | .catch(error => message.error("Não foi possível enviar seu email!") 172 | .then(before => setLoadingEmail(false)) 173 | ); 174 | }); 175 | 176 | 177 | 178 | setParticipantes(participantes.map(itemParticipante => { 179 | 180 | /*Buscando o participante que recebeu o email*/ 181 | if(itemParticipante.email === to) { 182 | 183 | itemParticipante['receiveCertificate'] = true 184 | return itemParticipante; 185 | 186 | } else { 187 | 188 | return itemParticipante; 189 | } 190 | 191 | })) 192 | 193 | } 194 | 195 | const dataSource = [] 196 | 197 | /*Preenchendo lista de participantes*/ 198 | participantes.map((participante, key) => { 199 | if(participante.course === evento.course) { 200 | 201 | let statusCertificate = '' 202 | let statusPresense = '' 203 | let colorCertificate = '' 204 | let colorPresense = '' 205 | 206 | /*Verifica se o participante recebeu certificado*/ 207 | statusCertificate = (participante.receiveCertificate) ? 'Enviado' : 'Não Enviado' 208 | colorCertificate = (participante.receiveCertificate) ? 'green' : 'orange' 209 | 210 | /*Verifica se o participante está confirmado no evento*/ 211 | statusPresense = (participante.present) ? 'Confirmada' : 'Não Confirmado' 212 | colorPresense = (participante.present) ? 'green' : 'red' 213 | 214 | dataSource.push({ 215 | key: key, 216 | checkbox: onChange(participante) }> 219 | , 220 | 221 | participante: participante.name, 222 | 223 | email: participante.email, 224 | 225 | status: {statusCertificate}, 226 | 227 | presense: {statusPresense}, 228 | 229 | certificado: , 236 | 237 | delete: 238 | deleteParticipant(participante.name) } 241 | okText="Sim" 242 | cancelText="Não" 243 | > 244 | 248 | 249 | }) 250 | } 251 | 252 | }) 253 | 254 | const columns = [ 255 | { 256 | title: 'Atualizar Presença', 257 | dataIndex: 'checkbox', 258 | key: 'checkbox' 259 | }, 260 | { 261 | title: 'Participante', 262 | dataIndex: 'participante', 263 | key: 'participante', 264 | }, 265 | { 266 | title: 'E-mail', 267 | dataIndex: 'email', 268 | key: 'email', 269 | }, 270 | { 271 | title: 'Status', 272 | dataIndex: 'status', 273 | key: 'status', 274 | }, 275 | { 276 | title: 'Presença', 277 | dataIndex: 'presense', 278 | key: 'presense', 279 | }, 280 | , 281 | { 282 | title: 'Certificado', 283 | dataIndex: 'certificado', 284 | key: 'certificado', 285 | } 286 | , 287 | { 288 | title: 'Excluir da lista', 289 | dataIndex: 'delete', 290 | key: 'delete', 291 | } 292 | ]; 293 | 294 | return ( 295 | <> 296 |
297 |
298 |

Adicione mais participantes a sua lista:

299 | setName(newName.target.value)}/> 300 |
301 | setEmail(newEmail.target.value)}/> 302 |
303 | 304 | 305 |
306 | 307 |
308 | 309 | 310 |

Lista de Participantes

311 | Click para enviar certificados para todos os participantes}> 312 | 313 | 314 | 315 | Click para cancelar a presença de todos os participantes}> 316 | 317 | 318 | 319 | 320 | 321 | 322 |
323 | 324 | { loadingEmail && 325 |
326 | 327 |
} 328 | 329 |
330 | Logo da empresa 331 | 5 estrelas 332 |

A comunidade {evento.company} confere ao participante {thisParticipante.name} o presente certificado 333 |
referente a sua participação no evento {evento.course} realizado do 334 |
dia {evento.startDate} ao {evento.finishDate}, com carga horaria de {evento.workload} horas. 335 |
336 |

337 | Assinatura Digital 338 |
339 |

{evento.user}

340 |
341 | 342 | 343 | 344 |
345 | 346 | ); 347 | } 348 | 349 | export default ListOfPresents; 350 | -------------------------------------------------------------------------------- /certificate/src/components/list-presents/style-certificate.css: -------------------------------------------------------------------------------- 1 | .certificate-background { 2 | text-align: center; 3 | align-items: center; 4 | justify-content: center; 5 | font-family: 'Raleway', sans-serif; 6 | font-weight: 200; 7 | font-size: 1.5vw; 8 | 9 | background: url('../../assets/wallpaper-certificate.png'); 10 | background-repeat: no-repeat; 11 | background-size: 100%; 12 | 13 | margin-left: 10%; 14 | margin-right: 10%; 15 | margin-top: 5%; 16 | margin-bottom: 10%; 17 | } 18 | 19 | /*Logo*/ 20 | .img-logo-certificate { 21 | display: flex; 22 | margin-left: 40%; 23 | margin-top: 10%; 24 | width: 15%; 25 | } 26 | 27 | /*Estrelas*/ 28 | .img-stars { 29 | display: flex; 30 | margin-left: 45%; 31 | width: 70px; 32 | height: 15px; 33 | } 34 | 35 | /*Texto*/ 36 | .p-certificate { 37 | margin-left: 5%; 38 | margin-top: 5%; 39 | width: 90%; 40 | } 41 | 42 | /*Assinatura Digital*/ 43 | .digitalSignature { 44 | width: 80px; 45 | height: 80px; 46 | } 47 | 48 | hr { 49 | width: 35%; 50 | color: black; 51 | margin-top: 0%; 52 | margin-left: 30%; 53 | background-color: brown; 54 | } 55 | 56 | /*Colocando as informações principais do certificado em negrito*/ 57 | .info-certificate { 58 | font-weight: 400; 59 | color: black; 60 | } 61 | 62 | /*Nome do organizador do evento*/ 63 | .p-2-certificate { 64 | margin-left: 32%; 65 | margin-bottom: 10%; 66 | 67 | width: 30%; 68 | } 69 | 70 | /*Botão para voltar a lista de participantes*/ 71 | .button-voltar { 72 | display: flex; 73 | margin-left: auto; 74 | margin-right: auto; 75 | margin-bottom: 3%; 76 | 77 | background-color: #00b7d2; 78 | border-color: #00b7d2; 79 | color: white; 80 | } 81 | 82 | .button-voltar:hover { 83 | background-color: white; 84 | border-color: #00b7d2; 85 | color: #00b7d2; 86 | transition: 0.5s; 87 | } 88 | 89 | .button-email { 90 | 91 | display: flex; 92 | margin-left: auto; 93 | margin-right: auto; 94 | margin-top: -5%; 95 | margin-bottom: 3%; 96 | 97 | background-color: #50c878; 98 | border-color: #50c878; 99 | color: white; 100 | } 101 | 102 | .button-email:hover { 103 | background-color: white; 104 | border-color: #50c878; 105 | color: #50c878; 106 | transition: 0.5s; 107 | } 108 | 109 | @media screen and (max-width: 700px) { 110 | .div-buttons { 111 | grid-template-columns: repeat(1, 1fr); 112 | } 113 | } 114 | 115 | @media screen and (max-width: 800px) { 116 | .img-logo-certificate { 117 | margin-top: 10%; 118 | margin-left: 46.5%; 119 | width: 10%; 120 | height: 10%; 121 | } 122 | 123 | .img-stars { 124 | width: 35px; 125 | height: 7.5px ; 126 | margin-left: 47%; 127 | } 128 | 129 | /*Assinatura Digital*/ 130 | .digitalSignature { 131 | width: 20px; 132 | height: 20px; 133 | } 134 | } 135 | 136 | @media screen and (min-width: 800px) and (max-width: 1000px){ 137 | .img-logo-certificate { 138 | margin-top: 5%; 139 | margin-left: 40%; 140 | } 141 | 142 | .button-pdf { 143 | background-color: pink; 144 | } 145 | 146 | /*Assinatura Digital*/ 147 | .digitalSignature { 148 | width: 40px; 149 | height: 40px; 150 | } 151 | } -------------------------------------------------------------------------------- /certificate/src/components/list-presents/style-spinkit.css: -------------------------------------------------------------------------------- 1 | 2 | .overlay-content { 3 | display: flex; 4 | width: 100%; 5 | left: 0; 6 | top: 0; 7 | align-items: center; 8 | height: 100%; 9 | justify-content: center; 10 | position: fixed; 11 | z-index: 999999; 12 | background: rgba(0, 0, 0, 0.7); 13 | flex-direction: column; 14 | } 15 | 16 | .overlay-content .wrapper { 17 | display: inherit; 18 | width: 100%; 19 | height: 100%; 20 | align-items: center; 21 | justify-content: center; 22 | flex-direction: column; 23 | } 24 | 25 | .overlay-content .wrapper .message { 26 | margin-top: 20px; 27 | color: white; 28 | font-weight: bold; 29 | text-shadow: 0 2px 5px black; 30 | } 31 | 32 | /* react-spinkit */ 33 | 34 | .sk-spinner.pacman > div:nth-child(n+3):nth-child(-n+5) { 35 | color: white; 36 | z-index: -1; 37 | } 38 | -------------------------------------------------------------------------------- /certificate/src/components/list-presents/style.css: -------------------------------------------------------------------------------- 1 | 2 | /*Div do titulo, lista de participantes e botão*/ 3 | .list-participants { 4 | display: grid; 5 | grid-template-columns: repeat(1, 1fr); 6 | padding: 3%; 7 | width: 100%; 8 | } 9 | 10 | /*Botão para adicionar participante*/ 11 | .button-add-participant { 12 | border-color: orange; 13 | background-color: orange; 14 | color: #ffffff; 15 | border-radius: 5px; 16 | border-width: 0.2em; 17 | font-size: 15px; 18 | height: 50px; 19 | margin-left: 0%; 20 | margin-bottom: 2%; 21 | margin-top: -10%; 22 | width: 20%; 23 | } 24 | 25 | .button-add-participant:hover { 26 | background-color: white; 27 | border-color: orange; 28 | color: orange; 29 | transition: 0.3s; 30 | } 31 | 32 | /*Botão para cancelar a presença de todos*/ 33 | .buttom-send-to-all { 34 | border-color: #98fb98; 35 | background-color: #98fb98; 36 | color: black; 37 | width: 15%; 38 | margin-left: 0%; 39 | margin-bottom: 2%; 40 | } 41 | 42 | .buttom-send-to-all:hover { 43 | border-color: #98fb98; 44 | background-color: #98fb98; 45 | color: #ffffff; 46 | box-shadow: 4px 4px 8px gray; 47 | } 48 | 49 | /*Botão para enviar e-mail a todos*/ 50 | .buttom-cancel { 51 | border-color: #fa7f72; 52 | background-color: #fa7f72; 53 | color: #ffffff; 54 | width: 15%; 55 | margin-left: 2%; 56 | margin-bottom: 2%; 57 | } 58 | 59 | .buttom-cancel:hover { 60 | border-color: #fa7f72; 61 | background-color: #fa7f72; 62 | color: #ffffff; 63 | box-shadow: 4px 4px 8px gray; 64 | } 65 | 66 | /*---------------------------------*/ 67 | 68 | /*Div de formulário*/ 69 | .input-participantes { 70 | text-align: center; 71 | width: 40%; 72 | margin-top: -5%; 73 | margin-right: auto; 74 | margin-left: auto; 75 | } 76 | /*Buttom para inserir um participante*/ 77 | .button-parcipants { 78 | margin-top: 3%; 79 | margin-bottom: 8%; 80 | } 81 | 82 | /*Voltar para a lista de participantes a partir do formulário*/ 83 | .buttom-voltar-participants { 84 | width: 45%; 85 | margin-right: auto; 86 | margin-left: auto; 87 | margin-bottom: -5%; 88 | background-color: #00b7d2; 89 | border-color: #00b7d2; 90 | color: white; 91 | } 92 | 93 | .button-voltar-participants:hover { 94 | background-color: white; 95 | border-color: #00b7d2; 96 | color: #00b7d2; 97 | transition: 0.5s; 98 | } 99 | 100 | .buttom-ver-certificado { 101 | margin-left: 3%; 102 | margin-right: 1%; 103 | } 104 | 105 | /*-------------------------------------*/ 106 | 107 | /*Lista de participantes*/ 108 | .title-2 { 109 | margin-top: 0; 110 | color: #c6255a; 111 | font-family: 'Raleway', sans-serif; 112 | } 113 | 114 | 115 | @media screen and (max-width: 600px) { 116 | .input-participantes { 117 | width: 100%; 118 | } 119 | 120 | .buttom-voltar-participants { 121 | margin-bottom: 1%; 122 | } 123 | } 124 | 125 | 126 | @media screen and (max-width: 800px) { 127 | .list-participants { 128 | grid-template-columns: repeat(1, 1fr); 129 | } 130 | 131 | .title-2 { 132 | margin-top: 5%; 133 | } 134 | 135 | .input-participantes { 136 | width: 70%; 137 | } 138 | 139 | .buttom-voltar-participants { 140 | margin-bottom: 1%; 141 | } 142 | 143 | .button-add-participant { 144 | width: 30%; 145 | } 146 | 147 | .buttom-send-to-all, .buttom-cancel { 148 | width: 20%; 149 | } 150 | } 151 | 152 | @media screen and (min-width: 800px) and (max-width: 1000px){ 153 | .input-participantes { 154 | width: 70%; 155 | } 156 | 157 | .buttom-voltar-participants { 158 | margin-bottom: -2%; 159 | } 160 | 161 | .button-add-participant { 162 | width: 30%; 163 | } 164 | 165 | .buttom-send-to-all, .buttom-cancel { 166 | width: 25%; 167 | } 168 | } 169 | 170 | -------------------------------------------------------------------------------- /certificate/src/components/menu-1-header/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import logoWomakers from "../../assets/img/logo_texto_branco.png"; 4 | import "./style.css"; 5 | 6 | function Menu1Header() { 7 | return ( 8 |
9 | logo 10 | 11 |
    12 |
  • Home
  • 13 |
  • Cadastro
  • 14 |
  • Login
  • 15 |
16 |
17 | ); 18 | } 19 | 20 | export default Menu1Header; -------------------------------------------------------------------------------- /certificate/src/components/menu-1-header/style.css: -------------------------------------------------------------------------------- 1 | .menu-1-header { 2 | display: block; 3 | background-color: transparent; 4 | } 5 | 6 | .logo-menu-header { 7 | width: 120px; 8 | height: 80px; 9 | margin-left: 10%; 10 | } 11 | 12 | .menu-list-header { 13 | display: inline-flex; 14 | margin-left: 45%; 15 | } 16 | 17 | .menu-list-header li { 18 | font-size: 1rem; 19 | color: white; 20 | padding: 2px 10px; 21 | } 22 | 23 | .menu-list-header li:hover { 24 | color: orange; 25 | } 26 | 27 | @media screen and (max-width: 600px) { 28 | .menu-list-header { 29 | margin-left: 5%; 30 | } 31 | } 32 | 33 | @media screen and (min-width: 600px) and (max-width: 1000px){ 34 | .menu-list-header { 35 | margin-left: 20%; 36 | } 37 | } -------------------------------------------------------------------------------- /certificate/src/components/menu-1/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import logoWomakers from "../../assets/img/logo_texto_cinza.png"; 4 | import "./style.css"; 5 | 6 | function MenuComponent() { 7 | return ( 8 |
9 | logo 10 | 11 |
    12 |
  • Cadastro
  • 13 |
  • Login
  • 14 |
15 |
16 | ); 17 | } 18 | 19 | export default MenuComponent; -------------------------------------------------------------------------------- /certificate/src/components/menu-1/style.css: -------------------------------------------------------------------------------- 1 | .menu-1 { 2 | display: block; 3 | background-color: white; 4 | box-shadow: 0px 0px 4px gray; 5 | } 6 | 7 | .logo-menu { 8 | width: 110px; 9 | height: 70px; 10 | margin-left: 10%; 11 | } 12 | 13 | .menu-list { 14 | display: inline-flex; 15 | margin-left: 45%; 16 | } 17 | 18 | .menu-list li { 19 | font-size: 1rem; 20 | color: gray; 21 | padding: 2px 10px; 22 | } 23 | 24 | .menu-list li:hover { 25 | color: orange; 26 | } 27 | 28 | @media screen and (max-width: 760px) { 29 | .menu-list { 30 | margin-left: 30%; 31 | } 32 | } 33 | 34 | @media screen and (max-width: 600px) { 35 | .menu-list { 36 | margin-left: 20%; 37 | } 38 | } -------------------------------------------------------------------------------- /certificate/src/components/message-alert/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './style.css' 3 | 4 | function MessageAlert(props) { 5 | 6 | return ( 7 |
8 |

9 | 10 | Os certificados foram enviados com sucesso,
11 | obrigada por usar nossa plataforma. 12 |

13 |
14 | ); 15 | } 16 | 17 | export default MessageAlert; -------------------------------------------------------------------------------- /certificate/src/components/message-alert/style.css: -------------------------------------------------------------------------------- 1 | .h3-success { 2 | text-align: center; 3 | font-family: 'Releway', sans-serif; 4 | font-size: 30px; 5 | font-weight: 300; 6 | color: black; 7 | display: block; 8 | margin: 20px auto; 9 | margin-top: 15%; 10 | position: relative; 11 | } 12 | 13 | .span-success { 14 | color: #c6255a; 15 | font-weight: bold; 16 | } 17 | 18 | @media screen and (max-width: 800px) { 19 | .h3-success{ 20 | font-size: 20px; 21 | } 22 | .span-success { 23 | font-size: 20px; 24 | } 25 | } -------------------------------------------------------------------------------- /certificate/src/components/model-certificate-home/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import './style.css'; 3 | import modelCertificate from '../../assets/model_certificate.png' 4 | 5 | function ModelCertificateHome(props) { 6 | 7 | return ( 8 |
9 |

Nosso modelo

10 | Modelo de Certificado 11 |
12 | ); 13 | } 14 | 15 | export default ModelCertificateHome; -------------------------------------------------------------------------------- /certificate/src/components/model-certificate-home/style.css: -------------------------------------------------------------------------------- 1 | .model { 2 | background-image: url('../../assets/wallpaper-section.jpg.png'); 3 | 4 | /*Compensando o margin-top definido para o footer*/ 5 | margin-bottom: -40%; 6 | } 7 | 8 | .sub-title-1 { 9 | border-color: #c6255a; 10 | border-top-style: solid; 11 | border-top-width: 7px; 12 | color: black; 13 | } 14 | 15 | .h1-model { 16 | margin-left: 3%; 17 | margin-top: 3%; 18 | font-family: 'Raleway', sans-serif; 19 | padding-top: 3%; 20 | } 21 | 22 | .model-color { 23 | color: #c6255a; 24 | font-weight: bold; 25 | } 26 | 27 | .modelCertificate { 28 | width: 50%; 29 | height: 50%; 30 | margin-top: 3%; 31 | margin-left: 25%; 32 | margin-bottom: 15%; 33 | } 34 | 35 | .modelCertificate:hover { 36 | box-shadow: 4px 4px 8px gray; 37 | transition: 1s; 38 | } 39 | 40 | @media screen and (max-width: 1280px) { 41 | .h1-model { 42 | margin-top: 6%; 43 | padding-top: 6%; 44 | } 45 | 46 | 47 | .modelCertificate { 48 | width: 70%; 49 | height: 70%; 50 | margin-left: 15%; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /certificate/src/components/profile-card/index.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | 3 | /*Estilos*/ 4 | import 'antd/dist/antd.css'; 5 | import { Avatar, message, Button, Input, Popconfirm } from 'antd'; 6 | import './style.css' 7 | 8 | /*Rotas*/ 9 | import { Redirect } from 'react-router-dom' 10 | 11 | function ProfileCard(props) { 12 | 13 | const { organizador, users, assinatura } = props 14 | 15 | /*Variável que irá renderizar o formulário de registro, mas com 16 | os dados do usuário para que possam ser atualizados*/ 17 | 18 | const [ toEditForm, setToEditForm] = useState(false) 19 | 20 | /*JSON dos usuários*/ 21 | const [ user, setUser ] = useState(users) 22 | 23 | /*Variável que irá permitir o retorno a Home após o usuário excluir a sua conta*/ 24 | const [ goToHome, setGoHome ] = useState(false) 25 | 26 | /*Recuperando os dados do usuário logado para inserir como valor inicial nos inputs*/ 27 | let nameProfile = "" 28 | let emailProfile = "" 29 | let passwordProfile = "" 30 | let avatarProfile = "" 31 | 32 | user.map(itemJson => { 33 | if(itemJson.token) { 34 | nameProfile = itemJson.name 35 | emailProfile = itemJson.email 36 | passwordProfile = itemJson.password 37 | avatarProfile = itemJson.avatar 38 | } 39 | }) 40 | 41 | /*Dados do perfil do usuário. 42 | Serão utilizados para mostrar seus dados na tela e para edita-los no forumulário*/ 43 | const [ name, setName ] = useState(nameProfile) 44 | const [ email, setEmail ] = useState(emailProfile) 45 | const [ password, setPassword] = useState(passwordProfile) 46 | 47 | /*Quando a opção de editar conta for acionada*/ 48 | const beforeEditForm = (event) => { 49 | event.preventDefault(); 50 | setToEditForm(!toEditForm) 51 | } 52 | 53 | /*Quando o usuário concluir as suas modificações, esta função será executada*/ 54 | const afterEditForm = (event) => { 55 | event.preventDefault(); 56 | 57 | if( !name || !email || !password ) { 58 | message.error('Os dados não podem ficar vázios') 59 | 60 | } else { 61 | setToEditForm(!toEditForm) 62 | 63 | /*Atualizando os dados do perfil*/ 64 | setUser( 65 | user.map(itemJson => { 66 | 67 | /*Atualizando o JSON de usuários sem o usuário ativo*/ 68 | if(itemJson.name === organizador){ 69 | itemJson['name'] = name 70 | itemJson['email'] = email 71 | itemJson['password'] = password 72 | 73 | return itemJson 74 | } else { 75 | return itemJson 76 | } 77 | }) 78 | ) 79 | 80 | message.success('Seus dados foram atualizados') 81 | } 82 | 83 | 84 | 85 | } 86 | 87 | /*Quando a opção de deletar conta for acionada*/ 88 | const deleteAccount = (event) => { 89 | event.preventDefault(); 90 | setUser( 91 | user.map(itemJson => { 92 | 93 | /*Atualizando o JSON de usuários sem o usuário ativo*/ 94 | if(itemJson.token){ 95 | itemJson['name'] = '' 96 | itemJson['email'] = '' 97 | itemJson['password'] = '' 98 | itemJson['token'] = false 99 | itemJson['avatar'] = '' 100 | 101 | return itemJson 102 | } else { 103 | return itemJson 104 | } 105 | }) 106 | ) 107 | console.log(user) 108 | 109 | message.info('Sua conta foi desabilitada') 110 | 111 | /*Redirecionar para a Home*/ 112 | setGoHome(true) 113 | } 114 | return ( 115 | <> 116 |
119 | 120 | 121 | { 122 | user.map(itemJson => { 123 | 124 | /*Descobrindo quem é o usuário logado*/ 125 | if(itemJson.token) { 126 | 127 | return( 128 | <> 129 |

{itemJson.name}

130 |

{itemJson.email}

131 | 132 | ); 133 | } 134 | }) 135 | } 136 | 137 | 138 | 144 | 145 | 146 |

Sua assinatura

147 |
148 |
149 | { assinatura ? ( 150 | Minha assinatura Digital 156 | ) :

Sem assinatura

} 157 | 158 |
159 | { goToHome && } 160 | 161 | { 162 | toEditForm && 163 | 164 |
167 |

Edite os dados da sua conta:

168 |

Nome:

169 | setName(newValue.target.value) }/> 170 |
171 |

E-mail:

172 | setEmail(newValue.target.value) } /> 173 |
174 |

Senha:

175 | setPassword(newValue.target.value) }/> 176 |
177 | 178 |
179 | 180 |
181 | } 182 | 183 | ); 184 | } 185 | 186 | export default ProfileCard; -------------------------------------------------------------------------------- /certificate/src/components/profile-card/style.css: -------------------------------------------------------------------------------- 1 | /*Perfil do usuário*/ 2 | .profile { 3 | margin-top: 3%; 4 | margin-left: 10%; 5 | 6 | } 7 | 8 | /*Formulário de Edição*/ 9 | .edit-profile { 10 | display: flex; 11 | margin: 5% auto; 12 | width: 50%; 13 | } 14 | 15 | /*Inputs do formulário de edição do perfil*/ 16 | .input-edit-1, .input-edit-2 { 17 | margin-bottom: 3%; 18 | } 19 | 20 | .button-edit-profile { 21 | margin-top: 3%; 22 | width: 100%; 23 | border-color: orange; 24 | background-color: orange; 25 | color: white; 26 | } 27 | 28 | .button-edit-profile:hover { 29 | border-color: orange; 30 | background-color: white; 31 | color: orange; 32 | transition: 0.5; 33 | } 34 | 35 | /*Botão para voltar ao perfil dentro do formulario para editar perfil*/ 36 | .back-button-profile { 37 | margin-top: 3%; 38 | width: 100%; 39 | } 40 | 41 | .profile-title { 42 | text-align: center; 43 | } 44 | 45 | @media screen and (max-width: 800px) { 46 | .edit-profile { 47 | width: 80%; 48 | } 49 | 50 | .button-back-of-profile { 51 | margin-right: auto; 52 | margin-left: auto; 53 | } 54 | } 55 | 56 | @media screen and (min-width: 600px) and (max-width: 1000px){ 57 | .edit-profile { 58 | width: 70%; 59 | } 60 | } -------------------------------------------------------------------------------- /certificate/src/components/section/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import "./style.css"; 4 | 5 | function Section(props) { 6 | 7 | return ( 8 |
9 |

10 | 11 | Suas alunas e participantes 12 | precisam de um 13 |   14 | 15 | 16 | certificado 17 | ? 18 |

19 |

20 | Siga nosso 21 |   22 | 23 | passo a passo 24 | , 25 | é 26 |   27 | 28 | rápido 29 | 30 |   31 | é 32 | prático! 33 | 34 |

35 | 36 | 39 | 40 |
41 | 42 | ); 43 | } 44 | 45 | export default Section; 46 | -------------------------------------------------------------------------------- /certificate/src/components/section/style.css: -------------------------------------------------------------------------------- 1 | .div-section { 2 | background-image: url('../../assets/wallpaper-section.jpg.png'); 3 | padding: 5%; 4 | text-align: center; 5 | } 6 | 7 | .h1-section { 8 | font-family: 'Releway', sans-serif; 9 | 10 | font-size: 40px; 11 | 12 | font-weight: bold; 13 | } 14 | 15 | .h2-section { 16 | font-family: 'Releway', sans-serif; 17 | 18 | font-size: 30px; 19 | 20 | } 21 | 22 | .span-1-home { 23 | color: #ffa900; 24 | font-weight: bold; 25 | } 26 | 27 | .span-2 { 28 | color: #006400; 29 | font-weight: bold; 30 | } 31 | 32 | .span-3 { 33 | border-color: #c6255a; 34 | border-top-style: solid; 35 | border-top-width: 7px; 36 | padding-top: 10px; 37 | } 38 | 39 | .span-4 { 40 | color: #c6255a; 41 | font-weight: bold; 42 | } 43 | 44 | .button-section { 45 | width: 20%; 46 | height: 50px; 47 | font-size: 20px; 48 | font-weight: bold; 49 | background-color: #c6255a; 50 | 51 | border-color: transparent; 52 | 53 | border-radius: 20px; 54 | color: #fff; 55 | } 56 | 57 | .button-section:hover { 58 | 59 | box-shadow: 4px 4px 8px gray; 60 | 61 | transition: 1s; 62 | } 63 | 64 | @media screen and (max-width: 800px) { 65 | .h2-section, 66 | .h1-section { 67 | font-size: 30px; 68 | } 69 | .span-3 { 70 | border-top-width: 5px; 71 | padding-top: 10px; 72 | } 73 | 74 | .button-section { 75 | display: flex; 76 | align-items: center; 77 | justify-content: center; 78 | margin-left: auto; 79 | margin-right: auto; 80 | width: 70%; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /certificate/src/components/steps/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import './style.css' 3 | 4 | function Steps(props) { 5 | 6 | return ( 7 |
8 |

9 | Veja como 10 | é simples e fácil de usar o nosso   11 | 12 | passo a passo 13 | 14 |

15 |

16 | 1 17 | Crie uma conta. 18 |

19 |

20 | 2 21 | Crie um evento. 22 |

23 |

24 | Insira todas as informações necessárias no formulário. Ele ficará salvo para nós. 25 |

26 |

27 | 3 28 | Cadastre os participantes do evento. 29 |

30 |

31 | 4 32 | 33 | Quer selecionar os participantes depois? É só usar o check-list! 34 | 35 |

36 |

37 | 5 38 | Está na hora de enviar os certificados? 39 |

40 |

41 | Basta clicar em 'Enviar Certificado' para cada um dos participantes. 42 |

43 |
44 | ); 45 | } 46 | 47 | export default Steps; -------------------------------------------------------------------------------- /certificate/src/components/steps/style.css: -------------------------------------------------------------------------------- 1 | .div-steps { 2 | margin-left: 3%; 3 | margin-top: 3%; 4 | font-family: 'Raleway', sans-serif; 5 | } 6 | 7 | .h2-steps { 8 | font-size: 30px; 9 | letter-spacing: 1px; 10 | 11 | } 12 | 13 | .h3-steps { 14 | color: #c6255a; 15 | font-weight: bold; 16 | font-size: 25px; 17 | letter-spacing: 2px; 18 | 19 | } 20 | 21 | .h4-steps { 22 | font-size: 20px; 23 | letter-spacing: 2px; 24 | } 25 | 26 | .span-1-steps { 27 | border-color: #c6255a; 28 | border-top-style: solid; 29 | border-top-width: 7px; 30 | padding-top: 10px; 31 | } 32 | 33 | .span-2-steps { 34 | color: #c6255a; 35 | } 36 | 37 | .span-3-steps { 38 | color: black; 39 | } 40 | 41 | @media screen and (max-width: 1280px) { 42 | .div-steps { 43 | margin-left: 6%; 44 | margin-right: 3%; 45 | margin-top: 6%; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /certificate/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /certificate/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | import * as serviceWorker from './serviceWorker'; 7 | 8 | ReactDOM.render(, document.getElementById('root')); 9 | 10 | // If you want your app to work offline and load faster, you can change 11 | // unregister() to register() below. Note this comes with some pitfalls. 12 | // Learn more about service workers: https://bit.ly/CRA-PWA 13 | serviceWorker.unregister(); 14 | -------------------------------------------------------------------------------- /certificate/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /certificate/src/pages/home/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | /*Componentes*/ 4 | import Header from '../../components/header/index' 5 | import Section from '../../components/section/index' 6 | import Cards from '../../components/cards/index' 7 | import ModelCertificateHome from '../../components/model-certificate-home/index' 8 | import Steps from '../../components/steps/index' 9 | import Footer from '../../components/footer/index' 10 | 11 | function Home(props) { 12 | 13 | return ( 14 | <> 15 | 16 |
17 |
18 | 19 | 20 | 21 |
22 | 23 | ); 24 | } 25 | 26 | export default Home; -------------------------------------------------------------------------------- /certificate/src/pages/list-of-events/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | /*Componentes*/ 4 | import MenuComponent from '../../components/menu-1/index' 5 | import ListEvents from '../../components/list-events/index'; 6 | import Footer from '../../components/footer/index'; 7 | 8 | function ListOfEvents(props) { 9 | 10 | const { organizador } = props 11 | 12 | return ( 13 | <> 14 | 15 | 16 |
17 | 18 | ); 19 | } 20 | 21 | export default ListOfEvents; -------------------------------------------------------------------------------- /certificate/src/pages/page-confirmation/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | /*Componentes*/ 4 | import MenuComponent from '../../components/menu-1/index' 5 | import MessageAlert from '../../components/message-alert/index'; 6 | import Footer from '../../components/footer/index'; 7 | 8 | function PageConfirmation(props) { 9 | 10 | return ( 11 | <> 12 | 13 | 14 |
15 | 16 | ); 17 | } 18 | 19 | export default PageConfirmation; -------------------------------------------------------------------------------- /certificate/src/pages/page-not-found/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { Link } from 'react-router-dom' 3 | import Error404 from '../../assets/img/erro404.gif' 4 | import './style.css' 5 | 6 | import MenuComponent from '../../components/menu-1/index' 7 | import Footer from '../../components/footer/index' 8 | 9 | 10 | function PageNotFound() { 11 | return ( 12 |
13 | 14 | imagem de página não encontrada 15 |
16 | Voltar para a Home 17 |
18 |
19 |
20 | ); 21 | } 22 | 23 | export default PageNotFound; -------------------------------------------------------------------------------- /certificate/src/pages/page-not-found/style.css: -------------------------------------------------------------------------------- 1 | img.gif-erro { 2 | width: 420px; 3 | height: 400px; 4 | display: block; 5 | margin: 20px auto; 6 | position: relative; 7 | } 8 | -------------------------------------------------------------------------------- /certificate/src/pages/profile/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | /*Componentes*/ 4 | import MenuComponent from '../../components/menu-1/index' 5 | import ProfileCard from '../../components/profile-card/index' 6 | import Footer from '../../components/footer/index' 7 | 8 | function Profile(props) { 9 | 10 | return ( 11 | <> 12 | 13 | 14 |
15 | 16 | ); 17 | } 18 | 19 | export default Profile; -------------------------------------------------------------------------------- /certificate/src/pages/sign-in/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | /*Componentes*/ 4 | import MenuComponent from '../../components/menu-1/index' 5 | import FormLogin from '../../components/form-login/index'; 6 | import Footer from '../../components/footer/index'; 7 | 8 | /*Estilos*/ 9 | import '../../style/App.css'; 10 | 11 | function SignIn(props) { 12 | return ( 13 | <> 14 | 15 | 16 |
17 | 18 | ); 19 | } 20 | 21 | export default SignIn; -------------------------------------------------------------------------------- /certificate/src/pages/sign-up/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | /*Componentes*/ 4 | import MenuComponent from '../../components/menu-1/index' 5 | import FormRegister from '../../components/form-register/index'; 6 | import Footer from '../../components/footer/index'; 7 | 8 | /*Estilos*/ 9 | import './styles.css'; 10 | import '../../style/App.css'; 11 | 12 | 13 | function SignUp(props) { 14 | 15 | return ( 16 | <> 17 | 18 | 19 |
20 | 21 | ); 22 | } 23 | 24 | export default SignUp; -------------------------------------------------------------------------------- /certificate/src/pages/sign-up/styles.css: -------------------------------------------------------------------------------- 1 | .loginBtn { 2 | box-sizing: border-box; 3 | position: relative; 4 | left: 40%; 5 | margin: 0.2em; 6 | padding: 0 15px 0 46px; 7 | border: none; 8 | text-align: left; 9 | line-height: 34px; 10 | white-space: nowrap; 11 | border-radius: 0.2em; 12 | font-size: 16px; 13 | color: #FFF; 14 | 15 | } 16 | 17 | .loginBtn:before { 18 | content: ""; 19 | box-sizing: border-box; 20 | position: absolute; 21 | top: 0; 22 | left: 0; 23 | width: 34px; 24 | height: 100%; 25 | } 26 | 27 | .loginBtn-google { 28 | background: #DD4B39; 29 | } 30 | .loginBtn-google:before { 31 | border-right: #BB3F30 1px solid; 32 | background: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/14082/icon_google.png') 6px 6px no-repeat; 33 | } 34 | 35 | .ou{ 36 | font-weight: bold; 37 | display: flex; 38 | justify-content: center; 39 | margin-top: 20px; 40 | margin-bottom: 20px; 41 | } 42 | 43 | @media screen and (max-width: 600px){ 44 | .loginBtn{ 45 | left: 30%; 46 | } 47 | } 48 | 49 | @media screen and (min-width: 600px) and (max-width: 1000px){ 50 | .loginBtn{ 51 | left: 35%; 52 | } 53 | } -------------------------------------------------------------------------------- /certificate/src/routes.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { BrowserRouter, Route, Switch } from "react-router-dom"; 3 | 4 | /*Importando todas as paginas*/ 5 | import Home from "./pages/home/index"; 6 | import ListOfEvents from "./pages/list-of-events/index"; 7 | import PageConfirmation from "./pages/page-confirmation/index"; 8 | import PageNotFound from "./pages/page-not-found/index"; 9 | import SignIn from "./pages/sign-in/index"; 10 | import SignUp from "./pages/sign-up/index"; 11 | 12 | /*Em path foi definida a rota de acesso que colocaremos 13 | na URL para acessar a page em component*/ 14 | 15 | const Routes = () => ( 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | ); 28 | 29 | export default Routes; 30 | -------------------------------------------------------------------------------- /certificate/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' } 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /certificate/src/services/events.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "user": "Lais Lima", 4 | "company": "WomakersCode", 5 | "course": "Bootcamp React", 6 | "startDate": "01/02/2020", 7 | "finishDate": "28/03/2020", 8 | "workload": "56", 9 | "logo": "https://miro.medium.com/max/478/1*jriufqYKgJTW4DKrBizU5w.png", 10 | "digitalSignature": "" 11 | }, 12 | { 13 | "user": "Lais Lima", 14 | "company": "WomakersCode", 15 | "course": "Workshop Reconhecimento Facial com Face API & Node.js", 16 | "startDate": "20/06/2020", 17 | "finishDate": "20/06/2020", 18 | "workload": "56", 19 | "logo": "https://miro.medium.com/max/478/1*jriufqYKgJTW4DKrBizU5w.png", 20 | "digitalSignature": "" 21 | }, 22 | { 23 | "user": "Lais Lima", 24 | "company": "WomakersCode", 25 | "course": "Bootcamp PHP", 26 | "startDate": "01/02/2023", 27 | "finishDate": "28/03/2023", 28 | "workload": "56", 29 | "logo": "https://miro.medium.com/max/478/1*jriufqYKgJTW4DKrBizU5w.png", 30 | "digitalSignature": "" 31 | }, 32 | { 33 | "user": "Lais Lima", 34 | "company": "WomakersCode", 35 | "course": "Bootcamp Ruby On Rails", 36 | "startDate": "01/02/2024", 37 | "finishDate": "28/03/2024", 38 | "workload": "56", 39 | "logo": "https://miro.medium.com/max/478/1*jriufqYKgJTW4DKrBizU5w.png", 40 | "digitalSignature": "" 41 | }, 42 | { 43 | "user": "Marília Suzart", 44 | "company": "Liv Up", 45 | "course": "React Native", 46 | "startDate": "03/03/2020", 47 | "finishDate": "03/04/2020", 48 | "workload": "30", 49 | "logo": "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTk4anvjc5Nyx05EpG5SVa-h_cYcp2CgOS3nAaaQoiPi_GgJylp&usqp=CAU", 50 | "digitalSignature": "" 51 | }, 52 | { 53 | "user": "Rebecca Arantes", 54 | "company": "Liv Up", 55 | "course": "Angular", 56 | "startDate": "03/03/2020", 57 | "finishDate": "03/04/2020", 58 | "workload": "30", 59 | "digitalSignature": "", 60 | "logo": "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTk4anvjc5Nyx05EpG5SVa-h_cYcp2CgOS3nAaaQoiPi_GgJylp&usqp=CAU" 61 | }, 62 | { 63 | "user": "Rebecca Arantes", 64 | "company": "Liv Up", 65 | "course": "Bootstrap", 66 | "startDate": "03/03/2020", 67 | "finishDate": "03/04/2020", 68 | "workload": "30", 69 | "digitalSignature": "", 70 | "logo": "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTk4anvjc5Nyx05EpG5SVa-h_cYcp2CgOS3nAaaQoiPi_GgJylp&usqp=CAU" 71 | }, 72 | { 73 | "user": "Brennda Farinha", 74 | "company": "Reprograma", 75 | "course": "Metodologias Ageis", 76 | "startDate": "03/03/2020", 77 | "finishDate": "03/04/2020", 78 | "workload": "70", 79 | "digitalSignature": "", 80 | "logo": "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcQx_9qBzg7v5vapa-NG-t0e9HSYRi3lJjwKomUgFEfIfYMa5U1J&usqp=CAU" 81 | }, 82 | { 83 | "user": "Adriele Rodrigues", 84 | "company": "Accenture Brasil", 85 | "course": "Python Avançado", 86 | "startDate": "03/03/2020", 87 | "finishDate": "03/04/2020", 88 | "workload": "120", 89 | "logo": "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcSJVBXCc4s68lb4RLyO3xncK1D6HQH7EuyENcf_Wb1eR9XlsYU6&usqp=CAU", 90 | "digitalSignature": "" 91 | } 92 | ] 93 | -------------------------------------------------------------------------------- /certificate/src/services/participantes.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Diana Regina", 4 | "email": "dianaregina22@outlook.com.br", 5 | "present": true, 6 | "receiveCertificate": false, 7 | "course": "Bootcamp React" 8 | }, 9 | { 10 | "name": "Chaiana Hermes", 11 | "email": "chaiana_hermes@yahoo.com.br", 12 | "present": true, 13 | "receiveCertificate": false, 14 | "course": "Bootcamp React" 15 | }, 16 | { 17 | "name": "Rose Ahakawa", 18 | "email": "rose.oyakawa@gmail.com", 19 | "present": true, 20 | "receiveCertificate": false, 21 | "course": "Bootcamp React" 22 | }, 23 | { 24 | "name": "Grasiele Kroger", 25 | "email": "gelbundschwarz@gmail.com", 26 | "present": true, 27 | "receiveCertificate": false, 28 | "course": "Bootcamp React" 29 | }, 30 | { 31 | "name": "Claudia Caroline Arruda Policarpo", 32 | "email": "claudia.policarpo89@gmail.com", 33 | "present": true, 34 | "receiveCertificate": false, 35 | "course": "React Navite" 36 | }, 37 | { 38 | "name": "Diana Coelho", 39 | "email": "coelhodiana04@gmail.com", 40 | "present": true, 41 | "receiveCertificate": false, 42 | "course": "Bootcamp React" 43 | } 44 | , 45 | { 46 | "name": "Larissa Oliveira", 47 | "email": "larioli.me@gmail.com", 48 | "present": true, 49 | "receiveCertificate": false, 50 | "course": "Bootcamp React" 51 | } 52 | , 53 | { 54 | "name": "Ariane Sousa", 55 | "email": "ariane.sousa011@gmail.com", 56 | "present": true, 57 | "receiveCertificate": false, 58 | "course": "Bootcamp React" 59 | } 60 | , 61 | { 62 | "name": "Anna Carolina Inhasz Aureliano", 63 | "email": "anna.inhasz@gmail.com", 64 | "present": true, 65 | "receiveCertificate": true, 66 | "course": "Bootcamp React" 67 | } 68 | , 69 | { 70 | "name": "Alessandra Nastassja", 71 | "email": "alessandra.nastassja@hotmail.com", 72 | "present": true, 73 | "receiveCertificate": true, 74 | "course": "Bootcamp React" 75 | } 76 | , 77 | { 78 | "name": "Isabella Soares de Lima", 79 | "email": "isabella.soares.28@gmail.com", 80 | "present": true, 81 | "receiveCertificate": false, 82 | "course": "Bootcamp React" 83 | }, 84 | { 85 | "name": "Mariana Tancredi", 86 | "email": "matancredi@hotmail.com", 87 | "present": true, 88 | "receiveCertificate": false, 89 | "course": "Bootcamp React" 90 | }, 91 | { 92 | "name": "Ana Paula Mak", 93 | "email": "anapaulamak@gmail.com", 94 | "present": true, 95 | "receiveCertificate": false, 96 | "course": "Bootcamp React" 97 | } 98 | , 99 | { 100 | "name": "Mariana Tancredi", 101 | "email": "alicia@outlook.com.br", 102 | "present": true, 103 | "receiveCertificate": false, 104 | "course": "Bootcamp React" 105 | }, 106 | { 107 | "name": "Leticia Campos", 108 | "email": "leehcamposs@gmail.com", 109 | "present": true, 110 | "receiveCertificate": false, 111 | "course": "Bootcamp React" 112 | }, 113 | { 114 | "name": "Fernanda R. A.", 115 | "email": "fernandaramos.a@outlook.com", 116 | "present": true, 117 | "receiveCertificate": false, 118 | "course": "Bootcamp React" 119 | }, 120 | { 121 | "name": "Angela Mutsumi", 122 | "email": "angelamutsumi@gmail.com", 123 | "present": true, 124 | "receiveCertificate": false, 125 | "course": "Bootcamp React" 126 | }, 127 | { 128 | "name": "Olívia Resende", 129 | "email": "olivinharesende@hotmail.com", 130 | "present": true, 131 | "receiveCertificate": false, 132 | "course": "Bootcamp React" 133 | }, 134 | { 135 | "name": "Dayana Maia", 136 | "email": "dayrmaia@gmail.com", 137 | "present": true, 138 | "receiveCertificate": false, 139 | "course": "Bootcamp React" 140 | } 141 | ] 142 | 143 | -------------------------------------------------------------------------------- /certificate/src/services/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "Marília Suzart", 4 | "email": "gabrielesuzart@gmail.com", 5 | "password": "marilha123", 6 | "token": false, 7 | "avatar": "https://avatars1.githubusercontent.com/u/30198542?s=400&u=6a8ee8b35180f91d7effe7acc030375f1719edc2&v=4" 8 | }, 9 | { 10 | "name": "Rebecca Arantes", 11 | "email": "arantes.rbc@gmail.com", 12 | "password": "rebeca123", 13 | "token": false, 14 | "avatar": "https://avatars2.githubusercontent.com/u/32600739?s=400&u=450cac5a54e04cd69ee94815b7cda1cf8fec4d2a&v=4" 15 | }, 16 | { 17 | "name": "Lais Lima", 18 | "email": "certificadowomakerscode@gmail.com", 19 | "password": "certificado123", 20 | "token": false, 21 | "avatar": "https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcS9-U_HbQAipum9lWln3APcBIwng7T46hdBA42EJv8Hf6Z4fDT3&usqp=CAU" 22 | }, 23 | { 24 | "name": "Brennda Farinha", 25 | "email": "brennda.perola@gmail.com", 26 | "password": "brenda123", 27 | "token": false, 28 | "avatar": "https://avatars0.githubusercontent.com/u/39424818?s=400&u=a578989c87d40226998f9dcbfc4a9542f0f39f2b&v=4" 29 | }, 30 | { 31 | "name": "Adriele Rodrigues", 32 | "email": "adrielerodr@gmail.com", 33 | "password": "brenda123", 34 | "token": false, 35 | "avatar": "https://media-exp1.licdn.com/dms/image/C4E03AQG4L48pX1sj6Q/profile-displayphoto-shrink_800_800/0?e=1591833600&v=beta&t=O86DZY-f4_R0m71wNlx3oYbeecJe-C-Nvt1UiVVzm0w" 36 | } 37 | 38 | ] -------------------------------------------------------------------------------- /certificate/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | 7 | import { configure } from 'enzyme'; 8 | import Adapter from 'enzyme-adapter-react-16'; 9 | configure({ adapter: new Adapter() }); -------------------------------------------------------------------------------- /certificate/src/style/App.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Raleway:200,400,800&display=swap'); 2 | 3 | body { 4 | font-family: 'Raleway', sans-serif; 5 | } 6 | -------------------------------------------------------------------------------- /layout.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/React-Bootcamp-WoMarkersCode/certificate-generator/6d8d576a1afabe735c9104400f866b19b9cdc9ed/layout.pptx --------------------------------------------------------------------------------