From 74413e833780fff475abc14cb6fee7c507375a87 Mon Sep 17 00:00:00 2001 From: Unknown Date: Wed, 20 Jan 2021 23:42:31 -0300 Subject: [PATCH] # Desafio finalizado --- README.md | 29 ++ lugares/.gitignore | 38 +++ lugares/db.json | 74 +++++ lugares/package.json | 59 ++++ lugares/public/favicon.ico | Bin 0 -> 3870 bytes lugares/public/index.html | 43 +++ lugares/public/logo32.png | Bin 0 -> 2399 bytes lugares/public/logo512.png | Bin 0 -> 9664 bytes lugares/public/manifest.json | 25 ++ lugares/public/robots.txt | 3 + lugares/public/static/.gitkeep | 0 lugares/public/static/lugares-logo.png | Bin 0 -> 4053 bytes lugares/public/static/lugares.png | Bin 0 -> 25017 bytes lugares/src/App.tsx | 17 ++ lugares/src/components/CardList.tsx | 178 ++++++++++++ lugares/src/components/FormAdd.tsx | 225 +++++++++++++++ lugares/src/components/FormEdit.tsx | 196 +++++++++++++ lugares/src/components/Topbar.tsx | 33 +++ lugares/src/configs/axios.tsx | 16 ++ lugares/src/configs/theme.jsx | 25 ++ lugares/src/helpers/capitalize.tsx | 7 + lugares/src/helpers/index.tsx | 5 + lugares/src/index.tsx | 16 ++ lugares/src/pages/Home.tsx | 379 +++++++++++++++++++++++++ lugares/src/react-app-env.d.ts | 1 + lugares/src/routes/index.tsx | 12 + lugares/src/services/api.tsx | 50 ++++ lugares/tsconfig.json | 27 ++ 28 files changed, 1458 insertions(+) create mode 100644 lugares/.gitignore create mode 100644 lugares/db.json create mode 100644 lugares/package.json create mode 100644 lugares/public/favicon.ico create mode 100644 lugares/public/index.html create mode 100644 lugares/public/logo32.png create mode 100644 lugares/public/logo512.png create mode 100644 lugares/public/manifest.json create mode 100644 lugares/public/robots.txt create mode 100644 lugares/public/static/.gitkeep create mode 100644 lugares/public/static/lugares-logo.png create mode 100644 lugares/public/static/lugares.png create mode 100644 lugares/src/App.tsx create mode 100644 lugares/src/components/CardList.tsx create mode 100644 lugares/src/components/FormAdd.tsx create mode 100644 lugares/src/components/FormEdit.tsx create mode 100644 lugares/src/components/Topbar.tsx create mode 100644 lugares/src/configs/axios.tsx create mode 100644 lugares/src/configs/theme.jsx create mode 100644 lugares/src/helpers/capitalize.tsx create mode 100644 lugares/src/helpers/index.tsx create mode 100644 lugares/src/index.tsx create mode 100644 lugares/src/pages/Home.tsx create mode 100644 lugares/src/react-app-env.d.ts create mode 100644 lugares/src/routes/index.tsx create mode 100644 lugares/src/services/api.tsx create mode 100644 lugares/tsconfig.json diff --git a/README.md b/README.md index 4b396901f..4930e2d52 100644 --- a/README.md +++ b/README.md @@ -55,3 +55,32 @@ Quando o usuário clicar em "Adicionar", o formulário deverá ser resetado e o - O canditado deverá realizar um fork deste repositório e submeter o código no mesmo; - O prazo de entrega para este desafio é de 2 (duas) semanas, contando a partir do dia em que o candidato recebeu o email com o link do repositório; - Ao finalizar o desafio, o candidato deverá enviar um email para jobs@clubpetro.com.br contendo o link do seu PR. + +### Baixe e execute o projeto localmente + +**1 -** Clone o projeto e instale as dependências: +``` +$ git clone https://github.com/wagnerGCastro/desafio-react-clubpetro-frontend +$ cd desafio-react-clubpetro-frontend +$ cd lugares +$ yarn +``` + +**2 -** Subir servidor JSON Server +``` +- Abra o terminal, dentro da pasta lugares execute: +$ yarn json-server + ou +$ yarn json-server --watch db.json -p 3065 +``` + +**3 -** Rodar a aplicação no browser +``` +- Abra outro terminal, dentro da pasta lugares execute: +$ yarn start +``` +Abra o navegador e acesse [https://localhost:3033](https://localhost:3033) para visualizar o projeto. + +**4 -** Preview do projeto finalizado e hospedado :) + +Acesse [http://desafio-clubpetro-frontend.wagnercastro.tk/](http://desafio-clubpetro-frontend.wagnercastro.tk/) \ No newline at end of file diff --git a/lugares/.gitignore b/lugares/.gitignore new file mode 100644 index 000000000..4f95daf1f --- /dev/null +++ b/lugares/.gitignore @@ -0,0 +1,38 @@ + +# Add any directories, files, or patterns you don't want to be tracked by version control +#ignorar arquivos do vscode +.vscode/* +!.vscode/.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +\.idea/* + +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* +package-lock.json + +\.eslintcache diff --git a/lugares/db.json b/lugares/db.json new file mode 100644 index 000000000..1d3fdb754 --- /dev/null +++ b/lugares/db.json @@ -0,0 +1,74 @@ +{ + "lugares": [ + { + "country": "Estados Unidos", + "flag": "https://restcountries.eu/data/usa.svg", + "local": "Disney World", + "meta": "12/2022", + "id": 56 + }, + { + "id": 57, + "country": "Itália", + "flag": "https://restcountries.eu/data/ita.svg", + "local": "Veneza", + "meta": "12/2022" + }, + { + "id": 58, + "country": "México", + "flag": "https://restcountries.eu/data/mex.svg", + "local": "Cancú", + "meta": "05/2022" + }, + { + "country": "França", + "flag": "https://restcountries.eu/data/fra.svg", + "local": "Paris", + "meta": "04/2023", + "id": 59 + }, + { + "country": "Emirados árabes Unidos", + "flag": "https://restcountries.eu/data/are.svg", + "local": "Dubai", + "meta": "01/2024", + "id": 60 + }, + { + "country": "Estados Unidos", + "flag": "https://restcountries.eu/data/usa.svg", + "local": "Filadélfia", + "meta": "12/2022", + "id": 61 + }, + { + "country": "Estados Unidos", + "flag": "https://restcountries.eu/data/usa.svg", + "local": "Nova York", + "meta": "12/2022", + "id": 62 + }, + { + "country": "Brasil", + "flag": "https://restcountries.eu/data/bra.svg", + "local": "Fortaleza", + "meta": "05/2022", + "id": 63 + }, + { + "country": "Bolívia", + "flag": "https://restcountries.eu/data/bol.svg", + "local": "Salar de Uyuni", + "meta": "04/2023", + "id": 64 + }, + { + "country": "Brasil", + "flag": "https://restcountries.eu/data/bra.svg", + "local": "Balneário Camboriu", + "meta": "04/2022", + "id": 65 + } + ] +} \ No newline at end of file diff --git a/lugares/package.json b/lugares/package.json new file mode 100644 index 000000000..39a7b520c --- /dev/null +++ b/lugares/package.json @@ -0,0 +1,59 @@ +{ + "name": "desafio-react-clubpetro-frontend", + "version": "0.1.0", + "private": true, + "dependencies": { + "@material-ui/core": "^4.11.2", + "@material-ui/icons": "^4.11.2", + "@material-ui/lab": "^4.0.0-alpha.57", + "@testing-library/jest-dom": "^5.11.4", + "@testing-library/react": "^11.1.0", + "@testing-library/user-event": "^12.1.10", + "@types/jest": "^26.0.15", + "@types/node": "^12.0.0", + "@types/react": "^16.9.53", + "@types/react-dom": "^16.9.8", + "axios": "^0.21.1", + "clsx": "^1.1.1", + "fontsource-roboto": "^4.0.0", + "json-server": "^0.16.3", + "node-sass": "^4.14.1", + "react": "^17.0.1", + "react-dom": "^17.0.1", + "react-input-mask": "^2.0.4", + "react-paginate": "^7.0.0", + "react-router-dom": "^5.2.0", + "react-scripts": "4.0.1", + "typescript": "^4.0.3", + "web-vitals": "^0.2.4" + }, + "scripts": { + "start": "PORT=3033 react-scripts start", + "build": "react-scripts build", + "json-server": "npx json-server --watch db.json --port=3065", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": [ + "react-app", + "react-app/jest" + ] + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + }, + "devDependencies": { + "@types/react-input-mask": "^3.0.0", + "@types/react-router-dom": "^5.1.7" + } +} diff --git a/lugares/public/favicon.ico b/lugares/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..a11777cc471a4344702741ab1c8a588998b1311a GIT binary patch literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ literal 0 HcmV?d00001 diff --git a/lugares/public/index.html b/lugares/public/index.html new file mode 100644 index 000000000..7715b54a9 --- /dev/null +++ b/lugares/public/index.html @@ -0,0 +1,43 @@ + + + + + + + + + + + + + ClubPetro Challenge + + + +
+ + + diff --git a/lugares/public/logo32.png b/lugares/public/logo32.png new file mode 100644 index 0000000000000000000000000000000000000000..30fe87520aedf71a53506910ff5405d17246b998 GIT binary patch literal 2399 zcmaJ@c~ld39*zZ3rN9S?drr zVuj~5okt3BxGCvQtpPJAHy{{bL+YGv9^w0e4+(%1 z<`MKP1y$h@BK1ybs~6F%AlwKgs2w*SYRH-PGiymHV35TQ8{!b8K6^XY>3K+XbcLK#--+Q864o% zMF>Xo!Va!lRQf7baK$6kW0;2vK`kvUU<(68y>$?c!{Iaf(VLlo*T0UC~jZI zgn|h1*}YB==0x4VxT4jD`Y|3M==9eVT%OmmZr`gi1q%iRtR9F4QpZ!804fy!AL??w zM*A=|@|)lPDeTkE^B|BK@u7aNJ$P`AjPXz&uF#8EG1RL?(Z-1?R@9>y>Z?aRfKUiz z>z!^GZSj#_!W9ax%U6l~!Xbi{osoaMN=NlIH}ftNbjvT<&nxv1(*_I*z7JoFu7CP|OVp4N0zSOD0An zDG`Dmrio^0Jk%V$MlqKhBWsEjHwcA7fstNVSePTsZEI_bPl?PR61f&}Zcc7NRo1l9 zW`U!qz@cjDtRk5#bX6KlO`A=R52Z+=q~1(j^;`Iq^?R3w$4ukd`K2&DHY2sWdu?iJ zYP!0HU6qLAIZ6!K>-Tnqm$epE&cx&K5;#*-$16t|8`f_iXlt}SX7cRmphlqfFouVR ztC~nDyh0X>wPZ<0gv3|wpwLZnZ4;#T=Bk_WVx(wXnM=_?2UT2-GLvM`9Uk1CD0dXk z0VAb8hDELOg0;1^jjjfJTdBcEHu|&DDR`}y98>0rlwu_gKEte_)u^Z@1(lzw$H2I9 zREg$EtmG7xy}W@Ps|rjnZ_s!d+GY;7n7R7T^J$ia=B0a>bF$@i(nF`V3Dp#-C2Q4t zi%Y#rJ63kaDSXq?$?+6$^X`=~GPJ4*eE(1{SjH@^&CRXWP>kAS6_Twt(5uBYfnv{m ztGt0#4D(49QjvKUtr*XQJK5@Vw;y3vkj>39o<3KFmDDcol#~hRMk&oG=hkE}Oy%Ob z!egK8?LR%B)F@eIKV+$vn2GbdoBGe}8@cu|P{ht+&1mRQ7Fp6uENR3lQwh3O-MX^W zDY-RzR#{(OU=>!nNUnCI&?cf8D+*vqY}E8nB3o0bO_x^|n%IqPdbUMIr9x-VorMfc zY^gm-Rw8rjiflzyK3amx6Eh=fXym9Kqe3Rt>~dU{7n~dsd*Ena&#uljdrxlKxA^^| zN8|EJ(<+^ze0ZubAg_m%joGS3>byUqyN_%I#JotEx2@a$-hp?w^=%dyNl{#l$P6m2 zJkY4gH5rF2MaKS59yutof6>(i_w($jsJo{-G1b2J^3Gxr}{5e@aeNQ~Cn0`;Zv ztYtCsA;;3smd{M+VMY#-I~I+-@XJaE7HT^i4*#?`C#H4y!r;iIkwN!^&_7)s!Pl6R zO)>Sid!uRXd}4doe+EK*XUvsX76E{3aM(QO$rJXh&o@WRG{?t9{3ZEXb-%eie#YPO zCC10x`Sb@ng!l#ipPy!|c|hLtRmi%r#MNh0E)w#u_=av@tOzm1E$UyNwY%;`M~>mb z>UF0^9~$84Q$_DUnnyBr!cbt>f^~zf-;mU5)yVzb{P^#(x|2hfuL~2%10+M;v2Oatq-s{HpJ|D0gUCyeINZYe(Z z*cM~?pRH{l{^yxM&DeG7x1a3Sb&c)W*^~4K_`*lqtD~O(yX|0kP4ce0Up^e|JNEqM z&3VZ6xq9)Z*A7RFecgi;*{rHlL#s3DaoQga-n(?__MD4o>wWHp%xCip=+DvUBhkZ= z>wd`?y0g!gooWFnrjJj2&--xG)xQ$MyI>3a_UIQyOvT;HTZ`j5M@Oi z%lM)8+$y6vtUFD9*ARYl?D?eJ6V|7ee?{e8y8L4?S?9-lwMVs~A7rnw=~|YrC>|;r zXubiq>Mqv$yNzF6g*rE;Y|89uJaPQX^qiCG%U|r*9#o@xJxC*#y UJJPehYy6i-CRU0L2rTXY1$b9rHvj+t literal 0 HcmV?d00001 diff --git a/lugares/public/logo512.png b/lugares/public/logo512.png new file mode 100644 index 0000000000000000000000000000000000000000..a4e47a6545bc15971f8f63fba70e4013df88a664 GIT binary patch literal 9664 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 b{|{}U^kRn2wo}j7|0ATu<;8xA7zX}7|B6mN literal 0 HcmV?d00001 diff --git a/lugares/public/manifest.json b/lugares/public/manifest.json new file mode 100644 index 000000000..080d6c77a --- /dev/null +++ b/lugares/public/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "icons": [ + { + "src": "favicon.ico", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo192.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo512.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/lugares/public/robots.txt b/lugares/public/robots.txt new file mode 100644 index 000000000..e9e57dc4d --- /dev/null +++ b/lugares/public/robots.txt @@ -0,0 +1,3 @@ +# https://www.robotstxt.org/robotstxt.html +User-agent: * +Disallow: diff --git a/lugares/public/static/.gitkeep b/lugares/public/static/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/lugares/public/static/lugares-logo.png b/lugares/public/static/lugares-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1a6652d3158c03cd7d4fc3186f330e3b193a0764 GIT binary patch literal 4053 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 Czxl!d literal 0 HcmV?d00001 diff --git a/lugares/public/static/lugares.png b/lugares/public/static/lugares.png new file mode 100644 index 0000000000000000000000000000000000000000..822d4812f15752395c632fac825e7ca387bcdf56 GIT binary patch literal 25017 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 literal 0 HcmV?d00001 diff --git a/lugares/src/App.tsx b/lugares/src/App.tsx new file mode 100644 index 000000000..82ec11438 --- /dev/null +++ b/lugares/src/App.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { BrowserRouter } from 'react-router-dom'; +import { ThemeProvider } from '@material-ui/core/styles'; +import theme from 'configs/theme'; +import Routes from './routes'; + +const App: React.FC = () => { + return ( + + + + + + ); +} + +export default App; diff --git a/lugares/src/components/CardList.tsx b/lugares/src/components/CardList.tsx new file mode 100644 index 000000000..b405539f6 --- /dev/null +++ b/lugares/src/components/CardList.tsx @@ -0,0 +1,178 @@ +import React from 'react'; +import clsx from 'clsx'; +import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'; +import { + Grid, Card, Box, ButtonGroup, Typography, IconButton, + DialogActions, DialogContent, Button, Dialog +} from '@material-ui/core'; +import EditIcon from '@material-ui/icons/Edit'; +import ClearIcon from '@material-ui/icons/Clear'; + +//---------------------- Interfaces ------------------------// +import { FormDataUpdInterface } from 'pages/Home' + +interface PropsInterface { + onClickEdit(event: React.MouseEvent, id: string | number): void; + formData: Array + onClickRemove(event: React.MouseEvent): void; + dialogConfirmDelete(event: React.MouseEvent, id: string | number): void; + onDialog: boolean; + closeDialog(): void; +} + +//------------------- Custom Material Ui -------------------// +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + overflow: 'hidden', + paddingTop: '50px', + paddingBottom: '30px', + flexGrow: 1, + }, + card: { + height: '245px', + width: '245px', + padding: '5px 10px 8px', + marginTop: '7px', + marginBottom: '7px', + borderRadius: '10px', + boxShadow: "0px 4px 2px 0px rgba(0,0,0,0.2), 0px 1px 1px 0px rgba(0,0,0,0.14), 0px 1px 3px 0px rgba(0,0,0,0.12)", + '&:hover': { + background: '#fefefe' + } + }, + cardHead: { + position: 'relative', + display: 'flex', + justifyContent: 'space-between', + }, + cardIcons: { + position: 'absolute', + right: '-5px', + top: 0 + }, + cardfigure: { + position: 'relative', + margin: '15px 0 10px', + padding: 0 + }, + cardSvg: { + width: '56px', + height: '34px' + }, + cardCountry: { + fontWeight: 700, + fontSize: '1rem', + color: '#4F9419', + textTransform: 'uppercase' + }, + carDesc: { + '& p': { + color: '#000', + fontSize: '1rem', + } + }, + cardLine: { + border: '1px solid #ABABAB' + }, + buttonGroup: { + marginTop: '10px', + padding: 0 + }, + iconButton: { + padding: 0, + minWidth: '30px' + }, + icon: { + color: '#868686', + }, + respContainer: { + [theme.breakpoints.up('lg')]: { + maxWidth: '1346px', + margin: 'auto' + }, + } + }), +); + +const CardList: React.FC = (props) => { + const classes = useStyles(); + + return ( + <> + + + + {props.formData.map((c, idx) => ( + + + + + +
+ lugares-logo +
+ {c.country} +
+
+ + + + props.onClickEdit(event, c.id)} data-id={c.id} className={classes.iconButton}> + + + + props.dialogConfirmDelete(event, c.id)} className={classes.iconButton}> + + + + +
+ +
+ + + + + + Local: {c.local} + + + + + + + Meta: {c.meta} + + + + +
+
+ ))} +
+
+
+ + + + Tem certeza que deseja deletar? + + + + + + + + + ); +} + +export default CardList; diff --git a/lugares/src/components/FormAdd.tsx b/lugares/src/components/FormAdd.tsx new file mode 100644 index 000000000..2bd00d554 --- /dev/null +++ b/lugares/src/components/FormAdd.tsx @@ -0,0 +1,225 @@ +import React from 'react'; +import InputMask from "react-input-mask"; +import clsx from 'clsx'; +import { makeStyles, Theme, withStyles, createStyles } from '@material-ui/core/styles'; +import { + Container, Grid, TextField, Box,Button, FormControl, + FormHelperText, NativeSelect, InputBase +} from '@material-ui/core'; + +//---------------------- Interfaces ------------------------// +import { CountryInterface } from 'pages/Home' +import { FormDataAddInterface } from 'pages/Home' + +interface PropsInterface { + onSubmitAdd(event: React.FormEvent): void; + onChangeFormAdd(event: React.ChangeEvent): void; + onChangeFormDataFlag(event: {target: HTMLInputElement} | React.ChangeEvent): void; + formDataAdd?: FormDataAddInterface; + countryes?: Array + onErrorCountry: boolean; + onErrorLocal: boolean; + onErrorMeta: boolean; +} + +//------------------- Custom Material Ui -------------------// +const BootstrapInput = withStyles((theme: Theme) => + createStyles({ + root: { + 'label + &': { + marginTop: theme.spacing(0), + }, + }, + input: { + borderRadius: 4, + position: 'relative', + backgroundColor: theme.palette.background.paper, + border: '1px solid #ced4da', + fontSize: 16, + color: '#868686', + padding: '12px 10px 13px', + transition: theme.transitions.create(['border-color', 'box-shadow']), + } + }), +)(InputBase); + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + sectionFormAdd: { + background: '#4F9419', + padding: '55px 0 60px', + }, + root: { + '& .MuiOutlinedInput-notchedOutline': { + display: 'none' + }, + '& .MuiFormHelperText-contained': { + marginLleft: '0px', + marginRight: '0px' + } + }, + withoutLabel: { + marginTop: theme.spacing(3), + }, + formControl: { + minWidth: 120, + }, + outlinedInput: { + padding: '0', + borderColor: 'none', + border: '0px', + borderRadius: '7px', + backgroundColor: '#fff', + color: '#868686', + '& :before, & :after, & :hover': { + border: 'none', + borderBottom: 'none !important', + }, + }, + selectEmpty: { + background: '#fff', + margin: theme.spacing(0), + padding:0, + borderColor: 'none', + border: '0px', + borderRadius: '7px', + color: '#868686', + }, + textField: { + width: '100%', + padding: 0, + color: '#fff', + }, + boxGroupInputs: { + display: "flex", + flexWrap: 'wrap' + }, + myButton: { + width: '100%', + marginTop: '19px', + padding: '11.5px', + textTransform: 'initial' + }, + error: { + border: '1px solid #fff817', + borderRadius: '4px' + }, + errorColor: { + color: '#fff817 !important' + }, + respBoxInputs: { + [theme.breakpoints.down('sm')]: { + width: '100%' + }, + }, + }), +); + +const FormAdd: React.FC = (props) => { + const classes = useStyles(); + const { + onSubmitAdd, onChangeFormAdd, onChangeFormDataFlag, formDataAdd, + countryes, onErrorCountry, onErrorLocal, onErrorMeta + } = props; + + return ( +
+ + +
+ + + + + + } + > + + {countryes?.map((c, idx) => ( + + ))} + + { + onErrorCountry ? + ( + *Campo obrigatório) + : null + } + + + + + + + + { + onErrorLocal ? + ( + *Campo obrigatório + ) + : null + } + + + + + + + + {() => } + + { + onErrorMeta ? + ( + *Campo obrigatório
*Data (01 á 12) e Ano (2021 á 2099) +
) + : null} +
+
+ + + + +
+
+
+
+
+ ); +} + +export default FormAdd; + diff --git a/lugares/src/components/FormEdit.tsx b/lugares/src/components/FormEdit.tsx new file mode 100644 index 000000000..c034eda1c --- /dev/null +++ b/lugares/src/components/FormEdit.tsx @@ -0,0 +1,196 @@ +import React from 'react'; +import InputMask from "react-input-mask"; +import { createStyles, makeStyles, Theme, withStyles } from '@material-ui/core/styles'; +import { + Button, Dialog, FormControl, NativeSelect, + InputBase, FormHelperText, OutlinedInput +} from '@material-ui/core'; + +import MuiDialogContent from '@material-ui/core/DialogContent'; +import MuiDialogActions from '@material-ui/core/DialogActions'; + +//---------------------- Interfaces ------------------------// +import { CountryInterface } from 'pages/Home' +import { FormDataUpdInterface } from 'pages/Home' + +interface PropsInterface { + onSubmitUpdate(event: React.MouseEvent): void; + editFormChange(event: React.ChangeEvent): void; + editFormChangeFlag(event: { target: HTMLInputElement } | React.ChangeEvent): void; + sEditForm?: FormDataUpdInterface; + countries?: Array + handleClickOpen(event: React.MouseEvent): void; + handleClose(event: React.MouseEvent): void; + open: boolean; + sEditErrorCountry: boolean; + sEditErrorLocal: boolean; + sEditErrorMeta: boolean; +} + +//------------------- Custom Material Ui -------------------// +const BootstrapInput = withStyles((theme: Theme) => + createStyles({ + root: { + 'label + &': { + marginTop: theme.spacing(0), + }, + }, + input: { + borderRadius: 4, + position: 'relative', + backgroundColor: theme.palette.background.paper, + border: '1px solid #ced4da', + fontSize: 16, + color: '#868686', + padding: '12px 10px 13px', + transition: theme.transitions.create(['border-color', 'box-shadow']), + } + }), +)(InputBase); + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + margin: '20px', + '& .MuiDialog-paper': { + margin: '0px' + } + }, + formControl: { + width: '100%', + marginTop: theme.spacing(2) + }, + myButton: { + marginTop: theme.spacing(2), + padding: '11.5px', + textTransform: 'initial' + }, + error: { + border: '1px solid #ff1744', + borderRadius: '4px' + } + }) +); + +const DialogContent = withStyles((theme: Theme) => ({ + root: { + padding: theme.spacing(2), + }, +}))(MuiDialogContent); + +const DialogActions = withStyles((theme: Theme) => ({ + root: { + margin: 0, + padding: theme.spacing(2), + }, +}))(MuiDialogActions); +//------------------------- End ----------------------------// + +const FormEdit: React.FC = (props) => { + const classes = useStyles(); + + const { + sEditForm, editFormChangeFlag, editFormChange, handleClose, open, + onSubmitUpdate, countries, sEditErrorCountry, sEditErrorLocal, sEditErrorMeta + } = props; + + return ( + + +
+ + + } + > + + {countries?.map((c, idx) => { + return( + + ) + })} + + {sEditErrorCountry ? (*Campo obrigatório) : null} + + + + + + { + sEditErrorLocal ? + ( + *Campo obrigatório + ) + : null} + + + + + + {() => } + + { + sEditErrorMeta ? + ( + *Campo obrigatório
*Data (01 á 12) e Ano (2021 á 2099) +
) + : null + } +
+
+
+ + + + + +
+ ); +} + +export default FormEdit; diff --git a/lugares/src/components/Topbar.tsx b/lugares/src/components/Topbar.tsx new file mode 100644 index 000000000..6efb95b68 --- /dev/null +++ b/lugares/src/components/Topbar.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { makeStyles, Theme, createStyles } from '@material-ui/core/styles'; +import { Container, AppBar, Toolbar } from '@material-ui/core'; + +//------------------- Custom Material Ui -------------------// +const useStyles = makeStyles((theme: Theme) => + createStyles({ + root: { + flexGrow: 1, + }, + toolbar: { + padding: 0, + }, + }), +); + +const Topbar: React.FC = () => { + const classes = useStyles(); + + return ( +
+ + + + logo + + + +
+ ); +} + +export default Topbar; diff --git a/lugares/src/configs/axios.tsx b/lugares/src/configs/axios.tsx new file mode 100644 index 000000000..a68983a96 --- /dev/null +++ b/lugares/src/configs/axios.tsx @@ -0,0 +1,16 @@ +import axios from "axios"; + +const axiosInstance = axios.create({ + baseURL: "http://localhost:3065", + responseType: "json", + // timeout: 20000 +}); + +const apiCountries = axios.create({ + baseURL: 'https://restcountries.eu/rest/v2', +}); + + +export { + axiosInstance, apiCountries +} diff --git a/lugares/src/configs/theme.jsx b/lugares/src/configs/theme.jsx new file mode 100644 index 000000000..ab6a79dd8 --- /dev/null +++ b/lugares/src/configs/theme.jsx @@ -0,0 +1,25 @@ +import { createMuiTheme } from '@material-ui/core/styles'; + +// A custom theme for this app +const theme = createMuiTheme({ + root: { + overflow: 'none' + }, + palette: { + primary: { + // main: '#556cd6', + main: '#006C18', + }, + secondary: { + main: '#19857b', + }, + error: { + main: '#f44336', + }, + background: { + default: '#fff', + }, + }, +}); + +export default theme; diff --git a/lugares/src/helpers/capitalize.tsx b/lugares/src/helpers/capitalize.tsx new file mode 100644 index 000000000..43fa11c4a --- /dev/null +++ b/lugares/src/helpers/capitalize.tsx @@ -0,0 +1,7 @@ + +export default function capitalize(str: string): void | string { + if (typeof str !== 'string') { + return ''; + } + return str.charAt(0).toUpperCase() + str.substr(1); +} diff --git a/lugares/src/helpers/index.tsx b/lugares/src/helpers/index.tsx new file mode 100644 index 000000000..c675ed9ff --- /dev/null +++ b/lugares/src/helpers/index.tsx @@ -0,0 +1,5 @@ +import capitalize from './capitalize' + +export { + capitalize +} \ No newline at end of file diff --git a/lugares/src/index.tsx b/lugares/src/index.tsx new file mode 100644 index 000000000..be9139874 --- /dev/null +++ b/lugares/src/index.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import CssBaseline from '@material-ui/core/CssBaseline'; + +// Fonts +import 'fontsource-roboto'; + +import App from './App'; + +ReactDOM.render( + + + + , + document.getElementById('root') +); diff --git a/lugares/src/pages/Home.tsx b/lugares/src/pages/Home.tsx new file mode 100644 index 000000000..2ad170248 --- /dev/null +++ b/lugares/src/pages/Home.tsx @@ -0,0 +1,379 @@ +import React, { useState, useEffect } from 'react'; +import { Snackbar } from '@material-ui/core'; +import MuiAlert, { AlertProps } from '@material-ui/lab/Alert'; +import * as service from 'services/api'; +import { capitalize } from 'helpers'; + +// Components +import AppTopbar from 'components/Topbar'; +import FormAdd from 'components/FormAdd'; +import CardList from 'components/CardList'; +import FormEdit from 'components/FormEdit'; + +//---------------------- Interfaces ------------------------// +export interface CountryInterface { + country: string; + flag: string; +} + +export interface FormDataUpdInterface extends FormDataAddInterface { + id: string ; +} + +export interface FormDataAddInterface { + country: string; + flag: string | undefined; + local: string; + meta: string; +} + +interface CountryesFormDataInterface { + countryes: Array +} + +interface SystemNotification { + status: boolean, + message: string, + type: string +} + +const Home: React.FC = () => { + //---------------------- States ------------------------// + var initialState = { + formAdd: { + country: '', + flag: '', + local: '', + meta: '', + }, + formEdit: { + id: '', + country: '', + flag: '', + local: '', + meta: '', + } + } + + // Countryes API + const [countryes, setCountries] = useState<[CountryInterface]>(); + + // Countryes Json Server + const [formData, setFormData] = useState({ countryes: [] }); + + // Add + const [formDataAdd, setFormDataAdd] = useState(initialState.formAdd); + const [onErrorCountry, setOnErrorCountry] = useState(false); + const [onErrorLocal, setOnErrorLocal] = useState(false); + const [onErrorMeta, setOnErrorMeta] = useState(false); + + // Edit + const [sEditForm, setEditForm] = useState(initialState.formEdit) + const [sEditErrorCountry, setEditErrorCountry] = useState(false) + const [sEditErrorLocal, setEditErrorLocal] = useState(false) + const [sEditErrorMeta, setEditErrorMeta] = useState(false) + const [sEditIdDelete, setEditsEditIdDelete] = useState({id_delete: ''}) + + // Notification + const [open, setOpen] = useState(false); + const [onDialog, setOnDialog] = useState(false); + const [openNotification, setOpenNotification] = useState(false); + const [msnNotification, setMsnNotification] = useState({status: false, message: '', type:''}); + + //---------------------- Methods ------------------------// + const handleClickOpen = () => setOpen(true); + const handleClose = () => setOpen(false); + const closeDialog = () => { + setOnDialog(false); + setEditsEditIdDelete({id_delete: ''}) + }; + + async function loadCountries() { + try { + const { data } = await service.getCountryAll(); + let dataFilter: any = []; + + // Order By Alphabet + data.forEach( (t: any) => dataFilter.push({ country: capitalize(t.translations.pt), flag: t.flag })); + dataFilter.sort((a: any, b: any)=> (a.country > b.country ? 1 : -1)); + setCountries(dataFilter) + + } catch(err) { + systemNotification({ + status: true, + message: 'Ops! Erro ao carregar lista de Países', + type: 'error' + }) + } + } + + async function loadLugares() { + try { + const { data } = await service.getLugaresAll(); + setFormData({countryes: data}) + + } catch(err) { + systemNotification({ + status: true, + message: 'Ops! Erro ao carregar lista de lugares', + type: 'error' + }) + } + } + + async function onSubmitAdd(event: React.FormEvent) { + event.preventDefault(); + let target = event.currentTarget; + let dataForm = { ...formDataAdd } + + // Validation + if(!validateFields(dataForm)) return; + + // Set Add + try { + let { data } = await service.create(dataForm); + setFormData({ countryes: [data, ...formData.countryes] }); + setFormDataAdd(initialState.formAdd); + target.country.value = ""; + systemNotification({status: true, message: 'Cadastrado com sucesso', type: 'success'}) + // clear fields + } catch(err) { + systemNotification({status: true, message: 'Ops! Houve erro ao cadastrar', type: 'error'}) + } + } + + const onClickEdit = (event: React.MouseEvent, idItem: string) => { + event.preventDefault(); + // Reseet Errors + resetErrors(); + editFormResetErrors(); + clearSystemNotification(); + + let result = formData.countryes.find( item => item.id === idItem ); + setEditForm({ ...sEditForm, ...result }) + setOpen(true); + } + + async function onSubmitUpdate(event: React.MouseEvent) { + event.preventDefault(); + let form = { ...sEditForm } + // Validation + if(!editFormValidateFields(form)) return; + + try { + // Set update + await service.update(form.id, form); + let updateItem = []; + updateItem = formData.countryes.map(item => (item.id === form.id ? { ...item, ...form } : item)); + setFormData({countryes: updateItem}) + editFormClear(); + setOpen(false); + systemNotification({status: true, message: 'Atualizado com sucesso', type: 'success'}) + + } catch(err) { + systemNotification({status: true, message: 'Ops! Houve erro ao cadastrar', type: 'error'}) + } + } + + async function onClickRemove (event: React.MouseEvent) { + event.preventDefault(); + setOnDialog(false); + + if (! sEditIdDelete.id_delete || sEditIdDelete.id_delete === '') { + alert('ID não existe') + return; + } + + try { + await service.deleteLugaresId(sEditIdDelete.id_delete); + const removedItem = [...formData.countryes].filter(item => item.id !== sEditIdDelete.id_delete); + setFormData({ countryes: removedItem}) + systemNotification({status: true, message: 'Deletado com sucesso', type: 'success'}) + } catch(err) { + systemNotification({status: true, message: 'Ops! houve um erro ao deletar', type: 'error'}) + } + } + + const dialogConfirmDelete = (event: React.MouseEvent, idItem: string ): void => { + event.preventDefault(); + setOnDialog(true); + setEditsEditIdDelete({id_delete: idItem}) + } + + const onChangeFormAdd = (event: { target: HTMLInputElement } ): void => { + let { name, value } = event.target; + let values = { [name]: value } + setFormDataAdd({...formDataAdd, ...values }); + if(name === 'meta') setOnErrorMeta(false); + if(name === 'local') setOnErrorLocal(false); + } + + const onChangeFormDataFlag = (event: React.ChangeEvent): void => { + let { name, value, selectedOptions } = event.target; + let values = { [name]: value }; + + if(selectedOptions[0].dataset.flag !== '') { + let values = { [name]: value , flag: selectedOptions[0].dataset.flag }; + setFormDataAdd({...formDataAdd, ...values }); + } else { + setFormDataAdd({...formDataAdd, ...values }); + } + + setOnErrorCountry(false); + } + + const editFormChangeFlag = (event: React.ChangeEvent): void => { + let { name, value, selectedOptions } = event.target; + let values = { [name]: value }; + + if(selectedOptions[0].dataset.flag !== '') { + let values = { [name]: value , flag: selectedOptions[0].dataset.flag }; + setEditForm({...sEditForm, ...values }); + } else { + setEditForm({...sEditForm, ...values }); + } + + setOnErrorCountry(false); + } + + const editFormChange = (event: { target: HTMLInputElement }) => { + let { name, value } = event.target; + let values = { [name]: value } + + setEditForm({...sEditForm, ...values }); + + if(name === 'meta') setOnErrorMeta(false); + if(name === 'local') setOnErrorLocal(false); + } + + const systemNotification = (v: SystemNotification) => { + let valuesMens = {status: v.status, message: v.message, type: v.type}; + setMsnNotification({ ...msnNotification, ...valuesMens }); + window.setTimeout(() => setOpenNotification(true), 500); + } + + //---------------------- Validates -----------------------// + const validateFields = (elem: any) => { + let count = 0; + + // Format: date YY (01|12) / Any YYYY (2021|2099) + let date_regex = /^(0[1-9]|1[0-2])\/(20[2-9][1-9])$/; + + if (!elem.country.trim()) {setOnErrorCountry(true); count++;} + if (!elem.local.trim()) {setOnErrorLocal(true); count++;} + if (!elem.meta.trim() || !date_regex.test(elem.meta)) {setOnErrorMeta(true); count++;} + if(count >= 1) return false; + + return true + } + + const editFormValidateFields = (elem: any) => { + let count = 0; + + // Format: date YY (01|12) / Any YYYY (2021|2099) + let date_regex = /^(0[1-9]|1[0-2])\/(20[2-9][1-9])$/; + + if (!elem.country.trim()) {setEditErrorCountry(true); count++;} + if (!elem.local.trim()) {setEditErrorLocal(true); count++;} + if (!elem.meta.trim() || !date_regex.test(elem.meta)) {setEditErrorMeta(true); count++;} + if(count >= 1) return false; + + return true + } + + //---------------- (Clean|Reset) States -----------------// + const editFormClear = () => { + setEditForm(initialState.formEdit) + } + + const clearSystemNotification = () => { + setMsnNotification({ status: false, message: '', type: ''}); + setOpenNotification(false) + } + + const resetErrors = () => { + setOnErrorCountry(false); + setOnErrorLocal(false); + setOnErrorMeta(false); + } + + const editFormResetErrors = () => { + setEditErrorCountry(false); + setEditErrorLocal(false); + setEditErrorMeta(false); + } + + const Alert = (props: AlertProps) => { + return ; + } + + const closeNotification = (event?: React.SyntheticEvent, reason?: string) => { + if (reason === 'clickaway') { + return; + } + + setOpenNotification(false); + }; + + //---------------------- Lifecycles------------------------// + useEffect(() => { + loadCountries(); + loadLugares(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + <> + + + + + + + + + { + openNotification && msnNotification.status && + + + { msnNotification.message } + + + } + + ); +} + +export default Home; diff --git a/lugares/src/react-app-env.d.ts b/lugares/src/react-app-env.d.ts new file mode 100644 index 000000000..6431bc5fc --- /dev/null +++ b/lugares/src/react-app-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/lugares/src/routes/index.tsx b/lugares/src/routes/index.tsx new file mode 100644 index 000000000..b3f227b6c --- /dev/null +++ b/lugares/src/routes/index.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Route, Switch } from 'react-router-dom'; + +import Home from 'pages/Home'; + +const Routes: React.FC = () => ( + + + +); + +export default Routes; diff --git a/lugares/src/services/api.tsx b/lugares/src/services/api.tsx new file mode 100644 index 000000000..2fc703e34 --- /dev/null +++ b/lugares/src/services/api.tsx @@ -0,0 +1,50 @@ +import { axiosInstance as request, apiCountries } from '../configs/axios' + +interface CountryPropsInterface { + country: string; + flag?: string; + local: string; + meta: string; +} + +export function getCountryAll() { + return apiCountries.get('/all') +} + +export function getLugaresAll() { + return request({ + url: '/lugares', + method: 'get' + }) +} + +export function getCountryName(country: string) { + return request({ + url: '/name/'+country, + method: 'get' + }) +} + +export function create(data: CountryPropsInterface) { + return request({ + url: '/lugares', + data, + method: 'post' + }) +} + +export function update(id: string, data: CountryPropsInterface) { + return request({ + url: '/lugares/'+id, + data, + method: 'put' + }) +} + +export function deleteLugaresId(id: string) { + return request({ + url: '/lugares/'+id, + method: 'delete' + }) +} + diff --git a/lugares/tsconfig.json b/lugares/tsconfig.json new file mode 100644 index 000000000..972b640ea --- /dev/null +++ b/lugares/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "baseUrl": "./src", + "target": "es5", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "module": "esnext", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx" + }, + "include": [ + "src" + ] +}