├── .github
└── ISSUE_TEMPLATE
│ └── novo-desafio.md
├── CONTRIBUTING.md
├── INSTALLING.md
├── README.md
├── frontend
├── .editorconfig
├── .env
├── .eslintrc.js
├── .gitignore
├── .prettierrc
├── Teste.log
├── debug.log
├── package.json
├── public
│ ├── banner.png
│ ├── favicon.ico
│ ├── fonts
│ │ └── FontAwesome.ttf
│ ├── index.html
│ ├── logo.png
│ ├── manifest.json
│ └── robots.txt
├── src
│ ├── App.js
│ ├── App.test.js
│ ├── assets
│ │ ├── chevron-down.svg
│ │ ├── logo.svg
│ │ └── page-under-construction.png
│ ├── components
│ │ ├── Banner
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── CategoriesList
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── CategoryListItem
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── ChallengeCard
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── ChallengesSkeleton
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── DashboardDefault
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── DevCard
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── Footer
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── Header
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── Logo
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── Newsletter
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── SidebarUser
│ │ │ ├── index.js
│ │ │ └── styles.js
│ │ ├── StatusCard
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ └── Steps
│ │ │ ├── index.js
│ │ │ └── styled.js
│ ├── index.js
│ ├── pages
│ │ ├── Challenges
│ │ │ ├── README.fr.md
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── ConstructPage
│ │ │ └── index.js
│ │ ├── Dashboard
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── Detail
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── Devs
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── Home
│ │ │ └── index.js
│ │ ├── MyChallenges
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ ├── Submit
│ │ │ ├── index.js
│ │ │ └── styled.js
│ │ └── ToDoChallenge
│ │ │ ├── index.js
│ │ │ └── styled.js
│ ├── routes.js
│ ├── serviceWorker.js
│ ├── services
│ │ ├── api.js
│ │ └── challenges.service.js
│ ├── setupTests.js
│ ├── styles
│ │ └── GlobalStyles.js
│ └── utils
│ │ └── toast.js
└── yarn.lock
├── package-lock.json
└── translations
├── README.cn.md
├── README.de.md
├── README.es.md
├── README.it.md
└── README.md
/.github/ISSUE_TEMPLATE/novo-desafio.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Novo desafio
3 | about: Sugestão de um novo desafio para o site
4 | title: "[CHALLENGE]"
5 | labels: challenge
6 | assignees: ''
7 |
8 | ---
9 |
10 | 1 - Tipo:
11 | [ ] Front-end
12 | [ ] Back-end
13 | [ ] Mobile
14 |
15 | 2 - Qual o título do seu desafio?
16 | Ex: Amazing Graph
17 |
18 | 3 - Informe o que deverá ser feito no seu desafio:
19 | Ex: Seu desafio será criar uma landing page sobre um site de criação de gráficos
20 |
21 | 4 - Quais tecnologias o dev precisará utilizar?
22 | Ex: HTML, CSS
23 |
24 | 5 - Informe o link do desafio no github:
25 | O seu desafio deverá ser um template no github, contendo texto utilizado, imagens, fontes e cores.
26 | Ex padrão: Amazing Graph .
27 | Caso você não possua, pode informar mais detalhes do desafio aqui que te auxilio ou crio o repositório pra você :)
28 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contribuir
2 | Gostaria de nos ajudar a melhorar o projeto? Veja este guia contribuição para ajudar o DevChallenge a crescer.
3 |
4 | ## Tabela de conteúdos
5 | - [Para começar](#para-começar)
6 | - [Clonando o repositório](#clonando-o-repositório)
7 | - [Criando a nova branch](#criando-a-nova-branch)
8 | - [Nomeando a mensagem de commit](#nomeando-a-mensagem-de-commit)
9 | - [Submetendo suas alterações](#submetendo-suas-alterações)
10 | - [Outras formas de contribuir](#outras-formas-de-contribuir)
11 |
12 | ## Para começar
13 | ### Clonando o repositório
14 | Faça um fork do repositório no GitHub e o clone em sua máquina.
15 | ```bash
16 | $ git clone https://github.com/{Seu nome}/DevChallenge.git
17 |
18 | $ cd DevChallenge
19 | ```
20 |
21 | ### Criando a nova branch
22 | Crie uma nova branch para a alteração que você deseja submeter. Por exemplo:
23 | ```bash
24 | $ git checkout -b fix-responsive
25 | ```
26 | Ao executar o comando acima, uma nova branch chamada `fix-responsive` será criada.
27 |
28 | **Nota:** O nome da branch deve ser significativo e deve indicar **apenas** a mudança a ser feita. Requisições que não seguirem esse padrão não serão aceitas.
29 |
30 | ### Nomeando a mensagem de commit
31 | Para elaborar uma boa mensagem de commit, você pode imaginar a seguinte frase: "Se aplicado, este commit irá {sua mensagem de commit}". Por exemplo:
32 |
33 | *Se aplicado, este commit irá **Corrigir responsividade mal formada**
34 |
35 | Ou se preferir, você também pode submeter seus commits em inglês:
36 |
37 | *If applied, this commit will **Fix malformed responsiveness***
38 |
39 | Lembre-se de começar sua mensagem com uma palavra como: Adicionar, refatorar, deletar, etc..
40 |
41 | **Nota:** Tente manter suas mensagens com menos de 50 caractéres e detalhar as alterações na descrição do commit. Apesar de não ser obrigatório, esta é uma prática muito conhecida e utilizada na comunidade do Git.
42 |
43 | ## Submetendo suas alterações
44 | Após ter realizado as mudanças, suba suas mudanças para o repositório remoto:
45 | ```bash
46 | $ git push origin fix-responsive
47 | ```
48 |
49 | Após isso, vá ao seu repositório recém clonado no GitHub, selecione a branch criada e clique em Pull Request.
50 |
51 | **IMPORTANTE:** Faça o Pull Request da sua branch especificamente para a branch `develop`. Pull Requests enviados a branch `master` serão automaticamente recusados.
52 |
53 | Faça um comentário geral sobre as mudanças realizadas e, se necessário dê uma descrição sobre as alterações realizadas e sua justificativa (opcional). Por exemplo:
54 |
55 | "**Corrigir #418**
56 |
57 | Este PR corrige a issue submetida em relação a um erro de responsividade."
58 |
59 | Após isso, seu Pull Request entrará em fase de revisão e, quem sabe, suas alterações sejam integradas ao DevChallenge!
60 |
61 | ## Outras formas de contribuir
62 | Você também pode ajudar o projeto crescer:
63 |
64 | - Criando novos desafios
65 | - Sugerindo mudanças e melhorias
66 | - Fazendo parte de nossa [comunidade](https://discord.gg/yvYXhGj) no Discord
67 |
--------------------------------------------------------------------------------
/INSTALLING.md:
--------------------------------------------------------------------------------
1 | # Instalação
2 | Essas instruções vão te levar a uma cópia do projeto rodando em sua máquina local para propósitos de testes e desenvolvimento.
3 |
4 | ## Pré-requisitos
5 | - [Node.js](https://nodejs.org/pt-br/download/) versão 12 ou superior
6 | - Gerenciador de pacotes (Yarn ou NPM)
7 |
8 | ### Clonando o repositório
9 | ```bash
10 | $ git clone https://github.com/Lorenalgm/DevChallenge.git
11 |
12 | $ cd DevChallenge
13 | ```
14 |
15 | Ou se preferir, faça o [download](https://github.com/Lorenalgm/DevChallenge/archive/master.zip) do projeto.
16 |
17 | ### Instalando dependências
18 | ```bash
19 | $ yarn
20 | ```
21 |
22 | ou
23 |
24 | ```bash
25 | $ npm install
26 | ```
27 |
28 | ### Iniciando uma instância local
29 | ```bash
30 | $ yarn start
31 | ```
32 |
33 | ou
34 |
35 | ```bash
36 | $ npm start
37 | ```
38 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [![Forks][forks-shield]][forks-url]
2 | [![Stargazers][stars-shield]][stars-url]
3 | [![Issues][issues-shield]][issues-url]
4 |
5 |
6 |
7 |
8 |
14 |
15 |
16 |
17 | DevChallenge
18 |
19 |
20 | Site para desenvolvedores melhorarem suas habilidades através de desafios de front-end, back-end e mobile!
21 |
22 |
23 | A website for developers to improve their skills by doing front-end and back-end challenges
24 |
25 |
26 | DevChallenge
27 |
28 |
29 | ## Índice
30 |
31 | - [Sobre o Projeto](#sobre-o-projeto)
32 | - [Demo](#demo)
33 | - [Tecnologias](#feito-com)
34 | - [Como Utilizar](#instalação)
35 | - [Como Contribuir](#contribuir)
36 | - [Autores](#autores)
37 | - [Comunidade](#comunidade)
38 | - [Redes sociais](#redes-sociais)
39 |
40 | ## Sobre o Projeto
41 |
42 | O [DevChallenge](https://www.devchallenge.com.br/) é um projeto que visa contribuir com a evolução de desenvolvedores, disponibilizando desafios para que possam praticar, melhorar suas skills e criarem seus portfólios :)
43 |
44 |
45 |
52 |
53 |
54 | Além disso, somos uma projeto open source onde você pode contribuir na evolução do backend, frontend e criação de novos desafios. Para saber mais, participe da nossa comunidade :)
55 |
56 | ### Feito com
57 |
58 | - [ReactJS](https://pt-br.reactjs.org/) - Biblioteca para criar interfaces de usuário
59 | - [Yarn](https://yarnpkg.com/) - Gerenciador de pacotes e dependências
60 |
61 | ## Instalação
62 |
63 | Para clonar o projeto e executá-lo em sua máquina, veja os detalhes em [INSTALLING.md](INSTALLING.md).
64 |
65 | ## Contribuir
66 |
67 | Gostaria de contribuir com o projeto? Por favor acesse [CONTRIBUTING.md](CONTRIBUTING.md) para o manual completo de contribuição.
68 |
69 | ## Autores
70 |
71 | - **Lorena Montes** - _Trabalho inicial_ - [Lorenalgm](https://github.com/Lorenalgm)
72 |
73 | Veja também a lista de [contribuidores](https://www.devchallenge.com.br/devs) que participaram do projeto.
74 |
75 | ## Comunidade
76 |
77 | Nosso objetivo é ajudar cada vez mais na evolução de desenvolvedores! Por isso, temos uma comunidade exclusiva do DevChallenge no Discord. Interessado? [Participe](https://discord.gg/yvYXhGj)!
78 |
79 | Acesse nossa [plataforma](https://www.devchallenge.com.br/)!
80 |
81 | ## Redes sociais
82 |
83 | Nos siga nas redes sociais!
84 |
85 |
86 |
87 |
88 |
94 |
95 |
96 |
97 |
98 |
104 |
105 |
106 |
107 |
108 |
114 |
115 |
116 |
117 |
118 | [forks-shield]: https://img.shields.io/github/forks/Lorenalgm/DevChallenge.svg?style=flat-square
119 | [forks-url]: https://github.com/Lorenalgm/DevChallenge/network/members
120 | [stars-shield]: https://img.shields.io/github/stars/Lorenalgm/DevChallenge.svg?style=flat-square
121 | [stars-url]: https://github.com/Lorenalgm/DevChallenge/stargazers
122 | [issues-shield]: https://img.shields.io/github/issues/Lorenalgm/DevChallenge.svg?style=flat-square
123 | [issues-url]: https://github.com/Lorenalgm/DevChallenge/issues
124 |
--------------------------------------------------------------------------------
/frontend/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 4
6 | charset = utf-8
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 |
--------------------------------------------------------------------------------
/frontend/.env:
--------------------------------------------------------------------------------
1 | REACT_APP_DEVCHALLENGE_API=http://localhost:3333
--------------------------------------------------------------------------------
/frontend/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | es6: true,
4 | },
5 | extends: ['airbnb', 'prettier', 'prettier/react'],
6 | globals: {
7 | Atomics: 'readonly',
8 | SharedArrayBuffer: 'readonly',
9 | __DEV__: 'readonly',
10 | },
11 | parser: 'babel-eslint',
12 | parserOptions: {
13 | ecmaFeatures: {
14 | jsx: true,
15 | },
16 | ecmaVersion: 2018,
17 | sourceType: 'module',
18 | },
19 | plugins: ['react', 'prettier'],
20 | rules: {
21 | 'prettier/prettier': 'error',
22 | 'react/jsx-filename-extension': [
23 | 'warn',
24 | {
25 | extensions: ['.jsx', '.js'],
26 | },
27 | ],
28 | 'import/prefer-default-export': 'off',
29 | 'react/state-in-constructor': 'off',
30 | 'react/static-property-placement': 'off',
31 | 'react/jsx-props-no-spreading': 'off',
32 | 'react/prop-types': 'off',
33 | 'no-param-reassign': 'off',
34 | 'no-console': 'off',
35 | 'no-undef': 'off',
36 | 'no-alert': 'off',
37 | },
38 | };
39 |
--------------------------------------------------------------------------------
/frontend/.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 | npm-debug.log*
21 | yarn-debug.log*
22 | yarn-error.log*
23 | .vscode
24 |
--------------------------------------------------------------------------------
/frontend/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "es5"
4 | }
5 |
--------------------------------------------------------------------------------
/frontend/Teste.log:
--------------------------------------------------------------------------------
1 | Testando PR na branch
--------------------------------------------------------------------------------
/frontend/debug.log:
--------------------------------------------------------------------------------
1 | [0729/221145.237:ERROR:crash_report_database_win.cc(469)] failed to stat report
2 | [0729/221145.282:ERROR:crash_report_database_win.cc(469)] failed to stat report
3 | [0729/221145.283:ERROR:crash_report_database_win.cc(469)] failed to stat report
4 | [0729/221145.283:ERROR:crash_report_database_win.cc(469)] failed to stat report
5 | [0729/223542.097:ERROR:crash_report_database_win.cc(469)] failed to stat report
6 | [0729/223542.098:ERROR:crash_report_database_win.cc(469)] failed to stat report
7 | [0729/223542.098:ERROR:crash_report_database_win.cc(469)] failed to stat report
8 | [0729/223542.098:ERROR:crash_report_database_win.cc(469)] failed to stat report
9 | [0729/235052.267:ERROR:crash_report_database_win.cc(469)] failed to stat report
10 | [0729/235052.268:ERROR:crash_report_database_win.cc(469)] failed to stat report
11 | [0729/235052.304:ERROR:crash_report_database_win.cc(469)] failed to stat report
12 | [0729/235052.304:ERROR:crash_report_database_win.cc(469)] failed to stat report
13 | [0730/213507.902:ERROR:crash_report_database_win.cc(469)] failed to stat report
14 | [0730/213507.904:ERROR:crash_report_database_win.cc(469)] failed to stat report
15 | [0730/213507.904:ERROR:crash_report_database_win.cc(469)] failed to stat report
16 | [0730/213507.904:ERROR:crash_report_database_win.cc(469)] failed to stat report
17 | [0731/195201.876:ERROR:crash_report_database_win.cc(469)] failed to stat report
18 | [0731/195201.899:ERROR:crash_report_database_win.cc(469)] failed to stat report
19 | [0731/195201.899:ERROR:crash_report_database_win.cc(469)] failed to stat report
20 | [0731/195201.899:ERROR:crash_report_database_win.cc(469)] failed to stat report
21 | [0801/210611.449:ERROR:crash_report_database_win.cc(469)] failed to stat report
22 | [0801/210611.500:ERROR:crash_report_database_win.cc(469)] failed to stat report
23 | [0801/210611.500:ERROR:crash_report_database_win.cc(469)] failed to stat report
24 | [0801/210611.500:ERROR:crash_report_database_win.cc(469)] failed to stat report
25 | [0813/135559.995:ERROR:crash_report_database_win.cc(469)] failed to stat report
26 | [0813/135600.175:ERROR:crash_report_database_win.cc(469)] failed to stat report
27 | [0813/135600.175:ERROR:crash_report_database_win.cc(469)] failed to stat report
28 | [0813/135600.176:ERROR:crash_report_database_win.cc(469)] failed to stat report
29 | [0813/172932.159:ERROR:crash_report_database_win.cc(469)] failed to stat report
30 | [0813/172932.219:ERROR:crash_report_database_win.cc(469)] failed to stat report
31 | [0813/172932.219:ERROR:crash_report_database_win.cc(469)] failed to stat report
32 | [0813/172932.219:ERROR:crash_report_database_win.cc(469)] failed to stat report
33 |
--------------------------------------------------------------------------------
/frontend/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "frontend",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@fortawesome/fontawesome-svg-core": "^1.2.28",
7 | "@fortawesome/free-brands-svg-icons": "^5.13.0",
8 | "@fortawesome/free-solid-svg-icons": "^5.13.0",
9 | "@fortawesome/react-fontawesome": "^0.1.9",
10 | "@lottiefiles/react-lottie-player": "^1.0.2",
11 | "@testing-library/jest-dom": "^4.2.4",
12 | "@testing-library/react": "^9.3.2",
13 | "@testing-library/user-event": "^7.1.2",
14 | "axios": "^0.21.2",
15 | "dotenv": "^8.2.0",
16 | "react": "^16.13.1",
17 | "react-awesome-slider": "^4.1.0",
18 | "react-dom": "^16.13.1",
19 | "react-icons": "^3.11.0",
20 | "react-loading-skeleton": "^2.0.1",
21 | "react-router-dom": "^5.2.0",
22 | "react-scripts": "3.4.1",
23 | "react-toastify": "^6.0.5",
24 | "react-web-vector-icons": "^1.0.2",
25 | "styled-components": "^5.1.1",
26 | "styled-media-query": "^2.1.2"
27 | },
28 | "scripts": {
29 | "start": "react-scripts start",
30 | "build": "react-scripts build",
31 | "test": "react-scripts test",
32 | "eject": "react-scripts eject"
33 | },
34 | "eslintConfig": {
35 | "extends": "react-app"
36 | },
37 | "browserslist": {
38 | "production": [
39 | ">0.2%",
40 | "not dead",
41 | "not op_mini all"
42 | ],
43 | "development": [
44 | "last 1 chrome version",
45 | "last 1 firefox version",
46 | "last 1 safari version"
47 | ]
48 | },
49 | "devDependencies": {
50 | "babel-eslint": "^10.1.0",
51 | "eslint": "^6.8.0",
52 | "eslint-config-airbnb": "^18.1.0",
53 | "eslint-config-prettier": "^6.11.0",
54 | "eslint-plugin-import": "^2.20.2",
55 | "eslint-plugin-jsx-a11y": "^6.2.3",
56 | "eslint-plugin-prettier": "^3.1.3",
57 | "eslint-plugin-react": "^7.20.0",
58 | "eslint-plugin-react-hooks": "^2.5.1",
59 | "prettier": "^2.0.5"
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/frontend/public/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lorenalgm/DevChallenge/8bbe628ae2140a8759802c7a2fc8b009d18ef2e2/frontend/public/banner.png
--------------------------------------------------------------------------------
/frontend/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lorenalgm/DevChallenge/8bbe628ae2140a8759802c7a2fc8b009d18ef2e2/frontend/public/favicon.ico
--------------------------------------------------------------------------------
/frontend/public/fonts/FontAwesome.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lorenalgm/DevChallenge/8bbe628ae2140a8759802c7a2fc8b009d18ef2e2/frontend/public/fonts/FontAwesome.ttf
--------------------------------------------------------------------------------
/frontend/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
38 | DevChallenge
39 |
40 |
43 |
44 |
45 | You need to enable JavaScript to run this app.
46 |
47 |
57 |
58 |
--------------------------------------------------------------------------------
/frontend/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lorenalgm/DevChallenge/8bbe628ae2140a8759802c7a2fc8b009d18ef2e2/frontend/public/logo.png
--------------------------------------------------------------------------------
/frontend/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "DevChallenge",
3 | "name": "DevChallenge",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo.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 |
--------------------------------------------------------------------------------
/frontend/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/frontend/src/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Routes from './routes';
3 |
4 | function App() {
5 | return ;
6 | }
7 |
8 | export default App;
9 |
--------------------------------------------------------------------------------
/frontend/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 |
--------------------------------------------------------------------------------
/frontend/src/assets/chevron-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/frontend/src/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/frontend/src/assets/page-under-construction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lorenalgm/DevChallenge/8bbe628ae2140a8759802c7a2fc8b009d18ef2e2/frontend/src/assets/page-under-construction.png
--------------------------------------------------------------------------------
/frontend/src/components/Banner/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link } from 'react-router-dom';
3 |
4 | import * as S from './styled';
5 |
6 | export default function Banner() {
7 | return (
8 |
9 |
10 | Melhore suas habilidades
11 |
12 |
13 | Com desafios de front-end, back-end e mobile
14 |
15 |
16 | Bora codar!
17 |
18 |
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/frontend/src/components/Banner/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | export const BannerContainer = styled.div`
5 | display: flex;
6 | flex-direction: column;
7 | flex-wrap: wrap;
8 | justify-content: center;
9 | align-items: center;
10 | margin-top: 160px;
11 | margin-bottom: 160px;
12 | ${media.lessThan('medium')`
13 | margin-top: 14%;
14 | margin-bottom: 14%;
15 | margin-left: 3%;
16 | margin-right: 3%;
17 | `}
18 | `;
19 |
20 | export const BannerTitle = styled.h1`
21 | color: var(--white);
22 | font-size: 60px;
23 | `;
24 |
25 | export const BannerSubtitle = styled.h2`
26 | color: var(--yellow);
27 | font-size: 20px;
28 | margin-top: 10px;
29 | margin-bottom: 20px;
30 |
31 | ${media.lessThan('medium')`
32 | font-size: 1em;
33 | `}
34 | `;
35 |
36 | export const BannerButton = styled.button`
37 | color: var(--white);
38 | background-color: var(--purple);
39 | width: 250px;
40 | height: 60px;
41 | font-weight: bold;
42 | font-size: 20px;
43 | border-radius: 50px;
44 | cursor: pointer;
45 | transition: 0.3s;
46 |
47 | &:hover {
48 | background-color: var(--dark-purple);
49 | }
50 | `;
51 |
52 | export const Typewriter = styled.div`
53 | h1 {
54 | color: var(--white);
55 | overflow: hidden;
56 | border-right: 0.15em solid var(--purple);
57 | white-space: nowrap;
58 | letter-spacing: 0.02em;
59 | animation: typing 3.5s steps(30, end),
60 | blink-caret 0.5s step-end infinite;
61 |
62 | ${media.lessThan('medium')`
63 | font-size: 1.8em;
64 | `}
65 | }
66 | @keyframes typing {
67 | from {
68 | width: 0;
69 | }
70 | to {
71 | width: 100%;
72 | }
73 | }
74 |
75 | @keyframes blink-caret {
76 | from,
77 | to {
78 | border-color: transparent;
79 | }
80 | 50% {
81 | border-color: var(--purple);
82 | }
83 | }
84 | `;
85 |
--------------------------------------------------------------------------------
/frontend/src/components/CategoriesList/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import CategoryListItem from '../CategoryListItem';
3 |
4 | import * as S from './styled';
5 |
6 | const categories = [
7 | { _id: 1, name: 'Front-end', icon: 'desktop' },
8 | { _id: 2, name: 'Back-end', icon: 'code' },
9 | { _id: 3, name: 'Mobile', icon: 'mobile' },
10 | ];
11 |
12 | export default function CategoriesList() {
13 | return (
14 |
15 | {categories.map((category) => (
16 |
17 | ))}
18 |
19 | );
20 | }
21 |
--------------------------------------------------------------------------------
/frontend/src/components/CategoriesList/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const Techs = styled.section`
4 | display: flex;
5 | flex-direction: row;
6 | flex-wrap: wrap;
7 | align-items: center;
8 | justify-content: center;
9 | `;
10 |
--------------------------------------------------------------------------------
/frontend/src/components/CategoryListItem/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import Icon from 'react-web-vector-icons';
4 | import * as S from './styled';
5 |
6 | export default function CategoryListItem({ category }) {
7 | const type = category.name.replace('-', '').toLowerCase();
8 | return (
9 |
16 |
17 |
23 | {category.name}
24 |
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/frontend/src/components/CategoryListItem/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | import { Link } from 'react-router-dom';
5 |
6 | export const Anchor = styled(Link)`
7 | text-decoration: none;
8 | margin: 0 25px 0 25px;
9 |
10 | ${media.lessThan('medium')`
11 | margin: 15px 0px 10px 0px;
12 | `}
13 | `;
14 |
15 | export const Card = styled.div`
16 | width: 300px;
17 | height: 300px;
18 | background-color: var(--secondary);
19 | border-radius: 20px;
20 |
21 | cursor: pointer;
22 | display: flex;
23 | flex-direction: column;
24 | align-items: center;
25 | justify-content: center;
26 | transition: 0.25s;
27 |
28 | &:hover {
29 | background-color: var(--dark-hover);
30 | }
31 | `;
32 |
33 | export const Title = styled.h2`
34 | color: var(--white);
35 | margin-top: 20px;
36 |
37 | ${media.lessThan('medium')`
38 | margin-top: 0.6em;
39 | `}
40 | `;
41 |
42 |
43 |
--------------------------------------------------------------------------------
/frontend/src/components/ChallengeCard/index.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 |
3 | import * as S from './styled';
4 |
5 | const colorMatch = {
6 | beginner: 'nephritis',
7 | intermediate: 'pumpkin',
8 | advanced: 'pomegranate',
9 | Mobile: 'blue',
10 | Frontend: 'red',
11 | Backend: 'light-purple',
12 | };
13 |
14 | function ChallengeCard({ challenge, progress, redirect, buttonText }) {
15 | const [techs, setTechs] = useState([]);
16 |
17 | useEffect(() => {
18 | const techsUnOrder = challenge.techs
19 | .toString()
20 | .split(',')
21 | .map((element) => element.replace(/^[ ]/, ''));
22 |
23 | techsUnOrder.forEach((techItem, i) => {
24 | techsUnOrder.forEach((element, j) => {
25 | if (j > i && element.length > techItem.length) {
26 | const aux = techItem;
27 | techsUnOrder[i] = element;
28 | techsUnOrder[j] = aux;
29 | }
30 | });
31 | });
32 |
33 | setTechs(techsUnOrder);
34 | }, [challenge.techs]);
35 |
36 | return (
37 |
38 |
39 |
40 |
41 | {techs.map((item) => (
42 |
46 | {item}
47 |
48 | ))}
49 |
50 |
51 |
52 | {challenge.type}
53 |
54 |
55 | {challenge.level}
56 |
57 |
58 |
59 |
60 | {progress && }
61 |
62 |
63 |
64 | {challenge.name}
65 |
66 | {challenge.description}
{' '}
67 |
68 |
69 | {buttonText}
70 |
71 |
72 | );
73 | }
74 |
75 | export default ChallengeCard;
76 |
--------------------------------------------------------------------------------
/frontend/src/components/ChallengeCard/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import { Link } from 'react-router-dom';
3 |
4 | export const Anchor = styled(Link)`
5 | text-decoration: none;
6 | cursor: pointer;
7 |
8 | color: var(--white-gray);
9 | `;
10 |
11 | export const Level = styled.span`
12 | background-color: var(--${(props) => props.color});
13 | padding: 6px 16px;
14 | font-size: 11px;
15 | height: 23px;
16 | border-radius: 20px;
17 | font-weight: bold;
18 | margin-bottom: 5px;
19 | `;
20 |
21 | export const ChallengeCard = styled.div`
22 | height: 350px;
23 | width: 300px;
24 |
25 | background-color: var(--secondary);
26 | border-radius: 16px;
27 |
28 | margin: 1em 1em 1em 1em;
29 |
30 | display: flex;
31 | flex-direction: column;
32 | align-items: center;
33 |
34 | position: relative;
35 | overflow: hidden;
36 | `;
37 |
38 | export const CardImage = styled.div`
39 | overflow: hidden;
40 | height: 150px;
41 | width: 300px;
42 | background-color: #2b3035;
43 |
44 | img {
45 | transition: 0.3s;
46 | width: 100%;
47 | }
48 | img:hover {
49 | transform: scale(1.1);
50 | }
51 | `;
52 |
53 | export const CardContent = styled.div`
54 | margin-top: 10px;
55 | color: var(--white-gray);
56 | text-align: center;
57 | width: 100%;
58 | padding: 0 16px;
59 |
60 | h1 {
61 | font-size: 25px;
62 | margin-top: 0px;
63 | font-weight: 500;
64 | }
65 |
66 | p {
67 | margin-top: 10px;
68 | }
69 | `;
70 |
71 | export const CardTechs = styled.div`
72 | position: absolute;
73 | right: 0;
74 | top: 16px;
75 | padding: 0 16px;
76 | height: auto;
77 | display: flex;
78 | flex-direction: column;
79 | justify-content: space-between;
80 | align-items: flex-end;
81 | z-index: 999;
82 | .tech {
83 | background-color: var(--quaternary);
84 | padding: 5px 15px;
85 | margin-bottom: 5px;
86 | border-radius: 25px;
87 | text-align: center;
88 | font-weight: bold;
89 | color: var(--white);
90 | align-items: center;
91 | font-size: 13px;
92 | }
93 |
94 | .level {
95 | color: var(--yellow);
96 | font-weight: bold;
97 | }
98 | `;
99 |
100 | export const CardPlatforms = styled.div`
101 | position: absolute;
102 | left: 0;
103 | top: 16px;
104 | padding: 0 16px;
105 | height: auto;
106 | display: flex;
107 | flex-direction: column;
108 | justify-content: space-between;
109 | align-items: flex-start;
110 | z-index: 999;
111 | `;
112 |
113 | export const Button = styled.button`
114 | width: 80%;
115 | height: 46px;
116 |
117 | position: absolute;
118 | bottom: 16px;
119 | left: 50%;
120 | transform: translateX(-50%);
121 |
122 | background: var(--purple);
123 | color: var(--white);
124 | font-weight: bold;
125 | font-size: 18px;
126 |
127 | border-radius: 50px;
128 |
129 | cursor: pointer;
130 |
131 | transition: 0.25s;
132 |
133 | &:hover {
134 | width: 83%;
135 | }
136 | `;
137 |
138 | export const ProgressBar = styled.div`
139 | width: 100%;
140 | height: 8px;
141 | background: var(--quinary);
142 |
143 | &::after {
144 | position: absolute;
145 | content: ' ';
146 | width: ${(props) => `${props.progress}%`};
147 | height: 8px;
148 | background: var(--green);
149 | border-radius: 0 5px 5px 0;
150 | }
151 | `;
152 |
--------------------------------------------------------------------------------
/frontend/src/components/ChallengesSkeleton/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Skeleton, { SkeletonTheme } from 'react-loading-skeleton';
3 | import * as S from './styled';
4 |
5 | export default function ChallengesSkeleton({ cards = 4 }) {
6 | const arr = Array.from({ length: cards }, (_, i) => i + 1);
7 |
8 | return (
9 |
10 |
11 | {arr.map((item) => (
12 |
13 |
14 |
15 | ))}
16 |
17 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/frontend/src/components/ChallengesSkeleton/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const Section = styled.section`
4 | margin-top: 3%;
5 | display: flex;
6 | flex-wrap: wrap;
7 | max-width: 100vw;
8 | align-items: center;
9 | justify-content: center;
10 | `;
11 |
12 | export const ChallengeSkeleton = styled.div`
13 | border-radius: 16px;
14 | cursor: pointer;
15 |
16 | height: 350px;
17 | width: 300px;
18 | margin: 0 0.5em 1em 0.5em;
19 |
20 | overflow: hidden;
21 | `;
22 |
--------------------------------------------------------------------------------
/frontend/src/components/DashboardDefault/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import SidebarUser from '../SidebarUser';
4 | import Logo from '../Logo';
5 | import { DashboardWrapper, DashboardContent, DbHeader } from './styled';
6 |
7 | function DashboardDefault(props) {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {props.children}
17 |
18 |
19 | );
20 | }
21 |
22 | export default DashboardDefault;
23 |
--------------------------------------------------------------------------------
/frontend/src/components/DashboardDefault/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | export const DashboardWrapper = styled.div`
5 | display: flex;
6 | min-height: calc(100vh - 100px);
7 | `;
8 |
9 | export const DashboardContent = styled.div`
10 | display: flex;
11 | flex: 1;
12 | flex-direction: column;
13 | color: var(--light-gray);
14 | `;
15 |
16 | export const DbHeader = styled.header`
17 | display: flex;
18 | align-items: center;
19 | justify-content: flex-end;
20 | padding: 0px 80px 0 80px;
21 | margin-top: 40px;
22 |
23 | font-weight: normal;
24 |
25 | ${media.between('medium', 'large')`
26 | padding: 0px 60px 0 60px;
27 | `}
28 |
29 | ${media.lessThan('medium')`
30 | display: flex;
31 | align-items: flex-end;
32 | flex-direction: column;
33 | justify-content: center;
34 | padding: 0 20px;
35 | position: relative;
36 | `}
37 | `;
38 |
--------------------------------------------------------------------------------
/frontend/src/components/DevCard/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4 | import { faGithubSquare, faLinkedin } from '@fortawesome/free-brands-svg-icons';
5 |
6 | import * as S from './styled';
7 |
8 | function DevCard(props) {
9 | return (
10 |
11 |
12 |
13 | {props.name}
14 | {props.position}
15 |
16 |
17 | {props.github && (
18 |
24 |
25 |
26 | )}
27 | {props.linkedin && (
28 |
34 |
35 |
36 | )}
37 |
38 |
39 | );
40 | }
41 |
42 | export default DevCard;
43 |
--------------------------------------------------------------------------------
/frontend/src/components/DevCard/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 |
5 | export const Card = styled.div`
6 | min-width: 300px;
7 | height: 90px;
8 |
9 | box-sizing: border-box;
10 | padding: 0px 10px;
11 |
12 | background: var(--secondary);
13 | border-radius: 16px;
14 |
15 | display: flex;
16 | align-items: center;
17 |
18 | position: relative;
19 |
20 | > img {
21 | height: 70px;
22 | width: 70px;
23 | border-radius: 50%;
24 | }
25 |
26 | ${media.lessThan('medium')`
27 | margin-bottom: 5%;
28 | `}
29 | `;
30 |
31 |
32 | export const Infos = styled.div`
33 | max-width: 200px;
34 | flex-wrap: wrap;
35 |
36 | display: flex;
37 | flex-direction: column;
38 | justify-content: center;
39 | align-items: left;
40 |
41 | margin: 0 16px;
42 |
43 | > h1 {
44 | font-size: 18px;
45 | font-weight: bold;
46 | color: var(--white);
47 | }
48 |
49 | > span {
50 | font-size: 14px;
51 | font-weight: 500;
52 | color: var(--yellow);
53 | }
54 | `;
55 |
56 |
57 | export const Social = styled.div`
58 | display: flex;
59 | flex-direction: column;
60 |
61 | position: absolute;
62 | right: 16px;
63 | `;
64 |
65 | export const Anchor = styled.a`
66 | text-decoration: none;
67 | color: var(--white);
68 | font-size: 20px;
69 |
70 | display: flex;
71 | align-items: center;
72 | justify-content: center;
73 |
74 | transition: .25s;
75 |
76 | &:hover{
77 | color: var(--yellow);
78 | }
79 | `;
--------------------------------------------------------------------------------
/frontend/src/components/Footer/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4 | import { faGithub, faDiscord, faInstagram, faTwitter } from '@fortawesome/free-brands-svg-icons';
5 |
6 | import * as S from './styled';
7 |
8 | function Footer() {
9 | return (
10 |
11 |
12 |
18 |
19 |
20 |
26 |
27 |
28 |
34 |
35 |
36 |
42 |
43 |
44 |
45 |
46 | DevChallenge
47 |
48 |
49 | );
50 | }
51 |
52 | export default Footer;
--------------------------------------------------------------------------------
/frontend/src/components/Footer/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | export const Container = styled.footer`
5 | width: 100%;
6 | height: 100px;
7 |
8 | padding: 40px 100px;
9 |
10 | background-color: var(--tertiary);
11 |
12 | display: flex;
13 | justify-content: space-between;
14 |
15 | ${media.lessThan('small')`
16 | flex-direction: column-reverse;
17 | align-items: center;
18 | justify-content: center;
19 | `}
20 | `;
21 |
22 | export const Social = styled.div`
23 | display: flex;
24 |
25 | > a ~ a {
26 | margin-left: 20px;
27 | }
28 | `;
29 |
30 | export const Title = styled.div`
31 | font-size: 24px;
32 | font-weight: bold;
33 | color: var(--white);
34 |
35 | span {
36 | color: var(--yellow);
37 | }
38 |
39 | ${media.lessThan('small')`
40 | margin-bottom: 25px;
41 | `}
42 | `;
43 |
44 | export const Anchor = styled.a`
45 | text-decoration: none;
46 | font-size: 22px;
47 | color: var(--quinary);
48 |
49 | transition: 0.25s;
50 |
51 | &:hover {
52 | color: var(--yellow);
53 | }
54 | `;
55 |
--------------------------------------------------------------------------------
/frontend/src/components/Header/index.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { useLocation } from 'react-router-dom';
3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4 | import { faBars, faTimes } from '@fortawesome/free-solid-svg-icons';
5 | import { faGithub } from '@fortawesome/free-brands-svg-icons';
6 | import * as S from './styled';
7 |
8 | export default function Header() {
9 | const location = useLocation();
10 | const [clicked, setClicked] = useState(false);
11 |
12 | useEffect(() => {
13 | setClicked(false);
14 | }, [location]);
15 |
16 | return (
17 |
18 |
19 |
20 | DevChallenge
21 |
22 |
23 |
24 | setClicked(!clicked)}>
25 | {!clicked ? (
26 |
27 | ) : (
28 |
29 | )}
30 |
31 |
32 |
33 |
34 |
35 |
36 | Início
37 |
38 |
39 |
40 |
44 | Desafios
45 |
46 |
47 |
48 |
49 | Comunidade
50 |
51 |
52 |
53 |
54 | Entrar
55 |
59 |
60 |
61 |
62 |
63 |
64 | );
65 | }
66 |
--------------------------------------------------------------------------------
/frontend/src/components/Header/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 | import { NavLink } from 'react-router-dom';
4 |
5 | export const Header = styled.header`
6 | display: flex;
7 | align-items: center;
8 | justify-content: space-between;
9 |
10 | padding: 0px 80px 0 80px;
11 | margin-top: 40px;
12 |
13 | font-weight: normal;
14 |
15 | ${media.between('medium', 'large')`
16 | padding: 0px 60px 0 60px;
17 | `}
18 |
19 | ${media.lessThan('medium')`
20 | display: flex;
21 | align-items: flex-start;
22 | flex-direction: column;
23 | justify-content: center;
24 | padding: 0;
25 | position: relative;
26 | `}
27 | `;
28 |
29 | export const Title = styled.div`
30 | font-size: 30px;
31 | font-weight: bold;
32 | color: var(--white);
33 |
34 | span {
35 | color: var(--yellow);
36 | }
37 |
38 | ${media.lessThan('medium')`
39 | margin-left: 20px;
40 | `}
41 | `;
42 |
43 | export const MenuMobile = styled.div`
44 | display: none;
45 |
46 | transition: 0.25s;
47 |
48 | ${media.lessThan('medium')`
49 | display: block;
50 | position: absolute;
51 | font-size: 25px;
52 | color: var(--white);
53 | top: 2;
54 | right: 0;
55 | margin-right: 20px;
56 | cursor: pointer;
57 |
58 | z-index: 9999;
59 | `}
60 | `;
61 |
62 | export const Menu = styled.div`
63 | ul {
64 | display: flex;
65 | align-items: center;
66 |
67 | list-style-type: none;
68 |
69 | font-size: 20px;
70 | color: var(--white);
71 | font-weight: 400;
72 |
73 | li ~ li {
74 | margin-left: 20px;
75 | }
76 |
77 | li:hover {
78 | opacity: 0.8;
79 | }
80 |
81 | ${media.lessThan('medium')`
82 | background-color: var(--primary);
83 | flex-direction: column;
84 | width: 100%;
85 | position: absolute;
86 | justify-content: space-around;
87 | height: 300px;
88 | align-items: center;
89 | margin-top: 0.5em;
90 | top: -100%;
91 | transform: ${({ open }) =>
92 | open ? 'translateY(-100%)' : 'translateY(0)'};
93 | transition: transform 0.5s ease;
94 | z-index: 1000;
95 | li ~ li {
96 | margin-left: 0;
97 | }
98 | `}
99 | }
100 | `;
101 |
102 | export const StyledLink = styled(NavLink)`
103 | text-decoration: none;
104 | color: var(--white);
105 |
106 | cursor: pointer;
107 |
108 | &.is-active {
109 | color: var(--yellow);
110 | }
111 | `;
112 |
113 | export const ButtonLink = styled(NavLink)`
114 | background-color: var(--quaternary);
115 |
116 | width: 100px;
117 | padding: 5px 30px;
118 | border-radius: 25px;
119 |
120 | text-align: center;
121 | text-decoration: none;
122 | color: var(--white);
123 |
124 | &.is-active {
125 | background-color: var(--yellow);
126 | color: var(--tertiary);
127 | }
128 | `;
129 |
--------------------------------------------------------------------------------
/frontend/src/components/Logo/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { StyledLink } from '../Header/styled';
4 | import { Title } from './styled';
5 |
6 | function Logo() {
7 | return (
8 |
9 |
10 | DevChallenge
11 |
12 |
13 | );
14 | }
15 |
16 | export default Logo;
17 |
--------------------------------------------------------------------------------
/frontend/src/components/Logo/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const Title = styled.div`
4 | font-size: 30px;
5 | font-weight: bold;
6 | color: var(--white);
7 | span {
8 | color: var(--yellow);
9 | }
10 | `;
11 |
--------------------------------------------------------------------------------
/frontend/src/components/Newsletter/index.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { Player } from '@lottiefiles/react-lottie-player';
3 | import api from '../../services/api';
4 | import ToastNotification from '../../utils/toast';
5 |
6 | import * as S from './styled';
7 |
8 | export default function Newsletter() {
9 | const [email, setEmail] = useState('');
10 |
11 | async function handleSubscribe(e) {
12 | e.preventDefault();
13 |
14 | const data = {
15 | email,
16 | };
17 |
18 | try {
19 | await api.post('newsletter', data);
20 | ToastNotification.notify(
21 | 'success',
22 | 'Feito! Você será o primeiro a saber sobre novos desafios :)'
23 | );
24 | } catch (err) {
25 | ToastNotification.notify(
26 | 'error',
27 | 'Opa, algo deu errado! Pode tentar novamente? :c'
28 | );
29 | }
30 | }
31 |
32 | return (
33 |
34 |
43 |
44 |
45 | Seja notificado sobre novos desafios!
46 |
47 |
48 | Inscreva-se para ser o primeiro a saber sobre novos desafios
49 | :)
50 |
51 |
52 | setEmail(e.target.value)}
57 | required
58 | />
59 | Inscrever
60 |
61 |
62 |
63 | );
64 | }
65 |
--------------------------------------------------------------------------------
/frontend/src/components/Newsletter/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | export const NewsletterContainer = styled.section`
5 | display: flex;
6 | flex-direction: row;
7 | justify-content: center;
8 | align-items: center;
9 |
10 | ${media.lessThan('medium')`
11 | flex-direction: column;
12 | `}
13 |
14 | div {
15 | display: flex;
16 | flex-direction: column;
17 | align-items: left;
18 | margin-left: 2em;
19 |
20 | ${media.lessThan('medium')`
21 | align-items: center;
22 | justify-content: center;
23 | text-align: center;
24 | margin-left: 0;
25 | `}
26 | }
27 | `;
28 |
29 | export const NewsletterTitle = styled.h1`
30 | color: var(--white);
31 | font-size: 2em;
32 | margin-bottom: 0.1em;
33 |
34 | ${media.lessThan('medium')`
35 | font-size: 1.3em;
36 | margin-bottom: 0.1em;
37 | `}
38 | `;
39 |
40 | export const NewsletterParagraph = styled.p`
41 | color: var(--yellow);
42 | font-size: 1em;
43 |
44 | ${media.lessThan('medium')`
45 | margin: 1em;
46 | `}
47 | `;
48 |
49 | export const NewsletterForm = styled.form`
50 | display: flex;
51 | flex-direction: column;
52 |
53 | ${media.lessThan('medium')`
54 | display: flex;
55 | align-content: center;
56 | justify-content: center;
57 | text-align: center;
58 | margin-bottom: 3em;
59 | `}
60 |
61 | input {
62 | height: 3.5em;
63 | width: 20em;
64 | margin-top: 1em;
65 | margin-bottom: 1em;
66 | border-radius: 0.5em;
67 | padding: 20px;
68 | font-size: 18px;
69 |
70 | ${media.lessThan('medium')`
71 | height: 3em;
72 | width: 18em;
73 | `}
74 | }
75 |
76 | button {
77 | color: var(--white);
78 | background-color: var(--purple);
79 | width: 350px;
80 | height: 60px;
81 | font-weight: bold;
82 | font-size: 20px;
83 | border-radius: 50px;
84 | cursor: pointer;
85 | transition: 0.3s;
86 |
87 | ${media.lessThan('medium')`
88 | width: 16em;
89 | height: 3em;
90 | `}
91 |
92 | &:hover {
93 | background-color: var(--dark-purple);
94 | }
95 | }
96 | `;
97 |
--------------------------------------------------------------------------------
/frontend/src/components/SidebarUser/index.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import { useLocation } from 'react-router-dom';
3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4 | import { faBars, faTimes } from '@fortawesome/free-solid-svg-icons';
5 |
6 | import Icon from 'react-web-vector-icons';
7 | import { Aside, Img, UserInfo, StyledLink, Menu, MenuMobile } from './styles';
8 |
9 | function SidebarUser() {
10 | const location = useLocation();
11 | const [clicked, setClicked] = useState(false);
12 | const [user, setUser] = useState({});
13 |
14 | useEffect(() => {
15 | setClicked(false);
16 | setUser({
17 | name: 'Dev Challenge',
18 | username: '@devChallenge',
19 | img: '',
20 | });
21 | }, [location]);
22 |
23 | return (
24 | <>
25 | setClicked(!clicked)}>
26 | {!clicked ? (
27 |
28 | ) : (
29 |
30 | )}
31 |
32 |
33 |
34 |
42 | {user.name}
43 | {user.username}
44 |
45 |
46 |
47 |
48 |
49 |
53 |
60 | Desafios
61 |
62 |
63 |
64 |
68 |
75 | Meus Desafios
76 |
77 |
78 |
79 |
80 |
87 | Comunidade
88 |
89 |
90 |
91 |
92 |
93 | >
94 | );
95 | }
96 |
97 | export default SidebarUser;
98 |
--------------------------------------------------------------------------------
/frontend/src/components/SidebarUser/styles.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 | import { NavLink } from 'react-router-dom';
4 |
5 | export const Aside = styled.aside`
6 | display: flex;
7 | align-items: center;
8 | flex-direction: column;
9 | text-align: center;
10 |
11 | width: 350px;
12 | background: var(--secondary);
13 | color: var(--white);
14 |
15 | ${media.between('medium', 'large')`
16 | width: 278px;
17 | `}
18 |
19 | ${media.lessThan('860px')`
20 | position: absolute;
21 | top: 0;
22 | bottom: 0;
23 | z-index: 9998;
24 |
25 | transform: ${({ open }) =>
26 | open ? 'translateX(0)' : 'translateX(-350px)'};
27 | transition: 0.5s ease;
28 | `}
29 | `;
30 |
31 | export const UserInfo = styled.div`
32 | margin-top: 40px;
33 |
34 | & > p {
35 | font-size: 16px;
36 | font-family: Roboto;
37 | }
38 |
39 | & > span {
40 | font-family: Roboto;
41 | font-size: 12px;
42 | }
43 | `;
44 |
45 | export const Img = styled.img`
46 | height: 90px;
47 | width: 90px;
48 | border-radius: 50%;
49 | margin-bottom: 10px;
50 | border: 3px solid var(--yellow);
51 | `;
52 |
53 | export const Menu = styled.div`
54 | ul {
55 | display: flex;
56 | flex-direction: column;
57 | align-items: center;
58 | justify-content: center;
59 | width: 350px;
60 | margin-top: 60px;
61 | list-style: none;
62 |
63 | ${media.between('medium', 'large')`
64 | width: 278px;
65 | `}
66 |
67 | li {
68 | width: 200px;
69 | height: 45px;
70 | display: flex;
71 | align-items: center;
72 | font-size: 18px;
73 | }
74 |
75 | li:hover {
76 | opacity: 0.8;
77 | }
78 | }
79 | `;
80 |
81 | export const StyledLink = styled(NavLink)`
82 | text-decoration: none;
83 | color: var(--white);
84 |
85 | &.is-active {
86 | color: var(--yellow);
87 | }
88 | `;
89 |
90 | export const MenuMobile = styled.div`
91 | display: none;
92 |
93 | transition: 0.25s;
94 |
95 | ${media.lessThan('860px')`
96 | display: block;
97 | position: absolute;
98 | font-size: 25px;
99 | color: var(--white);
100 | top: 50px;
101 | left: 20px;
102 | margin-right: 20px;
103 | cursor: pointer;
104 |
105 | z-index: 9999;
106 | `}
107 | `;
108 |
--------------------------------------------------------------------------------
/frontend/src/components/StatusCard/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import { CardWrapper } from './styled';
4 |
5 | function StatusCard(props) {
6 | return (
7 |
8 | {props.title}
9 | {props.count}
10 |
11 | );
12 | }
13 |
14 | export default StatusCard;
15 |
--------------------------------------------------------------------------------
/frontend/src/components/StatusCard/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const CardWrapper = styled.div`
4 | display: flex;
5 | width: 48%;
6 | max-width: 350px;
7 | height: 110px;
8 | background: var(--secondary);
9 | border-radius: 11px;
10 | border: 2px solid;
11 | padding: 25px;
12 | align-items: center;
13 | justify-content: space-between;
14 | color: var(--white);
15 |
16 | & > p {
17 | width: 150px;
18 | font-weight: 400;
19 | font-size: 20px;
20 | padding: 10px;
21 | }
22 |
23 | & > h1 {
24 | font-size: 50px;
25 | }
26 | `;
27 |
--------------------------------------------------------------------------------
/frontend/src/components/Steps/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import {
3 | faSearch,
4 | faCode,
5 | faShareSquare,
6 | } from '@fortawesome/free-solid-svg-icons';
7 |
8 | import * as S from './styled';
9 |
10 | export default function Steps() {
11 | return (
12 |
13 |
14 |
15 | Escolha
16 |
17 |
18 |
19 | Desenvolva
20 |
21 |
22 |
23 | Compartilhe
24 |
25 |
26 | );
27 | }
28 |
--------------------------------------------------------------------------------
/frontend/src/components/Steps/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
5 |
6 | export const StepsContainer = styled.section`
7 | margin-top: 100px;
8 |
9 | display: flex;
10 | align-items: center;
11 | justify-content: center;
12 |
13 | ${media.lessThan('medium')`
14 | padding: 0;
15 | `}
16 | `;
17 |
18 | export const Step = styled.div`
19 | width: 300px;
20 | height:300px;
21 |
22 | display: flex;
23 | flex-direction: column;
24 | align-items: center;
25 | justify-content: center;
26 |
27 | h2 {
28 | color: var(--yellow);
29 | margin-top: 20px;
30 |
31 | ${media.lessThan('medium')`
32 | font-size: 1em;
33 | `}
34 | }
35 | `;
36 |
37 | export const Icon = styled(FontAwesomeIcon)`
38 | color: var(--white);
39 | width: 60px !important;
40 | height: 60px;
41 |
42 | ${media.lessThan('medium')`
43 | height: 3em;
44 | width: 3em;
45 | `}
46 | `;
47 |
--------------------------------------------------------------------------------
/frontend/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import App from './App';
4 | import * as serviceWorker from './serviceWorker';
5 | import { GlobalStyles } from './styles/GlobalStyles';
6 |
7 | ReactDOM.render(
8 |
9 |
10 |
11 | ,
12 | document.getElementById('root')
13 | );
14 |
15 | // If you want your app to work offline and load faster, you can change
16 | // unregister() to register() below. Note this comes with some pitfalls.
17 | // Learn more about service workers: https://bit.ly/CRA-PWA
18 | serviceWorker.unregister();
19 |
--------------------------------------------------------------------------------
/frontend/src/pages/Challenges/README.fr.md:
--------------------------------------------------------------------------------
1 | [![Forks][forks-shield]][forks-url]
2 | [![Stargazers][stars-shield]][stars-url]
3 | [![Issues][issues-shield]][issues-url]
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
DevChallenge
12 |
13 |
14 | Site permettant aux développeurs d'améliorer leurs compétences grâce à des défis Front-end, Back-end et Mobile!
15 |
16 |
17 | DevChallenge
18 |
19 |
20 | ## Sommaire
21 |
22 | - [Sommaire](#sommaire)
23 | - [A propos du projet](#a-propos-du-projet)
24 | - [Demo:](#demo)
25 | - [Technologies:](#technologies)
26 | - [Utilisation](#utilisation)
27 | - [Contribution](#contribution)
28 | - [Prérequis](#prérequis)
29 | - [Installation](#installation)
30 | - [Communauté](#communauté)
31 |
32 | ## A propos du projet
33 | Le DevChallenge est un projet contribuant à l'évolution des développeurs, en leur fournissant des défis afin qu'ils puissent s'entraîner, améliorer leurs compétences et créer leur portfolio :)
34 |
35 | ### Demo:
36 |
37 |
38 |
39 |
40 | ### Technologies:
41 | - Backend: Nodejs
42 | - Frontend: Reactjs
43 | - Banque de données: MongoDB
44 |
45 | ## Utilisation
46 | 1 - Utilisez un des modèles DevChallenge comme base.
47 | 2 - Lisez les instructions du readme.md.
48 | 3 - Codez.
49 | 4 - Partagez le résultat avec la communauté :)
50 |
51 | ## Contribution
52 | Participez au projet:
53 | - Suggérez et / ou créez de nouveaux défis: ces défis seront alors disponibles et pourront aider tous les développeurs à s'entraîner.
54 | - Améliorez ou corrigez le site: vous pouvez envoyer une *Pull Request* afin que votre modification soit disponible à tous les développeurs!
55 |
56 | ### Prérequis
57 | 1. Nodejs
58 |
59 | ### Installation
60 |
61 | Front-end
62 |
63 | 1. Téléchargez ou clonez le répertoire DevChallenge
64 | ```sh
65 | git clone git@github.com:Lorenalgm/DevChallenge.git
66 | ```
67 | 2. Ouvrez le projet avec votre éditeur.
68 | 3. A partir du terminal, installez les dépendances (packages) nécessaires:
69 | ```sh
70 | yarn
71 | ```
72 | ou
73 | ```sh
74 | npm install
75 | ```
76 | 4. Parfait! Vous pouvez maintenant vous rendre dans le dossier `frontend` e inicier votre serveur:
77 | ```sh
78 | cd frontend
79 | ```
80 | ```sh
81 | yarn start
82 | ```
83 | 1. Ouvrez votre navigateur! Le DevChallenge sera disponible à `http://localhost:3000/` :)
84 |
85 |
86 | Back-end
87 |
88 | Le Backend est disponible dans le répertoire: DevChallengeAPI
89 |
90 |
91 | ## Communauté
92 | Notre objectif est d'aider au maximum les développeurs dans leur évolution! Nous avons donc une communauté DevChallenge exclusive sur Discord. On se retrouve là-bas? https://discord.gg/yvYXhGj
93 |
94 | Site: https://www.devchallenge.com.br/
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | [forks-shield]: https://img.shields.io/github/forks/Lorenalgm/DevChallenge.svg?style=flat-square
106 | [forks-url]: https://github.com/Lorenalgm/DevChallenge/network/members
107 | [stars-shield]: https://img.shields.io/github/stars/Lorenalgm/DevChallenge.svg?style=flat-square
108 | [stars-url]: https://github.com/Lorenalgm/DevChallenge/stargazers
109 | [issues-shield]: https://img.shields.io/github/issues/Lorenalgm/DevChallenge.svg?style=flat-square
110 | [issues-url]: https://github.com/Lorenalgm/DevChallenge/issues
111 |
--------------------------------------------------------------------------------
/frontend/src/pages/Challenges/index.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import api from '../../services/api';
3 | import ChallengesSkeleton from '../../components/ChallengesSkeleton';
4 | import ChallengeCard from '../../components/ChallengeCard';
5 | import Header from '../../components/Header';
6 | import * as S from './styled';
7 |
8 | const languages = [
9 | { id: 1, name: 'React Native' },
10 | { id: 2, name: 'Free Choice' },
11 | { id: 3, name: 'Javascript' },
12 | { id: 4, name: 'HTML' },
13 | { id: 5, name: 'CSS' },
14 | ];
15 |
16 | const types = [
17 | { id: 1, name: 'Frontend' },
18 | { id: 2, name: 'Backend' },
19 | { id: 3, name: 'Mobile' },
20 | ];
21 |
22 | export default function Challenges({ location }) {
23 | const [challenges, setChallenges] = useState([]);
24 | const [filteredChallenges, setFilteredChallenges] = useState([]);
25 | const [loading, setLoading] = useState(true);
26 | const [languageFilter, setLanguageFilter] = useState('');
27 | const [typeFilter, setTypeFilter] = useState(location.search.split('=')[1]);
28 |
29 | function capitalize(s) {
30 | return s && s[0].toUpperCase() + s.slice(1);
31 | }
32 |
33 | useEffect(() => {
34 | window.scrollTo(0, 0);
35 | async function loadChallenges() {
36 | const response = await api.get('/challenges');
37 |
38 | setChallenges(response.data);
39 | setFilteredChallenges(response.data);
40 |
41 | setLoading(false);
42 | }
43 |
44 | loadChallenges();
45 | }, [location]);
46 |
47 | useEffect(() => {
48 | let filtered = challenges;
49 | if (typeFilter) {
50 | filtered = filtered.filter(
51 | (challenge) =>
52 | challenge.type.toLowerCase() === typeFilter.toLowerCase()
53 | );
54 | }
55 | if (languageFilter) {
56 | filtered = filtered.filter((challenge) => {
57 | const [ techs ] = challenge.techs;
58 | const serializedTechs = techs.split(', ');
59 | const hasSelectedTech =
60 | serializedTechs.includes(languageFilter) ||
61 | serializedTechs.includes('Free Choice');
62 |
63 | return hasSelectedTech;
64 | });
65 | }
66 | setFilteredChallenges(filtered);
67 | }, [typeFilter, languageFilter, challenges]);
68 |
69 | return (
70 | <>
71 |
72 |
73 | Desafios
74 |
75 |
76 | Categoria
77 |
78 | {
81 | setTypeFilter(e.target.value);
82 | }}
83 | defaultValue={capitalize(typeFilter)}
84 | >
85 | All
86 | {types.map((type) => (
87 |
88 | {type.name}
89 |
90 | ))}
91 |
92 |
93 |
94 |
95 | Linguagem
96 |
97 |
101 | setLanguageFilter(e.target.value)
102 | }
103 | >
104 | All
105 | {languages.map((lang) => (
106 |
107 | {lang.name}
108 |
109 | ))}
110 |
111 |
112 |
113 |
114 |
115 |
116 | {loading && }
117 | {!loading && (
118 |
119 | {filteredChallenges.map((challenge) => {
120 | return (
121 |
127 | );
128 | })}
129 |
130 | )}
131 | >
132 | );
133 | }
134 |
--------------------------------------------------------------------------------
/frontend/src/pages/Challenges/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 | import chevronDown from '../../assets/chevron-down.svg';
4 |
5 | export const Alert = styled.form`
6 | color: white;
7 | text-align: center;
8 | margin-top: 3em;
9 | `;
10 |
11 | export const Section = styled.section`
12 | margin-top: 3%;
13 | display: flex;
14 | flex-wrap: wrap;
15 | max-width: 100vw;
16 | align-items: center;
17 | justify-content: center;
18 | `;
19 |
20 | export const Head = styled.div`
21 | display: flex;
22 | justify-content: space-between;
23 | align-items: center;
24 | border-bottom: 1px solid var(--quaternary);
25 | margin-top: 60px;
26 | padding: 0 80px;
27 | font-size: 18px;
28 |
29 | h1 {
30 | color: whitesmoke;
31 | ${media.lessThan('medium')`
32 | font-size: 30px;
33 | `}
34 | }
35 |
36 | ${media.lessThan('medium')`
37 | padding: 0 20px;
38 | `}
39 | `;
40 |
41 | export const Filters = styled.form`
42 | color: white;
43 | display: flex;
44 | `;
45 |
46 | export const InputGroup = styled.div`
47 | margin: 0 0 0 14px;
48 |
49 | label {
50 | padding-left: 4px;
51 | font-size: 14px;
52 | font-weight: bold;
53 | display: block;
54 | }
55 | `;
56 |
57 | export const Select = styled.div`
58 | padding-right: 20px;
59 | height: 34px;
60 | overflow: hidden;
61 | background: url(${chevronDown}) no-repeat right var(--primary);
62 |
63 | select {
64 | width: 120%;
65 | padding-right: 20px;
66 | background: transparent;
67 | padding: 5px;
68 | font-size: 16px;
69 | line-height: 1;
70 | border: 0;
71 | border-radius: 0;
72 | height: 34px;
73 | -webkit-appearance: none;
74 | -webkit-user-select: none;
75 | -moz-user-select: none;
76 | -ms-user-select: none;
77 | color: white;
78 | }
79 |
80 | option {
81 | background-color: var(--primary);
82 | border: 0;
83 | }
84 | `;
85 |
--------------------------------------------------------------------------------
/frontend/src/pages/ConstructPage/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import pageInConstruction from '../../assets/page-under-construction.png';
4 | import Header from '../../components/Header';
5 |
6 | function ConstructPage() {
7 | return (
8 | <>
9 |
10 |
19 |
24 |
Pagina em Construção
25 |
26 | >
27 | );
28 | }
29 |
30 | export default ConstructPage;
31 |
--------------------------------------------------------------------------------
/frontend/src/pages/Dashboard/index.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 |
3 | import DashboardDefault from '../../components/DashboardDefault';
4 | import StatusCard from '../../components/StatusCard';
5 | import { StatusCardWrapper, Title, Container } from './styled';
6 | import { ChallengeCard } from '../../components/ChallengeCard/styled';
7 |
8 | const fakeData = {
9 | complete: 5,
10 | inProgress: 2,
11 | };
12 |
13 | function Dashboard() {
14 | const [statusCount, setStatusCount] = useState({});
15 |
16 | useEffect(() => {
17 | setStatusCount(fakeData);
18 | }, []);
19 |
20 | return (
21 |
22 |
23 |
24 |
29 |
34 |
35 | #WeeklyDevChallenge
36 |
37 |
38 |
39 | );
40 | }
41 |
42 | export default Dashboard;
43 |
--------------------------------------------------------------------------------
/frontend/src/pages/Dashboard/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | export const Container = styled.div`
5 | padding: 0px 80px 0 80px;
6 |
7 | ${media.between('medium', 'large')`
8 | padding: 0px 60px 0 60px;
9 | `}
10 |
11 | ${media.lessThan('medium')`
12 | padding: 0px 20px 0 20px;
13 | `}
14 | `;
15 |
16 | export const StatusCardWrapper = styled.div`
17 | display: flex;
18 | justify-content: space-between;
19 | margin-top: 30px;
20 | margin-bottom: 50px;
21 |
22 | ${media.greaterThan('large')`
23 | justify-content: space-around;
24 | `}
25 | `;
26 |
27 | export const Title = styled.h2`
28 | margin-bottom: 20px;
29 | `;
30 |
--------------------------------------------------------------------------------
/frontend/src/pages/Detail/index.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { useParams } from 'react-router-dom';
3 | import { faCheck } from '@fortawesome/free-solid-svg-icons';
4 | import AwesomeSlider from 'react-awesome-slider';
5 | import 'react-awesome-slider/dist/styles.css';
6 | import api from '../../services/api';
7 | import DevCard from '../../components/DevCard';
8 |
9 | import * as S from './styled';
10 | import Header from '../../components/Header';
11 |
12 | const includes = [
13 | {
14 | id: 1,
15 | instruction:
16 | 'Readme com instruções de requisitos e as rotas da aplicação',
17 | },
18 | {
19 | id: 2,
20 | instruction: 'Imagens para adicionar no projeto',
21 | },
22 | {
23 | id: 3,
24 | instruction: 'Modelo como design para utilizar como referência',
25 | },
26 | {
27 | id: 4,
28 | instruction: 'Arquivo contendo o texto que será utilizado',
29 | },
30 | ];
31 |
32 | const starts = [
33 | {
34 | id: 1,
35 | steps: 'Clone o projeto com o código inicial',
36 | },
37 | {
38 | id: 2,
39 | steps: 'Leia as instruções disponíveis no readme',
40 | },
41 | {
42 | id: 3,
43 | steps: 'Inicie o desenvolvimento!',
44 | },
45 | {
46 | id: 4,
47 | steps: 'Compartilhe seus resultados com a comunidade',
48 | },
49 | ];
50 |
51 | const colorMatch = {
52 | beginner: 'nephritis',
53 | intermediate: 'pumpkin',
54 | advanced: 'pomegranate',
55 | Mobile: 'blue',
56 | Frontend: 'red',
57 | Backend: 'light-purple',
58 | };
59 |
60 | export default function Detail() {
61 | const [challenge, setChallenge] = useState({});
62 | const [techs, setTechs] = useState([]);
63 | const [dev, setDev] = useState({});
64 | const [images, setImages] = useState([]);
65 | const { id } = useParams();
66 |
67 | useEffect(() => {
68 | window.scrollTo(0, 0);
69 | async function loadChallenge() {
70 | const response = await api.get(`/challenges/${id}`);
71 | setChallenge(response.data);
72 | setDev(response.data.dev_id);
73 | setImages(response.data.images);
74 | setTechs(response.data.techs);
75 | }
76 |
77 | loadChallenge();
78 | }, [id]);
79 |
80 | return (
81 | <>
82 |
83 |
84 |
85 |
86 |
87 | {challenge.name}
88 |
89 |
90 |
91 |
92 | {challenge.level}
93 |
94 |
95 | {challenge.type}
96 |
97 | {techs[0]?.split(', ').map((item, idx) => (
98 | {item}
99 | ))}
100 |
101 |
102 |
103 | {challenge.description}
104 |
105 |
106 |
112 | Iniciar desafio
113 |
114 |
115 |
116 |
117 | {images.map((image) => (
118 |
119 |
124 |
125 | ))}
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | Sobre o desafio
134 | Seu desafio é {challenge.brief}.
135 |
136 |
137 |
138 | O que está incluso?
139 |
140 | {challenge.type === 'Backend' ? (
141 |
142 | Readme com
143 | instruções de requisitos e as rotas da
144 | aplicação
145 |
146 | ) : (
147 | <>
148 | {includes.map((include) => (
149 |
150 | {' '}
151 | {include.instruction}
152 |
153 | ))}
154 | >
155 | )}
156 |
157 |
158 | Como iniciar?
159 | {starts.map((start) => (
160 |
161 | {start.id} -
162 | {start.steps}
163 |
164 | ))}
165 |
166 |
167 |
168 |
175 |
176 |
177 | >
178 | );
179 | }
180 |
--------------------------------------------------------------------------------
/frontend/src/pages/Detail/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3 | import media from 'styled-media-query';
4 |
5 | export const Container = styled.div`
6 | display: flex;
7 | flex-direction: column;
8 | justify-content: center;
9 | margin: 2%;
10 | flex: 1;
11 |
12 | ${media.lessThan('medium')`
13 | flex-direction: column;
14 | align-items: center;
15 | justify-content: center;
16 | width: 100%;
17 | margin: 0%;
18 | margin-top: 5%;
19 | `}
20 | `;
21 |
22 | export const Banner = styled.div`
23 | display: flex;
24 | align-items: center;
25 | justify-content: center;
26 | margin-top: 3em;
27 |
28 | ${media.lessThan('medium')`
29 | flex-wrap: wrap-reverse;
30 | `}
31 | `;
32 |
33 | export const LeftColumn = styled.div`
34 | display: flex;
35 | flex-direction: column;
36 | align-items: left;
37 | justify-content: center;
38 | width: 40%;
39 | text-align: left;
40 |
41 | ${media.lessThan('medium')`
42 | display: flex;
43 | width: 100%;
44 | margin-top: 8%;
45 | flex-direction: column;
46 | align-items: center;
47 | justify-content: center;
48 | margin-left: 0;
49 | margin-right: 0;
50 | `}
51 |
52 | ${media.lessThan('small')`
53 | margin-right: 4%;
54 | margin-left: 4%;
55 | `}
56 | `;
57 |
58 | export const InfosType = styled.div`
59 | filter: brightness(90%);
60 | width: 10em;
61 | border-radius: 20px;
62 | text-align: left;
63 | font-weight: bold;
64 | margin-left: 4%;
65 | margin-bottom: 1%;
66 | color: var(--purple);
67 | ${media.lessThan('medium')`
68 | text-align: center;
69 | margin: 0;
70 | width: 5em;
71 | `};
72 | `;
73 |
74 | export const TitleContainer = styled.div`
75 | margin-left: 4%;
76 | margin-bottom: 1%;
77 | h1 {
78 | color: var(--yellow);
79 | text-align: left;
80 | }
81 |
82 | ${media.lessThan('medium')`
83 | margin: 0;
84 | margin-top: 4%;
85 | text-align: center;
86 | `}
87 | `;
88 |
89 | export const ChallengeDescription = styled.div`
90 | color: var(--white);
91 | font-size: 1.2em;
92 | margin-left: 4%;
93 | margin-bottom: 4%;
94 |
95 | ${media.lessThan('medium')`
96 | text-align: left;
97 | margin-left: 0;
98 | margin-top: 2%;
99 | margin-bottom: 4%;
100 | `}
101 | `;
102 |
103 | export const Infos = styled.div`
104 | display: flex;
105 | flex-wrap: wrap;
106 | align-items: center;
107 | justify-content: left;
108 | padding: 0 4%;
109 | font-size: 14px;
110 | margin-bottom: 10px;
111 |
112 | ${media.lessThan('medium')`
113 | align-items: start;
114 | width: 100%;
115 | padding: 0;
116 | `}
117 | `;
118 |
119 | export const InfosLevel = styled.div`
120 | background-color: var(--${(props) => props.color});
121 | filter: brightness(90%);
122 | padding: 7px 15px;
123 | margin-right: 2%;
124 | margin-bottom: 2%;
125 | border-radius: 20px;
126 | text-align: center;
127 | font-weight: bold;
128 | color: var(--white);
129 | `;
130 |
131 | export const InfosTechs = styled.div`
132 | background-color: var(--quaternary);
133 | filter: brightness(90%);
134 | padding: 7px 15px;
135 | margin-right: 2%;
136 | margin-bottom: 2%;
137 | border-radius: 20px;
138 | text-align: center;
139 | font-weight: bold;
140 | color: var(--white);
141 | `;
142 |
143 | export const ChallengeLink = styled.a`
144 | color: var(--white);
145 | background-color: var(--purple);
146 | width: 15em;
147 | height: 3em;
148 | font-weight: bold;
149 | font-size: 20px;
150 | border-radius: 50px;
151 | cursor: pointer;
152 | transition: 0.3s;
153 | margin: 4%;
154 | text-decoration: none;
155 | display: flex;
156 | justify-content: center;
157 | align-items: center;
158 |
159 | &:hover {
160 | background-color: var(--dark-purple);
161 | }
162 |
163 | ${media.lessThan('medium')`
164 | margin: 0;
165 | margin-top: 5%;
166 | margin-bottom: 2%;
167 | `}
168 |
169 | ${media.between('large', 'huge')`
170 | width: 20em;
171 | `}
172 | `;
173 |
174 | export const Demo = styled.div`
175 | width: 47em;
176 | border-radius: 10px;
177 |
178 | .image {
179 | height: 100%;
180 | }
181 |
182 | .slider {
183 | width: 100%;
184 | height: 100%;
185 | }
186 |
187 | .awssld__wrapper {
188 | border-radius: 10px;
189 | }
190 |
191 | .awssld__bullets {
192 | bottom: 0;
193 | z-index: 9999;
194 | padding: 10px 0;
195 | transition: 0.4s;
196 | }
197 |
198 | .awssld__bullets:hover {
199 | background-color: rgba(0, 0, 0, 0.3);
200 | }
201 |
202 | .awssld__bullets button {
203 | border: 3px solid var(--yellow);
204 | background-color: rgba(0, 0, 0, 0);
205 | }
206 |
207 | .awssld__bullets .awssld__bullets--active {
208 | background-color: var(--yellow);
209 | }
210 |
211 | .image {
212 | height: 100%;
213 | width: 100%;
214 | }
215 |
216 | ${media.lessThan('medium')`
217 | width: 90%;
218 | height: 100%;
219 | margin-bottom: 20px;
220 | `}
221 | `;
222 |
223 | export const FlexContainer = styled.div`
224 | display: flex;
225 | flex-direction: column;
226 | align-items: center;
227 |
228 | ${media.lessThan('medium')`
229 | align-items: center;
230 | justify-content: center;
231 | max-width: 100%;
232 | `}
233 | `;
234 |
235 | export const Content = styled.div`
236 | margin-top: 3%;
237 | `;
238 |
239 | export const ChallengeAbout = styled.div`
240 | width: 100%;
241 | margin-top: 5%;
242 | margin-bottom: 4%;
243 | text-align: left;
244 |
245 | h1 {
246 | color: var(--purple);
247 | font-size: 1.6em;
248 | }
249 |
250 | p {
251 | margin-top: 1%;
252 | color: var(--white);
253 | }
254 |
255 | ${media.lessThan('medium')`
256 | align-items: center;
257 | justify-content: center;
258 | margin-left: 4%;
259 | margin-right: 4%;
260 | max-width: 95%;
261 | `}
262 | `;
263 |
264 | export const ChallengeContainer = styled.div`
265 | width: 100%;
266 | display: flex;
267 | align-items: center;
268 | justify-content: center;
269 | line-height: 1.5em;
270 | margin-bottom: 4%;
271 | p {
272 | color: var(--white);
273 | }
274 |
275 | ${media.lessThan('medium')`
276 | text-align: left;
277 | flex-wrap: wrap;
278 | `}
279 | `;
280 |
281 | export const ChallengeInclude = styled.div`
282 | display: flex;
283 | margin-right: 8%;
284 | flex-direction: column;
285 |
286 | h3 {
287 | color: var(--purple);
288 | margin-top: 0.3em;
289 | padding: 0.2em;
290 | font-size: 1.6em;
291 | }
292 |
293 | span {
294 | color: var(--white);
295 | padding: 0.2em;
296 | display: block;
297 | }
298 |
299 | ${media.lessThan('medium')`
300 | margin-right: 0;
301 | `}
302 |
303 | ${media.lessThan('small')`
304 | margin-right: 4%;
305 | margin-left: 4%;
306 | `}
307 | `;
308 |
309 | export const Icon = styled(FontAwesomeIcon)`
310 | color: var(--green);
311 | `;
312 |
313 | export const ChallengeStart = styled.div`
314 | display: flex;
315 | flex-direction: column;
316 |
317 | h3 {
318 | color: var(--purple);
319 | padding: 0.2em;
320 | margin-top: 0.3em;
321 | font-size: 1.6em;
322 | }
323 |
324 | p {
325 | color: var(--white);
326 | padding: 0.2em;
327 | }
328 |
329 | span {
330 | color: var(--yellow);
331 | font-weight: bold;
332 | margin: 0;
333 | padding: 0;
334 | }
335 |
336 | ${media.lessThan('small')`
337 | margin-right: 4%;
338 | margin-left: 4%;
339 | `}
340 | `;
341 |
--------------------------------------------------------------------------------
/frontend/src/pages/Devs/index.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from 'react';
2 | import {
3 | faLightbulb,
4 | faCodeBranch,
5 | faComment,
6 | } from '@fortawesome/free-solid-svg-icons';
7 | // import { Link } from 'react-router-dom';
8 |
9 | import * as S from './styled';
10 |
11 | import api from '../../services/api';
12 |
13 | import DevCard from '../../components/DevCard';
14 | import Header from '../../components/Header';
15 |
16 | export default function Challenges() {
17 | const [devs, setDevs] = useState([]);
18 | const [loading, setLoading] = useState(true);
19 |
20 | useEffect(() => {
21 | async function loadChallenges() {
22 | const response = await api.get('/devs');
23 | // console.log(response.data);
24 | setDevs(response.data);
25 |
26 | setLoading(false);
27 | }
28 |
29 | loadChallenges();
30 | }, []);
31 |
32 | return (
33 | <>
34 |
35 |
36 |
37 |
43 |
44 |
48 |
49 |
50 | Submeter
51 |
52 | novo desafio
53 |
54 |
55 |
56 |
62 |
63 |
67 |
68 | Participar
69 |
70 | da comunidade
71 |
72 |
73 |
74 |
80 |
81 |
85 |
86 | Contribuir
87 |
88 | open source
89 |
90 |
91 |
92 |
93 | {!loading && (
94 |
95 | Últimas contribuições
96 |
97 | {devs.map((dev) => (
98 |
106 | ))}
107 |
108 |
109 | )}
110 |
111 | >
112 | );
113 | }
114 |
--------------------------------------------------------------------------------
/frontend/src/pages/Devs/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4 |
5 | export const Container = styled.div`
6 | display: flex;
7 | flex-direction: column;
8 | justify-content: center;
9 | margin: 6%;
10 | flex: 1 1;
11 |
12 | ${media.lessThan('medium')`
13 | flex-direction: column;
14 | align-items: center;
15 | justify-content: center;
16 | width: 100%;
17 | margin: 0%;
18 | margin-top: 5%;
19 | `}
20 | `;
21 |
22 | export const OptionsContainer = styled.div`
23 | display: flex;
24 | flex-direction: row;
25 | flex-wrap: wrap;
26 | align-items: center;
27 | justify-content: center;
28 | a {
29 | text-decoration: none;
30 | }
31 | `;
32 |
33 | export const Option = styled.div`
34 | width: 300px;
35 | height: 300px;
36 |
37 | background-color: var(--secondary);
38 |
39 | margin: 20px;
40 | border-radius: 10px;
41 |
42 | cursor: pointer;
43 |
44 | display: flex;
45 | flex-direction: column;
46 | flex-wrap: wrap;
47 | align-items: center;
48 | justify-content: center;
49 |
50 | transition: .25s;
51 |
52 | &:hover {
53 | transform: scale(1.05);
54 | background-color: var(--dark-hover);
55 | }
56 | `;
57 |
58 | export const OptionIcon = styled(FontAwesomeIcon)`
59 | color: var(--yellow) !important;
60 | font-size: 60px !important;
61 | height: 60px;
62 | `;
63 |
64 | export const OptionTitle = styled.h2`
65 | color: var(--white);
66 | margin-top: 20px;
67 | text-align: center;
68 | `;
69 |
70 | export const Help = styled.div`
71 | display: flex;
72 | flex-direction: column;
73 | justify-content: center;
74 | align-items: center;
75 |
76 | h3 {
77 | color: var(--white);
78 | font-size: 18px;
79 | font-weight: normal;
80 | margin-bottom: 0.5em;
81 | }
82 | `;
83 |
84 | export const DevsContainer = styled.div`
85 | margin-top: 4em;
86 | color: var(--white);
87 |
88 | display: flex;
89 | flex-direction: column;
90 | align-items: center;
91 |
92 | >h1 {
93 | margin-bottom: 1em;
94 | }
95 | `;
96 |
97 | export const Devs = styled.div`
98 | display: flex;
99 | flex-direction: row;
100 |
101 | justify-content: space-evenly;
102 | flex-wrap: wrap;
103 |
104 | > div {
105 | margin-bottom: 2em;
106 | }
107 | `;
108 |
--------------------------------------------------------------------------------
/frontend/src/pages/Home/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import CategoriesList from '../../components/CategoriesList';
3 | import Newsletter from '../../components/Newsletter';
4 | import Steps from '../../components/Steps';
5 | import Banner from '../../components/Banner';
6 | import Header from '../../components/Header';
7 |
8 | export default function Home() {
9 | return (
10 | <>
11 |
12 |
13 |
14 |
15 |
16 | >
17 | );
18 | }
19 |
--------------------------------------------------------------------------------
/frontend/src/pages/MyChallenges/index.js:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 |
3 | import DashboardDefault from '../../components/DashboardDefault';
4 | import { ProgressBar } from '../../components/ChallengeCard/styled';
5 | import ChallengeCard from '../../components/ChallengeCard';
6 |
7 | import { Title, Section, Container } from './styled';
8 |
9 | const fakeData = {
10 | inProgress: [
11 | {
12 | techs: ['CSS, React Native'],
13 | images: [
14 | 'https://i.imgur.com/nAsuQSs.png',
15 | 'https://i.imgur.com/A9sWFtn.png',
16 | ],
17 | _id: '5ec1cd5b9cd83622b185db7f',
18 | type: 'Mobile',
19 | name: 'Fisiotherapp',
20 | description: 'Ajude pacientes com exercícios de fisioterapia!',
21 | level: 'beginner',
22 | background: 'https://i.imgur.com/4FgywHQ.png',
23 | github_url: 'https://github.com/Lorenalgm/fisiotheapp',
24 | brief:
25 | 'criar um aplicativo em React Native para ajudar pessoas com exercícios de fisioterapia',
26 | dev_id: '5ec31e81e8051f63faefdf5e',
27 | createdAt: '2020-05-17T23:48:43.265Z',
28 | updatedAt: '2020-08-09T00:31:57.252Z',
29 | __v: 0,
30 | },
31 | ],
32 | complete: [
33 | {
34 | techs: ['CSS, React Native'],
35 | images: [
36 | 'https://i.imgur.com/nAsuQSs.png',
37 | 'https://i.imgur.com/A9sWFtn.png',
38 | ],
39 | _id: '5ec1cd5b9cd83622b185db7f',
40 | type: 'Mobile',
41 | name: 'Fisiotherapp',
42 | description: 'Ajude pacientes com exercícios de fisioterapia!',
43 | level: 'beginner',
44 | background: 'https://i.imgur.com/4FgywHQ.png',
45 | github_url: 'https://github.com/Lorenalgm/fisiotheapp',
46 | brief:
47 | 'criar um aplicativo em React Native para ajudar pessoas com exercícios de fisioterapia',
48 | dev_id: '5ec31e81e8051f63faefdf5e',
49 | createdAt: '2020-05-17T23:48:43.265Z',
50 | updatedAt: '2020-08-09T00:31:57.252Z',
51 | __v: 0,
52 | },
53 | ],
54 | };
55 |
56 | function MyChallenges() {
57 | const [challengesList, setChallengesList] = useState({});
58 |
59 | useEffect(() => {
60 | setChallengesList(fakeData);
61 | }, []);
62 |
63 | return (
64 |
65 |
66 | Em andamento
67 |
68 | {challengesList.inProgress?.map((challenge) => (
69 |
76 |
77 |
78 | ))}
79 |
80 |
81 | Concluídos
82 |
83 |
84 | {challengesList.complete?.map((challenge) => (
85 |
92 |
93 |
94 | ))}
95 |
96 |
97 |
98 | );
99 | }
100 |
101 | export default MyChallenges;
102 |
--------------------------------------------------------------------------------
/frontend/src/pages/MyChallenges/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | export const Container = styled.div`
5 | padding: 0px 80px 0 80px;
6 |
7 | ${media.between('medium', 'large')`
8 | padding: 0px 60px 0 60px;
9 | `}
10 | `;
11 |
12 | export const Title = styled.h2`
13 | margin-bottom: 20px;
14 | `;
15 |
16 | export const Section = styled.section`
17 | margin-top: 3%;
18 | display: flex;
19 | flex-wrap: wrap;
20 | max-width: 100vw;
21 | `;
22 |
--------------------------------------------------------------------------------
/frontend/src/pages/Submit/index.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { FiXCircle } from 'react-icons/fi';
3 |
4 | import * as S from './styled';
5 | import Header from '../../components/Header';
6 |
7 | const levels = [
8 | { id: 1, title: 'iniciante' },
9 | { id: 2, title: 'intermediário' },
10 | { id: 3, title: 'avançado' },
11 | ];
12 | const categories = [
13 | { id: 1, title: 'Frontend' },
14 | { id: 2, title: 'Backend' },
15 | { id: 3, title: 'Mobile' },
16 | ];
17 |
18 | const linkVerify = /^https:\/\/[A-z]/;
19 |
20 | export default function Submit() {
21 | const [title, setTitle] = useState('');
22 | const [level, setLevel] = useState('iniciante');
23 | const [category, setCategory] = useState('');
24 | const [description, setDescription] = useState('');
25 | const [languages, setLanguages] = useState('');
26 | const [link, setLink] = useState('');
27 | const [imageLink, setImageLink] = useState([]);
28 | const [imageInput, setImageInput] = useState('');
29 |
30 | function set(data) {
31 | let newString = '';
32 | if (category.includes(data)) {
33 | newString = category.replace(data, '');
34 | } else {
35 | newString = category.concat(` ${data}`);
36 | }
37 | setCategory(newString.trim());
38 | }
39 |
40 | async function addLink() {
41 | console.log(linkVerify.test(imageInput));
42 | if (imageInput !== '' && linkVerify.test(imageInput)) {
43 | await fetch(`${imageInput}`).then((response) => {
44 | if (response.ok) {
45 | setImageLink([...imageLink, imageInput]);
46 | setImageInput('');
47 | }
48 | });
49 | }
50 | }
51 |
52 | function removeImageItem(index) {
53 | const updatedLinkImages = imageLink.filter((item, i) => i !== index);
54 | setImageLink(updatedLinkImages);
55 | }
56 |
57 | function submitForm() {}
58 |
59 | function clearForm() {
60 | setCategory('');
61 | setDescription('');
62 | setTitle('');
63 | setLink('');
64 | setImageLink([]);
65 | setImageInput('');
66 | }
67 |
68 | return (
69 | <>
70 |
71 |
72 |
73 | Submissão de desafios
74 |
75 |
76 | Categoria
77 |
78 | {categories.map((categoryItem) => (
79 | set(categoryItem.title)}
85 | key={categoryItem.id}
86 | >
87 | {categoryItem.title}
88 |
89 | ))}
90 |
91 |
92 |
93 | Nível
94 |
95 | {levels.map((levelItem) => (
96 |
100 | setLevel(levelItem.title)
101 | }
102 | key={levelItem.id}
103 | >
104 | {levelItem.title}
105 |
106 | ))}
107 |
108 |
109 |
110 | Título
111 | setTitle(e.target.value)}
115 | />
116 |
117 |
118 | Descrição
119 | setDescription(e.target.value)}
124 | />
125 |
126 |
127 |
128 | Imagens
129 |
130 | setImageInput(e.target.value)}
134 | onKeyPress={(e) => {
135 | if (e.key === 'Enter') {
136 | addLink();
137 | }
138 | }}
139 | required
140 | value={imageInput}
141 | />
142 |
143 |
144 | Add Image +
145 |
146 |
147 |
148 | {imageLink.map((linkItem, i) => (
149 |
150 |
151 | removeImageItem(i)}
154 | >
155 |
156 |
157 |
158 | ))}
159 |
160 |
161 |
162 |
163 | Linguagens
164 | setLanguages(e.target.value)}
168 | />
169 |
170 |
171 |
172 | Informe o link do desafio no github
173 |
174 | setLink(e.target.value)}
178 | />
179 |
180 |
181 |
182 | Limpar
183 |
184 |
185 | Enviar
186 |
187 |
188 |
189 |
190 |
191 | >
192 | );
193 | }
194 |
--------------------------------------------------------------------------------
/frontend/src/pages/Submit/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | export const Section = styled.section`
5 | margin-top: 3%;
6 | margin-bottom: 10%;
7 | display: flex;
8 | flex-wrap: wrap;
9 | max-width: 100vw;
10 | align-items: center;
11 | justify-content: center;
12 |
13 | ${media.lessThan('medium')`
14 | margin-top: 15%;
15 | margin-bottom: 15%;
16 | `}
17 | `;
18 |
19 | export const Container = styled.div`
20 | background-color: var(--secondary);
21 | width: 50%;
22 | max-width: 800px;
23 | height: 50%;
24 | padding: 36px 48px 31px;
25 | border-radius: 10px;
26 |
27 | ${media.between('medium', 'large')`
28 | width: 70%;
29 | height: 70%;
30 | `}
31 |
32 | ${media.between('small', 'medium')`
33 | width: 80%;
34 | height: 80%;
35 | `}
36 |
37 | ${media.lessThan('small')`
38 | width: 80%;
39 | padding: 20px 28px 18px;
40 | `}
41 | `;
42 |
43 | export const Title = styled.p`
44 | color: var(--white);
45 | font-size: 20px;
46 | margin-bottom: 20px;
47 | font-weight: bold;
48 | `;
49 |
50 | export const Form = styled.div`
51 | width: 100%;
52 | margin: 0 0 15px;
53 | `;
54 | export const Field = styled.div`
55 | display: flex;
56 | flex-direction: column;
57 | justify-content: space-between;
58 | margin-bottom: 15px;
59 |
60 | ${media.lessThan('small')`
61 | flex-direction: column;
62 | align-items: flex-start;
63 | `}
64 | `;
65 | export const Label = styled.p`
66 | margin-bottom: 7px;
67 | color: var(--quaternary);
68 | font-size: 18px;
69 | font-weight: bold;
70 | `;
71 | export const Input = styled.input`
72 | width: 100%;
73 | background: var(--quaternary);
74 | height: 40px;
75 | display: flex;
76 | align-items: center;
77 | color: white;
78 | font-size: 14px;
79 | padding: 0 15px;
80 | border-radius: 40px;
81 |
82 | & + Input {
83 | margin-top: 10px;
84 | }
85 |
86 | ${media.lessThan('small')`
87 | width: 100%;
88 | `}
89 | `;
90 |
91 | export const Textarea = styled.textarea`
92 | width: 100%;
93 | min-height: 200px;
94 | background: var(--quaternary);
95 | padding: 10px 15px;
96 | font-size: 16px;
97 | color: white;
98 | border-radius: 20px;
99 |
100 | resize: vertical;
101 | `;
102 |
103 | export const Select = styled.div`
104 | display: flex;
105 | height: 40px;
106 |
107 | ${media.lessThan('small')`
108 | margin-bottom: 60px;
109 | width: 100%;
110 | flex-direction: column;
111 | `}
112 | `;
113 |
114 | const colorMatch = {
115 | category: [
116 | 'var(--quaternary)',
117 | 'var(--red)',
118 | 'var(--light-purple)',
119 | 'var(--blue)',
120 | ],
121 | level: [
122 | 'var(--quaternary)',
123 | 'var(--nephritis)',
124 | 'var(--pumpkin)',
125 | 'var(--pomegranate)',
126 | ],
127 | };
128 |
129 | export const Item = styled.button`
130 | width: 100%;
131 | padding: 5px 10px;
132 |
133 | text-transform: uppercase;
134 | color: var(--tertiary);
135 | font-size: 12px;
136 | font-weight: bold;
137 |
138 | cursor: pointer;
139 |
140 | &:first-child {
141 | background-color: ${(props) =>
142 | props.selected
143 | ? colorMatch[props.type][1]
144 | : colorMatch[props.type][0]};
145 | border-top-left-radius: 25px;
146 | border-bottom-left-radius: 25px;
147 | }
148 |
149 | &:nth-child(2) {
150 | background-color: ${(props) =>
151 | props.selected
152 | ? colorMatch[props.type][2]
153 | : colorMatch[props.type][0]};
154 | border-style: none solid;
155 | }
156 |
157 | &:last-child {
158 | background-color: ${(props) =>
159 | props.selected
160 | ? colorMatch[props.type][3]
161 | : colorMatch[props.type][0]};
162 | border-top-right-radius: 25px;
163 | border-bottom-right-radius: 25px;
164 | }
165 |
166 | ${media.lessThan('small')`
167 | padding: 10px 0;
168 | &:first-child {
169 | border-top-right-radius: 20px;
170 | border-top-left-radius: 20px;
171 | border-bottom-left-radius: 0;
172 | }
173 | &:nth-child(2) {
174 | border-style: solid none;
175 | }
176 | &:last-child {
177 | border-top-right-radius: 0;
178 | border-bottom-right-radius: 20px;
179 | border-bottom-left-radius: 20px;
180 | }
181 | `}
182 | `;
183 |
184 | export const Actions = styled.div`
185 | display: flex;
186 | width: 100%;
187 | margin-top: 30px;
188 | align-items: center;
189 | justify-content: space-around;
190 | `;
191 |
192 | export const Button = styled.button`
193 | padding: 10px 15px;
194 | border-radius: 40px;
195 | font-size: 18px;
196 | cursor: pointer;
197 |
198 | background-color: ${(props) =>
199 | props.type === 'submit' ? 'var(--yellow)' : 'var(--quaternary)'};
200 | `;
201 |
202 | export const AddLinkButton = styled.button`
203 | background-color: rgba(0, 0, 0, 0);
204 | cursor: pointer;
205 | margin-top: 10px;
206 | align-self: flex-end;
207 | padding: 0 20px;
208 | font-weight: bold;
209 |
210 | color: var(--quaternary);
211 | `;
212 |
213 | export const ImagePreview = styled.img`
214 | //width: 50px;
215 | height: 50px;
216 | border-radius: 10px;
217 | `;
218 |
219 | export const PreviewList = styled.ul`
220 | display: flex;
221 | flex-wrap: wrap;
222 | list-style: none;
223 | max-width: 100%;
224 |
225 | li {
226 | width: 50px;
227 | margin: 10px 30px;
228 | display: flex;
229 | align-items: center;
230 | justify-content: space-between;
231 | }
232 |
233 | button {
234 | position: relative;
235 | background-color: rgba(0, 0, 0, 0);
236 | color: var(--red);
237 | top: 25px;
238 | right: 15px;
239 | cursor: pointer;
240 | }
241 | `;
242 |
--------------------------------------------------------------------------------
/frontend/src/pages/ToDoChallenge/index.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 |
3 | import { HeaderImg, Container, ToDoDiv, AddToDo, Content } from './styled';
4 | import DashboardDefault from '../../components/DashboardDefault';
5 |
6 | function ToDoChallenge() {
7 | const [todos, setTodos] = useState([
8 | {
9 | id: 2,
10 | title: 'teste',
11 | checked: 1,
12 | subtodo: [{ id: 1, title: 'teste', checked: 1, subtodo: [] }],
13 | },
14 | ]);
15 |
16 | function renameTodo(todo, value) {
17 | return { ...todo, title: value };
18 | }
19 |
20 | function changeChecked(todo, value) {
21 | const newValue = value === '1' ? 0 : 1;
22 | console.log(newValue);
23 | return { ...todo, checked: newValue };
24 | }
25 |
26 | function createTodo(todo) {
27 | const newValue = { title: '', id: '', checked: 0, subtodo: [] };
28 | return { ...todo, newValue };
29 | }
30 |
31 | const modifiers = {
32 | rename: renameTodo,
33 | check: changeChecked,
34 | add: createTodo,
35 | };
36 |
37 | function findToDo(toDoList, id, modify, value) {
38 | const newTodoList = toDoList.map((todo) => {
39 | if (`${todo.id}` === id) {
40 | const todoItem = modifiers[modify](todo, value);
41 | return todoItem;
42 | }
43 | if (todo.subtodo.length !== 0) {
44 | const subtodos = findToDo(todo.subtodo, id, modify, value);
45 | return { ...todo, subtodo: subtodos };
46 | }
47 | return todo;
48 | });
49 | return newTodoList;
50 | }
51 |
52 | function toggleCheckedStatus(e, modify) {
53 | const { id, value } = e.target;
54 | const newTodoList = findToDo(todos, id, modify, value);
55 | setTodos(newTodoList);
56 | console.log(newTodoList);
57 | }
58 |
59 | function renderToDo(todo) {
60 | return (
61 | <>
62 |
63 | toggleCheckedStatus(e, 'check')}
69 | value={todo.checked}
70 | />
71 | {todo.title}
72 | toggleCheckedStatus(e, 'rename')}
77 | />
78 |
79 | {todo.subtodo.map((newTodo) => renderToDo(newTodo))}
80 |
81 | {todo.subtodo.length === 0 && (
82 | toggleCheckedStatus(e)}
85 | >
86 | + Add To-Do
87 |
88 | )}
89 | >
90 | );
91 | }
92 |
93 | return (
94 |
95 |
96 |
97 | Titulo
98 |
99 | {todos.map((todo) => renderToDo(todo))}
100 | toggleCheckedStatus(e)}>
101 | + Add To-Do
102 |
103 |
104 |
105 |
106 | );
107 | }
108 |
109 | export default ToDoChallenge;
110 |
--------------------------------------------------------------------------------
/frontend/src/pages/ToDoChallenge/styled.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 | import media from 'styled-media-query';
3 |
4 | export const Container = styled.div`
5 | padding: 40px 100px 0 100px;
6 |
7 | ${media.between('medium', 'large')`
8 | padding: 40px 60px 0 60px;
9 | `}
10 | `;
11 |
12 | export const HeaderImg = styled.div`
13 | width: 100%;
14 | height: 200px;
15 | background: ${(props) => `url(${props.img}) no-repeat`};
16 | background-size: cover;
17 | margin-top: 20px;
18 | `;
19 |
20 | export const Content = styled.div`
21 | padding: 30px;
22 | `;
23 | export const ToDoDiv = styled.div`
24 | display: flex;
25 | padding-left: 30px;
26 | padding-top: 10px;
27 | width: 100%;
28 | display: block;
29 |
30 | input[type='checkbox'] {
31 | display: none;
32 | }
33 |
34 | input[type='text'] {
35 | background: var(--primary);
36 | color: var(--quinary);
37 | font-size: 18px;
38 | width: 80%;
39 | }
40 |
41 | label {
42 | cursor: pointer;
43 | font-size: 0;
44 | }
45 |
46 | input + label::before {
47 | border: 1px solid var(--quinary);
48 | content: '\\00a0';
49 | display: inline-block;
50 | font: 16px/1em sans-serif;
51 | height: 16px;
52 | margin: 0 10px 0 0;
53 | padding: 0;
54 | vertical-align: top;
55 | width: 16px;
56 | }
57 |
58 | input[type='checkbox']:checked + label:before {
59 | color: var(--quinary);
60 | content: '\\2713';
61 | text-align: center;
62 | }
63 |
64 | input[type='checkbox']:checked + label:after {
65 | font-weight: bold;
66 | }
67 | `;
68 |
69 | export const AddToDo = styled.button`
70 | background: var(--primary);
71 | color: var(--quinary);
72 | opacity: 0;
73 | transition: 0.3s;
74 | padding-left: 30px;
75 |
76 | &:hover {
77 | opacity: 1;
78 | }
79 | `;
80 |
--------------------------------------------------------------------------------
/frontend/src/routes.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { BrowserRouter, Switch, Route, Redirect } from 'react-router-dom';
3 |
4 | import { ToastContainer } from 'react-toastify';
5 | import 'react-toastify/dist/ReactToastify.css';
6 | import Home from './pages/Home';
7 | import Challenges from './pages/Challenges';
8 | import Detail from './pages/Detail';
9 | import Devs from './pages/Devs';
10 | import Submit from './pages/Submit';
11 | import MyChallenges from './pages/MyChallenges';
12 | import Dashboard from './pages/Dashboard';
13 | import Footer from './components/Footer';
14 | import ToDoChallenge from './pages/ToDoChallenge';
15 |
16 | import { Container } from './styles/GlobalStyles';
17 | import ConstructPage from './pages/ConstructPage';
18 |
19 | const logged = false;
20 |
21 | const LoggedRoute = ({ component: Component, ...rest }) => (
22 |
25 | logged ? (
26 |
27 | ) : (
28 |
31 | )
32 | }
33 | />
34 | );
35 |
36 | function Routes() {
37 | return (
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
51 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | );
62 | }
63 |
64 | export default Routes;
65 |
--------------------------------------------------------------------------------
/frontend/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 &&
112 | contentType.indexOf('javascript') === -1)
113 | ) {
114 | // No service worker found. Probably a different app. Reload the page.
115 | navigator.serviceWorker.ready.then((registration) => {
116 | registration.unregister().then(() => {
117 | window.location.reload();
118 | });
119 | });
120 | } else {
121 | // Service worker found. Proceed as normal.
122 | registerValidSW(swUrl, config);
123 | }
124 | })
125 | .catch(() => {
126 | console.log(
127 | 'No internet connection found. App is running in offline mode.'
128 | );
129 | });
130 | }
131 |
132 | export function unregister() {
133 | if ('serviceWorker' in navigator) {
134 | navigator.serviceWorker.ready
135 | .then((registration) => {
136 | registration.unregister();
137 | })
138 | .catch((error) => {
139 | console.error(error.message);
140 | });
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/frontend/src/services/api.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | const api = axios.create({
4 | baseURL: process.env.REACT_APP_DEVCHALLENGE_API
5 | });
6 |
7 | export default api;
8 |
--------------------------------------------------------------------------------
/frontend/src/services/challenges.service.js:
--------------------------------------------------------------------------------
1 | import api from './api';
2 |
3 | export const getCategories = () =>
4 | api.get('categories').then(({ data }) => data);
5 |
--------------------------------------------------------------------------------
/frontend/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 |
--------------------------------------------------------------------------------
/frontend/src/styles/GlobalStyles.js:
--------------------------------------------------------------------------------
1 | import styled, { createGlobalStyle } from 'styled-components';
2 |
3 | export const GlobalStyles = createGlobalStyle`
4 | @font-face {
5 | font-family: FontAwesome;
6 | font-style: normal;
7 | font-weight: 400;
8 | src: url("/fonts/FontAwesome.ttf") format("truetype");
9 | }
10 |
11 | :root {
12 | /*main colors*/
13 | --yellow: #f4cf0a;
14 | --purple: #5c0d78;
15 |
16 |
17 | --white: #FFFFFF;
18 |
19 | --black: #110e0e;
20 | --dark-purple: #490861;
21 | --white-gray: #e3e3e3;
22 | --light-gray: #c1c1c1 ;
23 | --pale-gray: #333333;
24 | --dark-gray: #242020;
25 | --green: #adff2f;
26 |
27 | --nephritis: #27ae60;
28 | --pumpkin: #d35400;
29 | --pomegranate: #c0392b;
30 |
31 | --blue: #47ADE1;
32 | --red: #E63450;
33 | --light-purple: #D427D8;
34 |
35 | --primary: #0e0f10;
36 | --secondary: #191b1d;
37 | --tertiary: #1A1C1F;
38 |
39 | --quaternary: rgba(84, 84, 84, 0.75);
40 | --quinary: #858585;
41 | --senary: #828386;
42 |
43 | --dark-hover: #23272C;
44 | }
45 |
46 | * {
47 | margin: 0;
48 | padding: 0;
49 | outline: 0;
50 | box-sizing: border-box;
51 | }
52 |
53 | html {
54 | font-family: "Roboto", Arial, Helvetica, sans-serif;
55 | -webkit-font-smoothing: antialiased;
56 | -moz-osx-font-smoothing: grayscale;
57 | }
58 |
59 | html, body, #root {
60 | height: 100%;
61 | min-height: 100%;
62 |
63 | margin: 0 auto 0 auto;
64 | }
65 |
66 | body {
67 | background-color: var(--primary);
68 |
69 | ::-webkit-scrollbar-track {
70 | background-color: var(--dark-hover);
71 | }
72 | ::-webkit-scrollbar {
73 | width: 6px;
74 | background: none;
75 | }
76 | ::-webkit-scrollbar-thumb {
77 | background: var(--tertiary);
78 | border-radius: 3px;
79 | }
80 | }
81 |
82 | button,
83 | input,
84 | textarea {
85 | appearance: none;
86 | -moz-appearance: none;
87 | -webkit-appearance: none;
88 |
89 | border: none;
90 | }
91 |
92 | textarea {
93 | font-family: "Roboto", Arial, Helvetica, sans-serif;
94 | -webkit-font-smoothing: antialiased;
95 | -moz-osx-font-smoothing: grayscale;
96 | }
97 | `;
98 |
99 | export const Container = styled.main`
100 | min-height: calc(100vh - 100px);
101 | `;
102 |
--------------------------------------------------------------------------------
/frontend/src/utils/toast.js:
--------------------------------------------------------------------------------
1 | import { toast } from 'react-toastify';
2 |
3 | const messages = {
4 | error(msg) {
5 | return msg || 'Ocorreu um erro no processamento';
6 | },
7 | success(msg) {
8 | return msg || 'Sucesso';
9 | },
10 | };
11 |
12 | const ToastNotification = {
13 | notify: (method, msg) => {
14 | const methodStr = method;
15 | method = toast[method];
16 | method(messages[methodStr](msg));
17 | },
18 | };
19 |
20 | export default ToastNotification;
21 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "lockfileVersion": 1
3 | }
4 |
--------------------------------------------------------------------------------
/translations/README.cn.md:
--------------------------------------------------------------------------------
1 | [![Forks][forks-shield]][forks-url]
2 | [![Stargazers][stars-shield]][stars-url]
3 | [![Issues][issues-shield]][issues-url]
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
DevChallenge
12 |
13 |
14 | 开发人员可以通过该网站来提高其通过前端,后端和移动挑战的技能!
15 | 开发人员可以通过前端和后端挑战来提高技能的网站
16 |
17 |
18 | DevChallenge
19 |
20 |
21 | ## 指数
22 |
23 | - [Índice](#índice)
24 | - [Sobre o Projeto](#sobre-o-projeto)
25 | - [Demo:](#demo)
26 | - [Tecnologias:](#tecnologias)
27 | - [Como Utilizar](#como-utilizar)
28 | - [Como Contribuir](#como-contribuir)
29 | - [Requisitos](#requisitos)
30 | - [Instalar](#instalar)
31 | - [Comunidade](#comunidade)
32 |
33 | ## 关于该项目
34 | O DevChallenge 是一个旨在为开发人员的发展做出贡献,提供挑战以使他们能够练习,提高技能并创建投资组合的项目 :)
35 |
36 | ### 演示:
37 |
38 |
39 |
40 |
41 | ### 技术:
42 | - 后端: Nodejs
43 | - 前端: Reactjs
44 | - 数据库: MongoDB
45 |
46 | ## 如何使用
47 | 1 - 使用以下模板 DevChallenge 带有初始代码
48 | 2 - 阅读说明 readme.cn.md
49 | 3 - 开始编码!
50 | 4 - 与社区分享您的结果 :)
51 |
52 | 1 - 使用 DevChallenge template with the starter code
53 | 2 - 阅读说明书 readme.cn.md
54 | 3 - 开始编码!
55 | 4 - 与社区分享您的结果 :)
56 |
57 | ##如何贡献
58 | 您可以为该项目提供帮助:
59 | -建议和/或提出新的挑战:这些挑战将变为现实,并可以帮助所有开发人员实践
60 | -对网站进行改进和更正:您可以发送请求请求,以便所有开发人员都可以使用您的更改!
61 |
62 | 您可以通过提供新的挑战或改进网站来帮助
63 |
64 | ### 请求
65 | 1. Nodejs
66 |
67 | ### 安装
68 |
69 | 前端
70 |
71 | 1.做 下载 或从中克隆存储库 DevChallenge
72 | ```sh
73 | git clone git@github.com:Lorenalgm/DevChallenge.git
74 | ```
75 | 2. 在编辑器中打开项目.
76 | 3. 在您的终端中,安装必要的软件包
77 | ```sh
78 | yarn
79 | ```
80 | ou
81 | ```sh
82 | npm install
83 | ```
84 | 4. 节目! 现在,您可以转到前端文件夹并启动服务器:
85 | ```sh
86 | cd frontend
87 | ```
88 | ```sh
89 | yarn start
90 | ```
91 | 5. 打开浏览器! DevChallenge将在以下位置提供 http://localhost:3000/ :)
92 |
93 |
94 | 后端
95 |
96 | 后端在存储库中可用 DevChallengeAPI
97 |
98 |
99 | ## 社区
100 | 我们的目标是为开发人员的发展提供越来越多的帮助! 因此,我们在Discord上拥有专属的DevChallenge社区。 波拉? https://discord.gg/yvYXhGj
101 |
102 | 网站: https://www.devchallenge.com.br/
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | [forks-shield]: https://img.shields.io/github/forks/Lorenalgm/DevChallenge.svg?style=flat-square
114 | [forks-url]: https://github.com/Lorenalgm/DevChallenge/network/members
115 | [stars-shield]: https://img.shields.io/github/stars/Lorenalgm/DevChallenge.svg?style=flat-square
116 | [stars-url]: https://github.com/Lorenalgm/DevChallenge/stargazers
117 | [issues-shield]: https://img.shields.io/github/issues/Lorenalgm/DevChallenge.svg?style=flat-square
118 | [issues-url]: https://github.com/Lorenalgm/DevChallenge/issues
119 |
--------------------------------------------------------------------------------
/translations/README.de.md:
--------------------------------------------------------------------------------
1 | [![Forks][forks-shield]][forks-url]
2 | [![Stargazers][stars-shield]][stars-url]
3 | [![Issues][issues-shield]][issues-url]
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
DevChallenge
12 |
13 |
14 | Eine Webseite für Entwickler um ihre Fähigkeiten in der Frontend-, Backend- und Mobileentwicklung zu verbessern!
15 |
16 |
17 | DevChallenge
18 |
19 |
20 |
21 |
22 | ### _Read in [other languages](./translations)_
23 |
24 |
25 |
26 | [ ](./translations/README.pt_br.md)
27 | Nicht verfügbar
28 | [ ](./translations/README.de.md)
29 |
30 |
31 |
32 | ## Inhaltsverzeichnis
33 |
34 | - [Inhaltsverzeichnis](#inhaltsverzeichnis)
35 | - [Über das Projekt](#über-das-projekt)
36 | - [Demo](#demo)
37 | - [Technologien](#technologien)
38 | - [How to Use](#how-to-use)
39 | - [Mithelfen](#mithelfen)
40 | - [Voraussetzungen](#voraussetzungen)
41 | - [Installation](#installation)
42 | - [Community](#community)
43 |
44 | ## Über das Projekt
45 |
46 | DevChallenge ist ein Projekt um die Fähigkeiten von Entwicklern mit Challenges zum Üben zu verbessern und ihnen zu helfen ein Portfolio aufzubauen :)
47 |
48 | ### Demo
49 |
50 |
51 |
52 |
53 |
54 | ### Technologien
55 |
56 | - Backend: Nodejs
57 | - Frontend: Reactjs
58 | - Datenbank: MongoDB
59 |
60 | ## How to Use
61 |
62 | 1 - Such dir ein eine Vorlage von DevChallenge mit Beispiel-Code aus
63 | 2 - Lies die README.md für Anweisungen
64 | 3 - Fang an zu coden!
65 | 4 - Teile dein Ergebnis mit der Community :)
66 |
67 | ## Mithelfen
68 |
69 | Du kannst wie folgt beim Projekt mithelfen:
70 |
71 | - Vorschlagen und/oder erstellen von neuen Challenges: diese Challenges sind für alle verfügbar und können allen Entwicklern zum Üben dienen
72 | - Verbesserungen und Korrektungen an der Webseite: Du kannst einen Pull-Request mit deinen Änderungen machen!
73 |
74 | ### Voraussetzungen
75 |
76 | 1. Nodejs
77 |
78 | ### Installation
79 |
80 | Frontend
81 |
82 | 1. Lade das Projekt hier runter oder klone das Projekt
83 |
84 | ```sh
85 | git clone git@github.com:Lorenalgm/DevChallenge.git
86 | ```
87 |
88 | 2. Öffne das Projekt in deinem Editor.
89 | 3. Installiere die benötigten Dependencies über deine Konsole:
90 |
91 | ```sh
92 | yarn
93 | ```
94 |
95 | oder
96 |
97 | ```sh
98 | npm install
99 | ```
100 |
101 | 4. Jetzt kannst du den Frontend Ordner öffnen um den Server zu starten:
102 |
103 | ```sh
104 | cd frontend
105 | ```
106 |
107 | ```sh
108 | yarn start
109 | ```
110 |
111 | 5. Öffne deinen Browser! DevChallenge ist jetzt verfügbar unter http://localhost:3000/ :)
112 |
113 | Backend
114 |
115 | Das Backend-Projekt ist verfügbar unter: DevChallengeAPI
116 |
117 | ## Community
118 |
119 | Unser Ziel ist es Entwicklern bei ihrer persönlichen Entwicklung zu helfen! Das ist der Grund wieso wir auch eine exklusive DevChallenge community auf Discord haben. Du willst dabei sein? https://discord.gg/yvYXhGj
120 |
121 | Webseite: https://www.devchallenge.com.br/
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 | [forks-shield]: https://img.shields.io/github/forks/Lorenalgm/DevChallenge.svg?style=flat-square
133 | [forks-url]: https://github.com/Lorenalgm/DevChallenge/network/members
134 | [stars-shield]: https://img.shields.io/github/stars/Lorenalgm/DevChallenge.svg?style=flat-square
135 | [stars-url]: https://github.com/Lorenalgm/DevChallenge/stargazers
136 | [issues-shield]: https://img.shields.io/github/issues/Lorenalgm/DevChallenge.svg?style=flat-square
137 | [issues-url]: https://github.com/Lorenalgm/DevChallenge/issues
138 |
--------------------------------------------------------------------------------
/translations/README.es.md:
--------------------------------------------------------------------------------
1 | [![Forks][forks-shield]][forks-url]
2 | [![Stargazers][stars-shield]][stars-url]
3 | [![Issues][issues-shield]][issues-url]
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
DevChallenge
12 |
13 |
14 | Un sitio de desarrolladores para mejorar sus habilidades a través de front-end, back-end y desafíos móviles.
15 |
16 | DevChallenge
17 |
18 |
19 | # Traducciones
20 |
21 | | | Link |
22 | | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
23 | | | [Español](./translations/README.es.md) |
24 | | | [Português (Brasil)](../README.md) |
25 | | | [Deutsch](./README.de.md) |
26 |
27 |
28 | ## Índice
29 |
30 | * [Sobre el proyecto](#sobre-el-proyecto)
31 | * [Demo](#demo)
32 | * [Tecnología](#tecnología)
33 | * [Cómo utilizar](#como-utilizar)
34 | * [Cómo contribuir](#como-contribuir)
35 | * [Requisitos](#requisitos)
36 | * [Instalar](#instalar)
37 | * [Comunidad](#comunidad)
38 |
39 | ## Sobre el proyecto
40 | DevChallenge es un proyecto que tiene como objetivo contribuir a la evolución de los desarrolladores, proporcionar desafíos para que puedan practicar, mejorar sus habilidades y crear sus portafolios. :)
41 |
42 | ### Demo:
43 |
44 |
45 |
46 |
47 | ### Tecnología:
48 | - Backend: Nodejs
49 | - Frontend: Reactjs
50 | - Database: MongoDB
51 |
52 | ## Como utilizar
53 | 1 - Utilizar una plantilla de DevChallenge como código inicial
54 | 2 - Lee las instrucciones en readme.md
55 | 3 - ¡Inicia a hacer código!
56 | 4 - Comparta sus resultados con la comunidad :)
57 |
58 |
59 | ## Como contribuir
60 | Puedes ayudar con el proyecto:
61 | - Sugerir y/o crear nuevos retos: estos desafíos estarán disponibles y pueden ayudar a todos los desarrollares a practicar
62 | - Mejoras que contribuyen y corrigen al sitio: puede enviar una Pull Request para que su cambio esté disponible para todos los desarrolladores
63 |
64 |
65 | ### Requisitos
66 | 1. [Node.js](https://nodejs.org)
67 | 2. [Yarn](https://yarnpkg.com)
68 | 3. [Git](https://git-scm.com)
69 |
70 | ### Instalar
71 |
72 | Front-end
73 |
74 | 1. Descargar o clonar el repositorio DevChallenge
75 | ```sh
76 | git clone git@github.com:Lorenalgm/DevChallenge.git
77 | ```
78 | 2. Abrir el proyecto en su editor preferido.
79 | 3. En su terminal, instalar los paquetes necesarios:
80 | ```sh
81 | yarn
82 | ```
83 | o
84 | ```sh
85 | npm install
86 | ```
87 | 4. Listo! Ahora puede ir a la carpeta frontend y iniciar el servidor:
88 | ```sh
89 | cd frontend
90 | ```
91 | ```sh
92 | yarn start
93 | ```
94 | 5. Abre tu navegador! DevChallenge estará disponible en http://localhost:3000/ :)
95 |
96 |
97 | Back-end
98 |
99 | El backend está disponible en el siguiente repositorio: DevChallengeAPI
100 |
101 |
102 | ## Comunidad
103 | ¡Nuestra meta es ayudar más y más en la evolución de los desarrolladores!. Tenemos una exclusiva comunidad de DevChallenge en Discord. https://discord.gg/yvYXhGj
104 |
105 | Sitio web: https://www.devchallenge.com.br/
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | [forks-shield]: https://img.shields.io/github/forks/Lorenalgm/DevChallenge.svg?style=flat-square
117 | [forks-url]: https://github.com/Lorenalgm/DevChallenge/network/members
118 | [stars-shield]: https://img.shields.io/github/stars/Lorenalgm/DevChallenge.svg?style=flat-square
119 | [stars-url]: https://github.com/Lorenalgm/DevChallenge/stargazers
120 | [issues-shield]: https://img.shields.io/github/issues/Lorenalgm/DevChallenge.svg?style=flat-square
121 | [issues-url]: https://github.com/Lorenalgm/DevChallenge/issues
122 |
--------------------------------------------------------------------------------
/translations/README.it.md:
--------------------------------------------------------------------------------
1 | [![Forks][forks-shield]][forks-url]
2 | [![Stargazers][stars-shield]][stars-url]
3 | [![Issues][issues-shield]][issues-url]
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
DevChallenge
12 |
13 |
14 | Sito che consente agli sviluppatori di migliorare le proprie capacità grazie a sfide Front-end, Back-end e Mobile!
15 | Un sito web per gli sviluppatori per migliorare le proprie capacità facendo sfide front-end e back-end
16 |
17 |
18 | DevChallenge
19 |
20 |
21 | ## Indice
22 |
23 | - [Indice](#indice)
24 | - [Informazioni sul progetto](#sul-progetto)
25 | - [Demo:](#demo)
26 | - [Tecnologie:](#tecnologie)
27 | - [Come usare](#come-fare)
28 | - [Come contribuire](#come-contribuire)
29 | - [Requisiti](#requisiti)
30 | - [Installare](#installare)
31 | - [Community](#community)
32 |
33 | ## Sul progetto
34 | DevChallenge è un progetto che contribuisce all'evoluzione degli sviluppatori, offrendo sfide da mettere in pratica, migliorare le loro abilità e creare il loro portfolio 😄
35 |
36 | ### Demo:
37 |
38 |
39 |
40 |
41 | ### Tecnologie:
42 | - Backend: Nodejs
43 | - Frontend: Reactjs
44 | - Banca dati: MongoDB
45 |
46 | ## come-fare
47 | 1 - Utilizza un modello DevChallenge con il codice iniziale
48 | 2 - Leggi le istruzioni README.md
49 | 3 - Inizia la programmazione!
50 | 4 - Condividi i tuoi risultati con la comunità 😊
51 |
52 | ## Come contribuire
53 | Partecipa al progetto:
54 | - Suggestions et / ou creez de nouveaux défis: those défis seront alors available et pourront aider tous les développeurs à s'entraîner.
55 | - Améliorez o correggi il sito: puoi inviare una _Pull Request_ per votare la modifica, quindi è disponibile per tutti gli sviluppatori!
56 |
57 | ### Requisiti
58 | 1. Nodejs
59 |
60 | ### Instalare
61 |
62 | **Front-end**
63 |
64 | 1. Scarica o clona il repository DevChallenge.
65 | ```sh
66 | git clone git@github.com:Lorenalgm/DevChallenge.git
67 | ```
68 | 2. Apri il progetto nel tuo editor preferito.
69 | 3. Nel tuo terminale, installa le librerie necessarie:
70 | ```sh
71 | yarn
72 | ```
73 | ou
74 | ```sh
75 | npm install
76 | ```
77 | 4. Ora puoi andare alla cartella frontend per avviare il server:
78 | ```sh
79 | cd frontend
80 | ```
81 | ```sh
82 | yarn start
83 | ```
84 | 5. Apri il tuo browser! DevChallenge sarà disponibile su `http://localhost:3000/` :)
85 |
86 |
87 | **Back-end**
88 |
89 | Il backend è disponibile nel repository: DevChallengeAPI
90 |
91 |
92 | ## Comunity
93 | Il nostro obiettivo è aiutare sempre di più nell'evoluzione degli sviluppatori! Ecco perché abbiamo un'esclusiva community DevChallenge su Discord. Dai? https://discord.gg/yvYXhGj
94 |
95 | Sito web: https://www.devchallenge.com.br/
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | [forks-shield]: https://img.shields.io/github/forks/Lorenalgm/DevChallenge.svg?style=flat-square
107 | [forks-url]: https://github.com/Lorenalgm/DevChallenge/network/members
108 | [stars-shield]: https://img.shields.io/github/stars/Lorenalgm/DevChallenge.svg?style=flat-square
109 | [stars-url]: https://github.com/Lorenalgm/DevChallenge/stargazers
110 | [issues-shield]: https://img.shields.io/github/issues/Lorenalgm/DevChallenge.svg?style=flat-square
111 | [issues-url]: https://github.com/Lorenalgm/DevChallenge/issues
112 |
--------------------------------------------------------------------------------
/translations/README.md:
--------------------------------------------------------------------------------
1 | # Translations
2 |
3 | | | Link |
4 | | ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
5 | | | [Español](./README.es.md) | |
6 | | | [Português (Brasil)](../README.md) |
7 | | | [Deutsch](./README.de.md) |
8 | | | [French](./README.fr.md) |
9 |
--------------------------------------------------------------------------------