├── .github └── workflows │ └── ci.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── SECURITY.md ├── ToDo.md ├── client ├── .dockerignore ├── .env ├── .env.example ├── .gitignore ├── .vscode │ └── extensions.json ├── Dockerfile ├── index.html ├── package-lock.json ├── package.json ├── pnpm-lock.yaml ├── src │ ├── App.vue │ ├── assets │ │ ├── icon.png │ │ ├── icons │ │ │ ├── angulo.png │ │ │ ├── artwork.png │ │ │ ├── aviao-de-papel.png │ │ │ ├── aviao-de-papel2.png │ │ │ ├── casa.png │ │ │ ├── config.png │ │ │ ├── cruz.png │ │ │ ├── envio.png │ │ │ ├── estagio.png │ │ │ ├── forma.png │ │ │ ├── grafico-horizontal-simples.png │ │ │ ├── hamburger.png │ │ │ ├── icon.png │ │ │ ├── iconhome1.png │ │ │ ├── iconhome2.png │ │ │ ├── iconhome3.png │ │ │ ├── lapis.png │ │ │ ├── link.png │ │ │ ├── m1.png │ │ │ ├── m2.png │ │ │ ├── m3.png │ │ │ ├── olho-1.png │ │ │ ├── olho-2.png │ │ │ ├── pasta.png │ │ │ ├── procurar.png │ │ │ ├── saida.png │ │ │ ├── trofeu.png │ │ │ ├── user.png │ │ │ ├── user2.png │ │ │ └── verificar.png │ │ └── imgs │ │ │ ├── defaultBanner.png │ │ │ ├── image404.png │ │ │ ├── imageAdmin.png │ │ │ ├── imageMain.png │ │ │ ├── img1.jpg │ │ │ ├── img2.jpg │ │ │ ├── img3.jpg │ │ │ ├── img4.jpg │ │ │ └── logoHeader.png │ ├── components │ │ ├── Aside.vue │ │ ├── Cards.vue │ │ ├── ChatComponent.vue │ │ ├── ContactUs.vue │ │ ├── Footer.vue │ │ ├── Header.vue │ │ ├── Select.vue │ │ ├── Slides.vue │ │ ├── Sucess.vue │ │ ├── admin │ │ │ ├── Aside.vue │ │ │ ├── AsideDashboard.vue │ │ │ └── Header.vue │ │ ├── aluno │ │ │ ├── Aside.vue │ │ │ ├── AsideDashboard.vue │ │ │ └── Header.vue │ │ ├── empresa │ │ │ ├── Aside.vue │ │ │ ├── AsideDashboard.vue │ │ │ └── Header.vue │ │ ├── funcionario │ │ │ ├── Aside.vue │ │ │ ├── AsideDashboard.vue │ │ │ └── Header.vue │ │ └── professor │ │ │ ├── Aside.vue │ │ │ ├── AsideDashboard.vue │ │ │ └── Header.vue │ ├── main.js │ ├── router │ │ ├── guards │ │ │ └── guards.js │ │ ├── index.js │ │ └── routes │ │ │ ├── admin.js │ │ │ ├── aluno.js │ │ │ ├── empresa.js │ │ │ ├── funcionario.js │ │ │ ├── professor.js │ │ │ └── shared.js │ ├── scss │ │ ├── abstracts │ │ │ ├── _mixins.scss │ │ │ └── _variables.scss │ │ ├── base │ │ │ ├── _base.scss │ │ │ └── _typography.scss │ │ ├── layouts │ │ │ ├── _aside.scss │ │ │ ├── _cards.scss │ │ │ ├── _contactUs.scss │ │ │ ├── _footer.scss │ │ │ ├── _header.scss │ │ │ ├── _select.scss │ │ │ ├── _slides.scss │ │ │ ├── _sucess.scss │ │ │ ├── admin │ │ │ │ └── _aside.scss │ │ │ └── aluno │ │ │ │ └── _asideDashboard.scss │ │ ├── main.scss │ │ └── pages │ │ │ ├── admin │ │ │ ├── _dashboard.scss │ │ │ ├── _login.scss │ │ │ ├── _registerCoordenador.scss │ │ │ ├── _registerCurso.scss │ │ │ ├── _registerFuncionario.scss │ │ │ ├── _registerProfessor.scss │ │ │ ├── _registerTurma.scss │ │ │ ├── _tableCoordenador.scss │ │ │ ├── _tableCurso.scss │ │ │ ├── _tableEmpresa.scss │ │ │ ├── _tableEstagio.scss │ │ │ ├── _tableFuncionario.scss │ │ │ ├── _tableProfessor.scss │ │ │ └── _tableTurma.scss │ │ │ ├── aluno │ │ │ ├── _chat.scss │ │ │ ├── _chats.scss │ │ │ ├── _complete.scss │ │ │ ├── _config.scss │ │ │ ├── _home.scss │ │ │ ├── _login.scss │ │ │ ├── _profile.scss │ │ │ ├── _recovery.scss │ │ │ ├── _rede.scss │ │ │ ├── _register.scss │ │ │ ├── _validateRecovery.scss │ │ │ └── _validateRegister.scss │ │ │ ├── empresa │ │ │ ├── _dashboard.scss │ │ │ ├── _login.scss │ │ │ ├── _recovery.scss │ │ │ ├── _register.scss │ │ │ ├── _validate.scss │ │ │ └── _validateRecovery.scss │ │ │ ├── funcionario │ │ │ ├── _boletins.scss │ │ │ ├── _dashboard.scss │ │ │ ├── _init.scss │ │ │ ├── _login.scss │ │ │ ├── _recovery.scss │ │ │ ├── _registerVaga.scss │ │ │ ├── _validate.scss │ │ │ └── _validateRecovery.scss │ │ │ ├── professor │ │ │ ├── _dashboard.scss │ │ │ ├── _init.scss │ │ │ ├── _login.scss │ │ │ ├── _profile.scss │ │ │ ├── _recovery.scss │ │ │ ├── _validate.scss │ │ │ └── _validateRecovery.scss │ │ │ └── shared │ │ │ ├── _home.scss │ │ │ ├── _notFound.scss │ │ │ ├── _perfilAluno.scss │ │ │ ├── _perfilProfessor.scss │ │ │ ├── _pesquisa.scss │ │ │ ├── _ranking.scss │ │ │ ├── _vaga.scss │ │ │ └── _vagas.scss │ ├── services │ │ ├── api.js │ │ └── api │ │ │ ├── admin.js │ │ │ ├── aluno.js │ │ │ ├── empresa.js │ │ │ ├── funcionario.js │ │ │ ├── professor.js │ │ │ └── shared.js │ ├── socket.js │ ├── util │ │ ├── authMixins.js │ │ └── mixins.js │ └── views │ │ ├── admin │ │ ├── Dashboard.vue │ │ ├── Login.vue │ │ ├── RegisterCoordenador.vue │ │ ├── RegisterCurso.vue │ │ ├── RegisterFuncionario.vue │ │ ├── RegisterProfessor.vue │ │ ├── RegisterTurma.vue │ │ ├── TableCoordenador.vue │ │ ├── TableCurso.vue │ │ ├── TableEmpresa.vue │ │ ├── TableEstagio.vue │ │ ├── TableFuncionario.vue │ │ ├── TableProfessor.vue │ │ └── TableTurma.vue │ │ ├── aluno │ │ ├── Complete.vue │ │ ├── Config.vue │ │ ├── Home.vue │ │ ├── Login.vue │ │ ├── Message.vue │ │ ├── Messages.vue │ │ ├── PerfilAluno.vue │ │ ├── PerfilEmpresa.vue │ │ ├── Pesquisa.vue │ │ ├── Profile.vue │ │ ├── Ranking.vue │ │ ├── Recovery.vue │ │ ├── Rede.vue │ │ ├── Register.vue │ │ ├── Vaga.vue │ │ ├── Vagas.vue │ │ ├── ValidateRecovery.vue │ │ └── ValidateRegister.vue │ │ ├── empresa │ │ ├── Aluno.vue │ │ ├── Dashboard.vue │ │ ├── Login.vue │ │ ├── Mensagem.vue │ │ ├── Mensagens.vue │ │ ├── Pesquisa.vue │ │ ├── Ranking.vue │ │ ├── Recovery.vue │ │ ├── Register.vue │ │ ├── Validate.vue │ │ └── ValidateRecovery.vue │ │ ├── funcionario │ │ ├── Boletins.vue │ │ ├── Dashboard.vue │ │ ├── Init.vue │ │ ├── Login.vue │ │ ├── Recovery.vue │ │ ├── RegisterVaga.vue │ │ ├── Validate.vue │ │ └── ValidateRecovery.vue │ │ ├── professor │ │ ├── Aluno.vue │ │ ├── Dashboard.vue │ │ ├── Init.vue │ │ ├── Login.vue │ │ ├── Mensagem.vue │ │ ├── Mensagens.vue │ │ ├── Pesquisa.vue │ │ ├── Profile.vue │ │ ├── Recovery.vue │ │ ├── Rede.vue │ │ ├── Validate.vue │ │ └── ValidateRecovery.vue │ │ └── shared │ │ ├── Home.vue │ │ ├── NotFound.vue │ │ ├── PerfilAluno.vue │ │ ├── PerfilEmpresa.vue │ │ ├── PerfilProfessor.vue │ │ ├── Pesquisa.vue │ │ ├── Ranking.vue │ │ ├── Rankings.vue │ │ ├── Vaga.vue │ │ └── Vagas.vue └── vite.config.js ├── docker-compose.yml ├── nginx.conf └── server ├── .dockerignore ├── .env.example ├── .gitignore ├── Dockerfile ├── package-lock.json ├── package.json ├── pnpm-lock.yaml ├── prisma ├── migrations │ ├── 20240412003138_first_migrate │ │ └── migration.sql │ ├── 20240412192902_fix_field_names │ │ └── migration.sql │ ├── 20240416002008_add_pre_aluno_table │ │ └── migration.sql │ ├── 20240416002554_update_pre_aluno_table │ │ └── migration.sql │ ├── 20240416003534_update_pre_aluno_email │ │ └── migration.sql │ ├── 20240422143505_add_aluno_new_column │ │ └── migration.sql │ ├── 20240422143704_fix_aluno_column_name │ │ └── migration.sql │ ├── 20240423220555_add_curso_new_column │ │ └── migration.sql │ ├── 20240423223207_remove_curso_periodo │ │ └── migration.sql │ ├── 20240424234133_add_professor_and_coordenador_tables │ │ └── migration.sql │ ├── 20240425214437_add_funcionario_and_atividade_and_update_on_anothertables │ │ └── migration.sql │ ├── 20240425215818_fix_error_column_name │ │ └── migration.sql │ ├── 20240425220631_fix_email_column_in_professor_table │ │ └── migration.sql │ ├── 20240429212723_fix_cargo_enum │ │ └── migration.sql │ ├── 20240430185547_add_new_professor_column │ │ └── migration.sql │ ├── 20240503160551_add_funcionario_validated_column │ │ └── migration.sql │ ├── 20240507003915_add_tentativas_restantes_column_on_tables │ │ └── migration.sql │ ├── 20240509012700_fix_empresa_table │ │ └── migration.sql │ ├── 20240509020030_updade_patrocinador_empresa_column │ │ └── migration.sql │ ├── 20240509145838_add_empresa_validated_column │ │ └── migration.sql │ ├── 20240509150241_add_empresatentativas_restantes_column │ │ └── migration.sql │ ├── 20240509151050_fix_empresa_cnpj_column │ │ └── migration.sql │ ├── 20240521003302_add_new_table_vincolos_and_addcolumns │ │ └── migration.sql │ ├── 20240524172824_add_accepted_column_on_vinculo_table │ │ └── migration.sql │ ├── 20240601200546_update_curriculo_column_aluno_table │ │ └── migration.sql │ ├── 20240603211401_remove_pre_aluno_add_turma_aluno_and_extra_curricular_table │ │ └── migration.sql │ ├── 20240610234129_add_banner_on_professor_table │ │ └── migration.sql │ ├── 20240616234412_add_message_table │ │ └── migration.sql │ ├── 20240706180957_add_title_label_on_vagas_table │ │ └── migration.sql │ ├── 20240706193450_fix_vaga_table_fields │ │ └── migration.sql │ ├── 20240731003618_add_aluno_atividade_relation_table │ │ └── migration.sql │ ├── 20240803010917_create_boletins_table │ │ └── migration.sql │ ├── 20240804231659_add_notas_and_materias_tables │ │ └── migration.sql │ ├── 20241016131941_add_notificacao_table │ │ └── migration.sql │ ├── 20241030201222_add_telefone_field_on_aluno_table │ │ └── migration.sql │ ├── 20241031194037_add_boletim_notification_type │ │ └── migration.sql │ ├── 20241123155243_add_banner_field_empresa │ │ └── migration.sql │ ├── 20241123175644_add_site_field_empresa │ │ └── migration.sql │ ├── 20241124224106_add_sobre_fiel_professor │ │ └── migration.sql │ └── migration_lock.toml └── schema.prisma ├── src ├── connection │ ├── controllers │ │ ├── entryController.ts │ │ ├── messageControllers.ts │ │ ├── notificationController.ts │ │ └── vinculoController.ts │ ├── router │ │ └── sokcets.routes.ts │ └── socket.ts ├── errors │ └── error.ts ├── index.ts ├── jwt │ └── jwtServices.ts ├── mail │ ├── config │ │ └── email.ts │ └── templates │ │ ├── aluno │ │ ├── recovery.ts │ │ └── register.ts │ │ ├── empresa │ │ ├── recoveryEmpresa.ts │ │ └── registerEmpresa.ts │ │ ├── funcionario │ │ ├── recoveryFuncionario.ts │ │ └── registerFuncionario.ts │ │ └── professor │ │ ├── recoveryProfessor.ts │ │ └── registerProfessor.ts ├── middleware │ └── auth │ │ ├── autentication.ts │ │ └── socket.ts ├── minioService.ts ├── modules │ ├── controllers │ │ ├── adminControllers.ts │ │ ├── alunoControllers.ts │ │ ├── empresaControllers.ts │ │ ├── funcionarioControllers.ts │ │ ├── professorControllers.ts │ │ └── sharedControllers.ts │ ├── interfaces │ │ ├── adminDTOs.ts │ │ ├── alunoDTOs.ts │ │ ├── empresaDTOs.ts │ │ ├── funcionarioDTOs.ts │ │ ├── professorDTOs.ts │ │ └── sharedDTOs.ts │ └── services │ │ ├── admin │ │ ├── Get │ │ │ ├── Coordenadores.ts │ │ │ ├── CoordenasdoresNames.ts │ │ │ ├── Cursos.ts │ │ │ ├── Empresas.ts │ │ │ ├── Estagios.ts │ │ │ ├── Funcionario.ts │ │ │ ├── ProfessorNames.ts │ │ │ ├── Professores.ts │ │ │ └── Turmas.ts │ │ ├── LoginAdminUseCase.ts │ │ ├── RefreshTokenUseCase.ts │ │ ├── RegisterCoordenadorUseCase.ts │ │ ├── RegisterCursosUseCase.ts │ │ ├── RegisterFuncionarioUseCase.ts │ │ ├── RegisterProfessorUseCase.ts │ │ └── RegisterTurmasUseCase.ts │ │ ├── aluno │ │ ├── ChangePassUseCase.ts │ │ ├── CompleteRegisterUseCase.ts │ │ ├── CreateAlunoUseCase.ts │ │ ├── CreateExtraUseCase.ts │ │ ├── EditExtraUsecase.ts │ │ ├── ExcludeExtraUseCase.ts │ │ ├── GenerateCurriculumUseCase.ts │ │ ├── GetCourseYearUseCase.ts │ │ ├── GetCurriculoUseCase.ts │ │ ├── GetExtracurricularesUseCase.ts │ │ ├── GetMeUseCase.ts │ │ ├── LoginAlunoUseCase.ts │ │ ├── RecoveryAlunoUseCase.ts │ │ ├── RefreshTokenUseCase.ts │ │ ├── SendBoletimUseCase.ts │ │ ├── UpdateCurriculoUseCase.ts │ │ ├── UploadCapaUseCase.ts │ │ ├── UploadProfileUseCase.ts │ │ ├── ValidateAlunoUseCase.ts │ │ └── ValidateRecoveryUseCase.ts │ │ ├── empresa │ │ ├── GetEmpresaUseCase.ts │ │ ├── LoginEmpresaUseCase.ts │ │ ├── RecoveryEmpresaUseCase.ts │ │ ├── RefreshTokenUseCase.ts │ │ ├── RegisterEmpresaUseCase.ts │ │ ├── UpdateSiteUseCase.ts │ │ ├── UploadCapaUseCase.ts │ │ ├── UploadProfileUseCase.ts │ │ ├── ValidateEmpresaUseCase.ts │ │ └── ValidateRecoveryEmpresa.ts │ │ ├── funcionario │ │ ├── CompareBoletinsUseCase.ts │ │ ├── GetunapprovedUsecase.ts │ │ ├── InitFuncionarioUseCase.ts │ │ ├── LoginFuncionarioUseCase.ts │ │ ├── RecoveryUseCase.ts │ │ ├── RefreshTokenUseCase.ts │ │ ├── RegisterVagasUseCase.ts │ │ ├── SetAsParceiraUseCase.ts │ │ ├── ValidateFuncionarioUseCase.ts │ │ └── ValidateRecoveryUseCase.ts │ │ ├── professor │ │ ├── CreateActivityUseCase.ts │ │ ├── GetCurriculoUseCase.ts │ │ ├── InitProfessorUseCase.ts │ │ ├── LinkAlunoActivityUseCase.ts │ │ ├── LoginProfessorUseCase.ts │ │ ├── RecoveryProfessorUseCase.ts │ │ ├── RefreshTokenUseCase.ts │ │ ├── UodateCurriculoUseCase copy.ts │ │ ├── UodateCurriculoUseCase.ts │ │ ├── UploadCapaUseCase.ts │ │ ├── UploadProfileUseCase.ts │ │ ├── ValidateProfessorUseCase.ts │ │ └── ValidateRecoveryUseCase.ts │ │ └── shared │ │ ├── AcceptVinculoUseCase.ts │ │ ├── CreateMessageUseCase.ts │ │ ├── CreateVinculoUseCase.ts │ │ ├── DeleteVinculoUseCase.ts │ │ ├── GetBannerUseCase.ts │ │ ├── GetChatUseCase.ts │ │ ├── GetCurriculoUseCase.ts │ │ ├── GetCursosUseCase.ts │ │ ├── GetEmpresasUseCase.ts │ │ ├── GetExtraUseCase.ts │ │ ├── GetMessagesUseCase.ts │ │ ├── GetProfileImageUseCase.ts │ │ ├── GetProfileVincUseCase.ts │ │ ├── GetProfilesUseCase.ts │ │ ├── GetRanking.ts │ │ ├── GetUnlinkedsUseCase.ts │ │ ├── GetVagaUseCase.ts │ │ ├── GetVagasUseCase.ts │ │ ├── GetVinculosUseCase.ts │ │ ├── IgnoreVinculoUseCase.ts │ │ └── helpers │ │ └── helpers.ts ├── pdf │ ├── curriculum_template.html │ └── style.css ├── prisma │ └── client.ts └── router │ ├── index.ts │ └── routes │ ├── admin.routes.ts │ ├── aluno.routes.ts │ ├── empresa.routes.ts │ ├── funcionario.routes.ts │ ├── imports │ ├── admin.ts │ ├── aluno.ts │ ├── empresa.ts │ ├── funcionario.ts │ ├── professor.ts │ └── shared.ts │ ├── professor.routes.ts │ └── shared.routes.ts ├── tsconfig.json └── vercel.json /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | schedule: 11 | -cron: '0 0 * * *' 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - name: Code checkout 19 | uses: actions/checkout@v3 20 | 21 | - name: Docker-compose configurations 22 | run: docker compose up -d 23 | 24 | - name: Check if docker-compose is working 25 | run: docker compose ps 26 | 27 | - name: Stop and remove docker-compose containers 28 | run: docker compose down -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | data 2 | my.cnf 3 | .vscode -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions to this project are welcome. Please follow these steps to contribute: 4 | 5 | 1. Fork the repository. 6 | 2. Create a new branch for your feature or bug fix. 7 | 3. Commit your changes. 8 | 4. Push to the branch. 9 | 5. Submit a pull request. 10 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 5.1.x | :white_check_mark: | 11 | | 5.0.x | :x: | 12 | | 4.0.x | :white_check_mark: | 13 | | < 4.0 | :x: | 14 | 15 | ## Reporting a Vulnerability 16 | 17 | Use this section to tell people how to report a vulnerability. 18 | 19 | Tell them where to go, how often they can expect to get an update on a 20 | reported vulnerability, what to expect if the vulnerability is accepted or 21 | declined, etc. 22 | -------------------------------------------------------------------------------- /ToDo.md: -------------------------------------------------------------------------------- 1 | # Server 2 | - [ ] arrumar o erro das imgs 3 | 4 | ## Aluno 5 | - [ ] exportar currículo 6 | - [ ] Ranking de alunos 7 | - [ ] Home - Notificações sobre estágio, aceitação de boletim ou atividades, solicitações e novas mensagens. 8 | - [ ] Arrumar a curso e turno do complete register 9 | 10 | ## Funcionário 11 | - [ ] Dashboard - Notificações de envio de boletim e encerramento de estágio. 12 | - [ ] Validar boletim 13 | 14 | ## Professor 15 | - [ ] Dashboard - Notificações de mensagens, atividades extracurriculares. 16 | 17 | ## Empresa 18 | - [ ] Dashboard - Notificações de mensagens 19 | 20 | ## Coordenador 21 | 22 | ## Admin 23 | - [ ] Dashboard - Gráficos do canva 24 | -------------------------------------------------------------------------------- /client/.dockerignore: -------------------------------------------------------------------------------- 1 | node_moludes 2 | .vscode 3 | .gitignore -------------------------------------------------------------------------------- /client/.env: -------------------------------------------------------------------------------- 1 | SERVER_URL="http://localhost:3333" -------------------------------------------------------------------------------- /client/.env.example: -------------------------------------------------------------------------------- 1 | VITE_SERVER_URL="http://localhost:3333" -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /client/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar"] 3 | } 4 | -------------------------------------------------------------------------------- /client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:latest 2 | 3 | WORKDIR /client 4 | 5 | COPY package*.json ./ 6 | 7 | RUN npm install 8 | 9 | COPY . . 10 | 11 | EXPOSE 5173 12 | 13 | CMD ["npm","run","dev"] -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Boot 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite --host", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "axios": "^1.6.8", 13 | "dotenv": "^16.4.5", 14 | "js-cookie": "^3.0.5", 15 | "socket.io-client": "^4.7.5", 16 | "vue": "^3.4.21", 17 | "vue-router": "^4.3.0" 18 | }, 19 | "devDependencies": { 20 | "@vitejs/plugin-vue": "^5.0.4", 21 | "sass": "^1.75.0", 22 | "vite": "^5.2.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /client/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 11 | 12 | -------------------------------------------------------------------------------- /client/src/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icon.png -------------------------------------------------------------------------------- /client/src/assets/icons/angulo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/angulo.png -------------------------------------------------------------------------------- /client/src/assets/icons/artwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/artwork.png -------------------------------------------------------------------------------- /client/src/assets/icons/aviao-de-papel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/aviao-de-papel.png -------------------------------------------------------------------------------- /client/src/assets/icons/aviao-de-papel2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/aviao-de-papel2.png -------------------------------------------------------------------------------- /client/src/assets/icons/casa.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/casa.png -------------------------------------------------------------------------------- /client/src/assets/icons/config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/config.png -------------------------------------------------------------------------------- /client/src/assets/icons/cruz.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/cruz.png -------------------------------------------------------------------------------- /client/src/assets/icons/envio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/envio.png -------------------------------------------------------------------------------- /client/src/assets/icons/estagio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/estagio.png -------------------------------------------------------------------------------- /client/src/assets/icons/forma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/forma.png -------------------------------------------------------------------------------- /client/src/assets/icons/grafico-horizontal-simples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/grafico-horizontal-simples.png -------------------------------------------------------------------------------- /client/src/assets/icons/hamburger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/hamburger.png -------------------------------------------------------------------------------- /client/src/assets/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/icon.png -------------------------------------------------------------------------------- /client/src/assets/icons/iconhome1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/iconhome1.png -------------------------------------------------------------------------------- /client/src/assets/icons/iconhome2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/iconhome2.png -------------------------------------------------------------------------------- /client/src/assets/icons/iconhome3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/iconhome3.png -------------------------------------------------------------------------------- /client/src/assets/icons/lapis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/lapis.png -------------------------------------------------------------------------------- /client/src/assets/icons/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/link.png -------------------------------------------------------------------------------- /client/src/assets/icons/m1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/m1.png -------------------------------------------------------------------------------- /client/src/assets/icons/m2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/m2.png -------------------------------------------------------------------------------- /client/src/assets/icons/m3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/m3.png -------------------------------------------------------------------------------- /client/src/assets/icons/olho-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/olho-1.png -------------------------------------------------------------------------------- /client/src/assets/icons/olho-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/olho-2.png -------------------------------------------------------------------------------- /client/src/assets/icons/pasta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/pasta.png -------------------------------------------------------------------------------- /client/src/assets/icons/procurar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/procurar.png -------------------------------------------------------------------------------- /client/src/assets/icons/saida.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/saida.png -------------------------------------------------------------------------------- /client/src/assets/icons/trofeu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/trofeu.png -------------------------------------------------------------------------------- /client/src/assets/icons/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/user.png -------------------------------------------------------------------------------- /client/src/assets/icons/user2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/user2.png -------------------------------------------------------------------------------- /client/src/assets/icons/verificar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/icons/verificar.png -------------------------------------------------------------------------------- /client/src/assets/imgs/defaultBanner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/imgs/defaultBanner.png -------------------------------------------------------------------------------- /client/src/assets/imgs/image404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/imgs/image404.png -------------------------------------------------------------------------------- /client/src/assets/imgs/imageAdmin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/imgs/imageAdmin.png -------------------------------------------------------------------------------- /client/src/assets/imgs/imageMain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/imgs/imageMain.png -------------------------------------------------------------------------------- /client/src/assets/imgs/img1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/imgs/img1.jpg -------------------------------------------------------------------------------- /client/src/assets/imgs/img2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/imgs/img2.jpg -------------------------------------------------------------------------------- /client/src/assets/imgs/img3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/imgs/img3.jpg -------------------------------------------------------------------------------- /client/src/assets/imgs/img4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/imgs/img4.jpg -------------------------------------------------------------------------------- /client/src/assets/imgs/logoHeader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/assets/imgs/logoHeader.png -------------------------------------------------------------------------------- /client/src/components/ChatComponent.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 62 | 63 | -------------------------------------------------------------------------------- /client/src/components/ContactUs.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 30 | 58 | -------------------------------------------------------------------------------- /client/src/components/Footer.vue: -------------------------------------------------------------------------------- 1 | 2 | 25 | 26 | 43 | -------------------------------------------------------------------------------- /client/src/components/Select.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 65 | 66 | 69 | -------------------------------------------------------------------------------- /client/src/components/Sucess.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 32 | 33 | -------------------------------------------------------------------------------- /client/src/components/empresa/Aside.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 59 | 60 | -------------------------------------------------------------------------------- /client/src/components/funcionario/Aside.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 59 | 60 | -------------------------------------------------------------------------------- /client/src/components/professor/Aside.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 59 | 60 | -------------------------------------------------------------------------------- /client/src/main.js: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | 5 | createApp(App).use(router).mount('#app') -------------------------------------------------------------------------------- /client/src/router/index.js: -------------------------------------------------------------------------------- 1 | import { createRouter, createWebHistory } from 'vue-router'; 2 | import { alunoRoutes } from './routes/aluno'; 3 | import { adminRoutes } from './routes/admin'; 4 | import { professorRoutes } from './routes/professor'; 5 | import { funcionarioRoutes } from './routes/funcionario'; 6 | import { empresaRoutes } from './routes/empresa'; 7 | import { sharedRoutes } from './routes/shared'; 8 | 9 | const routes = [ 10 | ...alunoRoutes, 11 | ...adminRoutes, 12 | ...professorRoutes, 13 | ...funcionarioRoutes, 14 | ...empresaRoutes, 15 | ...sharedRoutes 16 | ]; 17 | 18 | const router = createRouter({ 19 | history: createWebHistory(), 20 | routes 21 | }); 22 | 23 | export default router; -------------------------------------------------------------------------------- /client/src/scss/abstracts/_variables.scss: -------------------------------------------------------------------------------- 1 | $font-color-light: #000000; 2 | $font-color-dark: #fcf3ee; 3 | $font-color-dark-2: #9c9794; 4 | $bg-color-light: #fff0e6; 5 | $bg-color-dark: #202020; 6 | 7 | // Default Colors 8 | 9 | $primary-color-dark: #161616; 10 | $secondary-color-dark: #1a1a1a; 11 | $terciary-color-dark: #202020; 12 | 13 | $primary-color-orange: #ff872b; 14 | $secondary-color-orange: #deb99b; 15 | -------------------------------------------------------------------------------- /client/src/scss/base/_base.scss: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | list-style: none; 6 | } 7 | 8 | body { 9 | overflow-x: hidden; 10 | min-height: 100vh; 11 | width: 100vw; 12 | display: flex; 13 | flex-direction: column; 14 | } 15 | 16 | main { 17 | min-height: calc(100vh - 80px); 18 | } 19 | 20 | img, 21 | button, 22 | a { 23 | -webkit-user-select: none; 24 | user-select: none; 25 | transition: 0.2s; 26 | } 27 | 28 | .alertBox { 29 | @include flex(row, flex-start, center); 30 | @include font-inter(500); 31 | padding: 10px; 32 | margin-bottom: 15px; 33 | border: 1px solid transparent; 34 | border-radius: 4px; 35 | } 36 | 37 | .alertBox-error { 38 | color: $font-color-dark; 39 | background-color: #b32323; 40 | border-color: #a72727; 41 | } 42 | 43 | .alertBox-sucess { 44 | color: $font-color-dark; 45 | background-color: #07d873; 46 | border-color: #0ccf4d; 47 | } -------------------------------------------------------------------------------- /client/src/scss/base/_typography.scss: -------------------------------------------------------------------------------- 1 | @import url("https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap"); 2 | -------------------------------------------------------------------------------- /client/src/scss/layouts/_footer.scss: -------------------------------------------------------------------------------- 1 | footer { 2 | background-color: $primary-color-dark; 3 | height: 250px; 4 | @include flex(column, space-evenly, center); 5 | @include font-inter(200); 6 | @include m-screen(1400px) { 7 | height: 200px; 8 | } 9 | @include m-screen(1120px) { 10 | height: 180px; 11 | } 12 | @include m-screen(680px) { 13 | height: 200px; 14 | } 15 | 16 | img { 17 | height: 40px; 18 | @include m-screen(1400px) { 19 | height: 34px; 20 | } 21 | @include m-screen(1120px) { 22 | height: 30px; 23 | } 24 | } 25 | 26 | nav ul { 27 | margin: 0px; 28 | @include flex(row, center, center); 29 | 30 | li { 31 | margin: 0px 10px; 32 | 33 | a { 34 | margin: 0px; 35 | text-decoration: none; 36 | transition: 0.1s linear; 37 | color: $font-color-dark-2; 38 | font-size: 1rem; 39 | @include font-inter(700); 40 | @include m-screen(1400px) { 41 | font-size: 0.8rem; 42 | } 43 | &:hover { 44 | color: $secondary-color-orange; 45 | } 46 | } 47 | } 48 | } 49 | 50 | > li { 51 | height: 1px; 52 | background-color: $font-color-dark-2; 53 | width: 90%; 54 | } 55 | 56 | > p { 57 | color: $font-color-dark-2; 58 | font-size: 1rem; 59 | @include m-screen(1400px) { 60 | font-size: 0.8rem; 61 | } 62 | @include font-inter(700); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /client/src/scss/layouts/_select.scss: -------------------------------------------------------------------------------- 1 | .custom-select { 2 | @include font-inter(300); 3 | @include flex(column, center, flex-start); 4 | position: relative; 5 | display: inline-block; 6 | width: 200px; 7 | cursor: pointer; 8 | border-radius: 5px; 9 | 10 | &:focus { 11 | border-left: solid 3px $secondary-color-orange; 12 | border-radius: 0px 5px 5px 0px; 13 | .selected { 14 | border-radius: 0px 5px 5px 0px; 15 | } 16 | } 17 | 18 | .selected { 19 | @include flex(column, center, flex-start); 20 | padding: 10px; 21 | border: 1px solid $terciary-color-dark; 22 | background-color: $terciary-color-dark; 23 | color: $font-color-dark; 24 | border-radius: 5px; 25 | 26 | .description{ 27 | @include flex(row, space-between, center); 28 | width: 100%; 29 | font-size: 0.8rem; 30 | 31 | p { 32 | font-size: 0.9rem; 33 | } 34 | 35 | img{ 36 | transform: rotate(-90deg); 37 | width: 10px; 38 | filter: invert(100%); 39 | margin-right: 10px; 40 | } 41 | } 42 | 43 | 44 | label { 45 | letter-spacing: 1.5px; 46 | @include font-inter(200); 47 | font-size: 0.8rem; 48 | color: $font-color-dark-2; 49 | } 50 | } 51 | 52 | .options { 53 | position: absolute; 54 | top: 100%; 55 | left: 0; 56 | width: 100%; 57 | border: 1px solid $terciary-color-dark; 58 | background-color: $terciary-color-dark; 59 | max-height: 200px; 60 | overflow-y: auto; 61 | z-index: 1000; 62 | list-style: none; 63 | margin: 0; 64 | padding: 0; 65 | font-size: 0.9rem; 66 | 67 | li { 68 | padding: 10px; 69 | cursor: pointer; 70 | color: $font-color-dark-2; 71 | 72 | &:hover { 73 | background-color: $secondary-color-orange; 74 | color: $terciary-color-dark; 75 | } 76 | } 77 | 78 | li:first-child{ 79 | opacity: 0.8; 80 | } 81 | } 82 | } -------------------------------------------------------------------------------- /client/src/scss/main.scss: -------------------------------------------------------------------------------- 1 | @import "abstracts/_mixins.scss"; 2 | @import "abstracts/_variables.scss"; 3 | 4 | @import "base/_base.scss"; 5 | @import "base/typography"; 6 | -------------------------------------------------------------------------------- /client/src/scss/pages/admin/_dashboard.scss: -------------------------------------------------------------------------------- 1 | nav { 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: space-around; 5 | align-items: center; 6 | height: 30px; 7 | 8 | a { 9 | text-decoration: none; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /client/src/scss/pages/admin/_tableCoordenador.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | 7 | .path { 8 | width: 100%; 9 | @include flex(row, flex-start, center); 10 | 11 | font-size: 0.9rem; 12 | @include font-inter(300); 13 | margin-bottom: 20px; 14 | > p { 15 | @include flex(column, center, center); 16 | @include font-inter(400); 17 | 18 | &:after { 19 | width: 100%; 20 | height: 3px; 21 | margin-top: 3px; 22 | background-color: $secondary-color-orange; 23 | } 24 | 25 | &:hover::after { 26 | animation: none; 27 | } 28 | } 29 | 30 | img { 31 | @include flex(column, center, center); 32 | width: 15px; 33 | transform: rotate(180deg); 34 | filter: invert(100%); 35 | margin-inline: 20px; 36 | } 37 | } 38 | 39 | .table { 40 | display: flex; 41 | flex-direction: column; 42 | width: 100%; 43 | 44 | .table-header { 45 | border-left: 3px solid $secondary-color-orange; 46 | .table-cell { 47 | @include font-inter(600); 48 | } 49 | } 50 | 51 | .table-row { 52 | display: flex; 53 | flex-direction: row; 54 | border-bottom: 1px dashed $font-color-dark-2; 55 | } 56 | 57 | .table-row1{ 58 | border-bottom: 0px solid $font-color-dark; 59 | } 60 | 61 | .table-cell { 62 | flex: 1; 63 | padding: 8px; 64 | font-size: 1rem; 65 | @include font-inter(300); 66 | color: $font-color-dark; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /client/src/scss/pages/admin/_tableCurso.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | 7 | .path { 8 | width: 100%; 9 | @include flex(row, flex-start, center); 10 | 11 | font-size: 0.9rem; 12 | @include font-inter(300); 13 | margin-bottom: 20px; 14 | > p { 15 | @include flex(column, center, center); 16 | @include font-inter(400); 17 | 18 | &:after { 19 | width: 100%; 20 | height: 3px; 21 | margin-top: 3px; 22 | background-color: $secondary-color-orange; 23 | } 24 | 25 | &:hover::after { 26 | animation: none; 27 | } 28 | } 29 | 30 | img { 31 | @include flex(column, center, center); 32 | width: 15px; 33 | transform: rotate(180deg); 34 | filter: invert(100%); 35 | margin-inline: 20px; 36 | } 37 | } 38 | 39 | .table { 40 | display: flex; 41 | flex-direction: column; 42 | width: 100%; 43 | 44 | .table-header { 45 | border-left: 3px solid $secondary-color-orange; 46 | .table-cell { 47 | @include font-inter(600); 48 | } 49 | } 50 | 51 | .table-row { 52 | display: flex; 53 | flex-direction: row; 54 | border-bottom: 1px dashed $font-color-dark-2; 55 | } 56 | 57 | .table-row1{ 58 | border-bottom: 0px solid $font-color-dark; 59 | } 60 | 61 | .table-cell { 62 | flex: 1; 63 | padding: 8px; 64 | border-right: 1px solid #ddd; 65 | font-size: 1rem; 66 | @include font-inter(300); 67 | color: $font-color-dark; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /client/src/scss/pages/admin/_tableEmpresa.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | 7 | .path { 8 | width: 100%; 9 | @include flex(row, flex-start, center); 10 | 11 | font-size: 0.9rem; 12 | @include font-inter(300); 13 | margin-bottom: 20px; 14 | > p { 15 | @include flex(column, center, center); 16 | @include font-inter(400); 17 | 18 | &:after { 19 | width: 100%; 20 | height: 3px; 21 | margin-top: 3px; 22 | background-color: $secondary-color-orange; 23 | } 24 | 25 | &:hover::after { 26 | animation: none; 27 | } 28 | } 29 | 30 | img { 31 | @include flex(column, center, center); 32 | width: 15px; 33 | transform: rotate(180deg); 34 | filter: invert(100%); 35 | margin-inline: 20px; 36 | } 37 | } 38 | 39 | .table { 40 | display: flex; 41 | flex-direction: column; 42 | width: 100%; 43 | 44 | .table-header { 45 | border-left: 3px solid $secondary-color-orange; 46 | .table-cell { 47 | @include font-inter(600); 48 | } 49 | } 50 | 51 | .table-row { 52 | display: flex; 53 | flex-direction: row; 54 | border-bottom: 1px dashed $font-color-dark-2; 55 | } 56 | 57 | .table-row1{ 58 | border-bottom: 0px solid $font-color-dark; 59 | } 60 | 61 | .table-cell { 62 | flex: 1; 63 | padding: 8px; 64 | border-right: 1px solid #ddd; 65 | font-size: 1rem; 66 | @include font-inter(300); 67 | color: $font-color-dark; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /client/src/scss/pages/admin/_tableEstagio.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | 7 | .path { 8 | width: 100%; 9 | @include flex(row, flex-start, center); 10 | 11 | font-size: 0.9rem; 12 | @include font-inter(300); 13 | margin-bottom: 20px; 14 | > p { 15 | @include flex(column, center, center); 16 | @include font-inter(400); 17 | 18 | &:after { 19 | width: 100%; 20 | height: 3px; 21 | margin-top: 3px; 22 | background-color: $secondary-color-orange; 23 | } 24 | 25 | &:hover::after { 26 | animation: none; 27 | } 28 | } 29 | 30 | img { 31 | @include flex(column, center, center); 32 | width: 15px; 33 | transform: rotate(180deg); 34 | filter: invert(100%); 35 | margin-inline: 20px; 36 | } 37 | } 38 | 39 | .table { 40 | display: flex; 41 | flex-direction: column; 42 | width: 100%; 43 | 44 | .table-header { 45 | border-left: 3px solid $secondary-color-orange; 46 | .table-cell { 47 | @include font-inter(600); 48 | } 49 | } 50 | 51 | .table-row { 52 | display: flex; 53 | flex-direction: row; 54 | border-bottom: 1px dashed $font-color-dark-2; 55 | } 56 | 57 | .table-row1{ 58 | border-bottom: 0px solid $font-color-dark; 59 | } 60 | .table-cell { 61 | flex: 1; 62 | padding: 8px; 63 | border-right: 1px solid #ddd; 64 | font-size: 1rem; 65 | @include font-inter(300); 66 | color: $font-color-dark; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /client/src/scss/pages/admin/_tableFuncionario.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | 7 | .path { 8 | width: 100%; 9 | @include flex(row, flex-start, center); 10 | 11 | font-size: 0.9rem; 12 | @include font-inter(300); 13 | margin-bottom: 20px; 14 | > p { 15 | @include flex(column, center, center); 16 | @include font-inter(400); 17 | 18 | &:after { 19 | width: 100%; 20 | height: 3px; 21 | margin-top: 3px; 22 | background-color: $secondary-color-orange; 23 | } 24 | 25 | &:hover::after { 26 | animation: none; 27 | } 28 | } 29 | 30 | img { 31 | @include flex(column, center, center); 32 | width: 15px; 33 | transform: rotate(180deg); 34 | filter: invert(100%); 35 | margin-inline: 20px; 36 | } 37 | } 38 | 39 | .table { 40 | display: flex; 41 | flex-direction: column; 42 | width: 100%; 43 | 44 | .table-header { 45 | border-left: 3px solid $secondary-color-orange; 46 | .table-cell { 47 | @include font-inter(600); 48 | } 49 | } 50 | 51 | .table-row { 52 | display: flex; 53 | flex-direction: row; 54 | border-bottom: 1px dashed $font-color-dark-2; 55 | } 56 | 57 | .table-row1{ 58 | border-bottom: 0px solid $font-color-dark; 59 | } 60 | 61 | .table-cell { 62 | flex: 1; 63 | padding: 8px; 64 | border-right: 1px solid #ddd; 65 | font-size: 1rem; 66 | @include font-inter(300); 67 | color: $font-color-dark; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /client/src/scss/pages/admin/_tableProfessor.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | 7 | .path { 8 | width: 100%; 9 | @include flex(row, flex-start, center); 10 | 11 | font-size: 0.9rem; 12 | @include font-inter(300); 13 | margin-bottom: 20px; 14 | > p { 15 | @include flex(column, center, center); 16 | @include font-inter(400); 17 | 18 | &:after { 19 | width: 100%; 20 | height: 3px; 21 | margin-top: 3px; 22 | background-color: $secondary-color-orange; 23 | } 24 | 25 | &:hover::after { 26 | animation: none; 27 | } 28 | } 29 | 30 | img { 31 | @include flex(column, center, center); 32 | width: 15px; 33 | transform: rotate(180deg); 34 | filter: invert(100%); 35 | margin-inline: 20px; 36 | } 37 | } 38 | 39 | .table { 40 | display: flex; 41 | flex-direction: column; 42 | width: 100%; 43 | 44 | .table-header { 45 | border-left: 3px solid $secondary-color-orange; 46 | .table-cell { 47 | @include font-inter(600); 48 | } 49 | } 50 | 51 | .table-row { 52 | display: flex; 53 | flex-direction: row; 54 | border-bottom: 1px dashed $font-color-dark-2; 55 | } 56 | 57 | .table-row1{ 58 | border-bottom: 0px solid $font-color-dark; 59 | } 60 | 61 | .table-cell { 62 | flex: 1; 63 | padding: 8px; 64 | border-right: 1px solid #ddd; 65 | font-size: 1rem; 66 | @include font-inter(300); 67 | color: $font-color-dark; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /client/src/scss/pages/admin/_tableTurma.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | 7 | .path { 8 | width: 100%; 9 | @include flex(row, flex-start, center); 10 | 11 | font-size: 0.9rem; 12 | @include font-inter(300); 13 | margin-bottom: 20px; 14 | > p { 15 | @include flex(column, center, center); 16 | @include font-inter(400); 17 | 18 | &:after { 19 | width: 100%; 20 | height: 3px; 21 | margin-top: 3px; 22 | background-color: $secondary-color-orange; 23 | } 24 | 25 | &:hover::after { 26 | animation: none; 27 | } 28 | } 29 | 30 | img { 31 | @include flex(column, center, center); 32 | width: 15px; 33 | transform: rotate(180deg); 34 | filter: invert(100%); 35 | margin-inline: 20px; 36 | } 37 | } 38 | 39 | .table { 40 | display: flex; 41 | flex-direction: column; 42 | width: 100%; 43 | 44 | .table-header { 45 | border-left: 3px solid $secondary-color-orange; 46 | .table-cell { 47 | @include font-inter(600); 48 | } 49 | } 50 | 51 | .table-row { 52 | display: flex; 53 | flex-direction: row; 54 | border-bottom: 1px dashed $font-color-dark-2; 55 | } 56 | 57 | .table-row1{ 58 | border-bottom: 0px solid $font-color-dark; 59 | } 60 | 61 | .table-cell { 62 | flex: 1; 63 | padding: 8px; 64 | border-right: 1px solid #ddd; 65 | font-size: 1rem; 66 | @include font-inter(300); 67 | color: $font-color-dark; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /client/src/scss/pages/funcionario/_dashboard.scss: -------------------------------------------------------------------------------- 1 | nav { 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: space-around; 5 | align-items: center; 6 | height: 30px; 7 | 8 | a { 9 | text-decoration: none; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /client/src/scss/pages/professor/_dashboard.scss: -------------------------------------------------------------------------------- 1 | nav { 2 | display: flex; 3 | flex-direction: row; 4 | justify-content: space-around; 5 | align-items: center; 6 | height: 30px; 7 | 8 | a { 9 | text-decoration: none; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /client/src/scss/pages/professor/_profile.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | -------------------------------------------------------------------------------- /client/src/scss/pages/shared/_notFound.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | 7 | .box { 8 | width: 50%; 9 | height: 30%; 10 | @include flex-center; 11 | 12 | .img { 13 | width: 30%; 14 | height: 100%; 15 | background-image: url(../../assets/imgs/image404.png); 16 | background-position: center; 17 | background-size: 100%; 18 | background-repeat: no-repeat; 19 | } 20 | 21 | .info { 22 | width: 70%; 23 | height: 100%; 24 | @include flex(column, flex-start, start); 25 | padding: 20px; 26 | 27 | h1 { 28 | width: 80%; 29 | font-size: 2rem; 30 | @include font-inter(300); 31 | color: $font-color-dark; 32 | } 33 | 34 | .p { 35 | margin-top: 10px; 36 | width: 80%; 37 | font-size: 1rem; 38 | @include font-inter(300); 39 | color: $font-color-dark-2; 40 | } 41 | 42 | .code { 43 | display: inline; 44 | margin-top: 0; 45 | width: auto; 46 | font-size: 1rem; 47 | @include font-inter(300); 48 | color: $primary-color-orange; 49 | } 50 | 51 | a { 52 | border: none; 53 | cursor: pointer; 54 | text-decoration: none; 55 | height: 40px; 56 | width: 140px; 57 | color: $secondary-color-dark; 58 | border: solid 1px $primary-color-orange; 59 | background-color: $primary-color-orange; 60 | font-size: 0.9rem; 61 | border-radius: 3px; 62 | margin-top: 12%; 63 | transition: 0.1s linear; 64 | @include font-inter(400); 65 | @include flex-center; 66 | 67 | &:hover { 68 | background-color: $secondary-color-dark; 69 | color: $primary-color-orange; 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /client/src/scss/pages/shared/_perfilProfessor.scss: -------------------------------------------------------------------------------- 1 | main { 2 | height: calc(100vh - 80px); 3 | background-color: $primary-color-dark; 4 | @include flex-center; 5 | } 6 | -------------------------------------------------------------------------------- /client/src/services/api.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { server_url } from '../socket' 3 | 4 | const api = axios.create({ 5 | baseURL: server_url 6 | }); 7 | 8 | export default api; -------------------------------------------------------------------------------- /client/src/socket.js: -------------------------------------------------------------------------------- 1 | import { io } from "socket.io-client"; 2 | import { reactive } from 'vue'; 3 | 4 | 5 | export const server_url = "http://localhost:3333"; 6 | 7 | // export const server_url = import.meta.env.VITE_SERVER_URL; 8 | 9 | export const socket = io(server_url); 10 | 11 | export const state = reactive({ 12 | connected: false, 13 | }); 14 | 15 | socket.on("connect", () => { 16 | state.connected = true; 17 | console.log('Connected to Socket.IO server'); 18 | }); 19 | 20 | socket.on("disconnect", () => { 21 | state.connected = false; 22 | console.log('Disconnected from Socket.IO server'); 23 | }); 24 | -------------------------------------------------------------------------------- /client/src/views/admin/Dashboard.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 39 | 40 | 66 | -------------------------------------------------------------------------------- /client/src/views/funcionario/Dashboard.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 43 | 44 | -------------------------------------------------------------------------------- /client/src/views/professor/Profile.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 27 | 28 | -------------------------------------------------------------------------------- /client/src/views/professor/Rede.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/views/professor/Rede.vue -------------------------------------------------------------------------------- /client/src/views/shared/Home.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 60 | 61 | -------------------------------------------------------------------------------- /client/src/views/shared/NotFound.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 43 | 44 | -------------------------------------------------------------------------------- /client/src/views/shared/PerfilProfessor.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 27 | 28 | -------------------------------------------------------------------------------- /client/src/views/shared/Rankings.vue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VitorCarvalho67/Boot/93c7e670a71872ec1d00c7e22b1f00155af33ae4/client/src/views/shared/Rankings.vue -------------------------------------------------------------------------------- /client/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import vue from '@vitejs/plugin-vue' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [vue()], 7 | css: { 8 | preprocessorOptions: { 9 | scss: { additionalData: `@import "src/scss/main.scss";` } 10 | } 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | 3 | services: 4 | client: 5 | build: ./client 6 | ports: 7 | - "5173:5173" 8 | depends_on: 9 | - api01 10 | networks: 11 | - BOOT 12 | 13 | api: &api 14 | build: ./server 15 | deploy: 16 | resources: 17 | limits: 18 | cpus: '0.15' 19 | memory: '0.4GB' 20 | depends_on: 21 | - database 22 | networks: 23 | - BOOT 24 | 25 | api01: 26 | <<: *api 27 | ports: 28 | - "3333:3333" 29 | command: sh -c "sleep 10 && npx prisma migrate deploy" 30 | 31 | api02: 32 | <<: *api 33 | ports: 34 | - "3334:3333" 35 | 36 | api03: 37 | <<: *api 38 | ports: 39 | - "3335:3333" 40 | 41 | nginx: # Load Balancer 42 | image: nginx:latest 43 | volumes: 44 | - ./nginx.conf:/etc/nginx/nginx.conf:ro 45 | depends_on: 46 | - api02 47 | - api03 48 | deploy: 49 | resources: 50 | limits: 51 | cpus: '0.15' 52 | memory: '0.5GB' 53 | ports: 54 | - "9999:9999" 55 | networks: 56 | - BOOT 57 | 58 | minio: 59 | image: docker.io/bitnami/minio:latest 60 | ports: 61 | - "9000:9000" 62 | - "9001:9001" 63 | environment: 64 | - MINIO_ROOT_USER=your_username 65 | - MINIO_ROOT_PASSWORD=your_password 66 | - MINIO_DEFAULT_BUCKETS=boot 67 | volumes: 68 | - minio_data:/minio/data 69 | networks: 70 | - BOOT 71 | 72 | database: 73 | image: mariadb 74 | command: --default-authentication-plugin=mysql_native_password 75 | restart: always 76 | ports: 77 | - "3306:3306" 78 | environment: 79 | MYSQL_ROOT_PASSWORD: 123pass 80 | MYSQL_DATABASE: bootdb 81 | MYSQL_USER: testuser 82 | MYSQL_PASSWORD: 123pass 83 | volumes: 84 | - ./data:/var/lib/mysql 85 | networks: 86 | - BOOT 87 | 88 | networks: 89 | BOOT: 90 | 91 | volumes: 92 | minio_data: 93 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | worker_processes auto; 2 | worker_rlimit_nofile 500000; 3 | 4 | events { 5 | use epoll; 6 | worker_connections 1024; 7 | } 8 | 9 | http { 10 | access_log off; 11 | error_log /dev/null emerg; 12 | 13 | upstream backend { 14 | server api02:3334; 15 | server api03:3335; 16 | keepalive 200; 17 | } 18 | 19 | server { 20 | listen 9999; 21 | location / { 22 | proxy_buffering off; 23 | proxy_set_header Host $host; 24 | proxy_set_header X-Real-IP $remote_addr; 25 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 26 | proxy_set_header X-Forwarded-Proto $scheme; 27 | proxy_set_header Connection ""; 28 | 29 | # Simple requests 30 | if ($request_method ~* "(GET|POST)") { 31 | add_header "Access-Control-Allow-Origin" *; 32 | } 33 | 34 | # Preflighted requests 35 | if ($request_method = OPTIONS ) { 36 | add_header "Access-Control-Allow-Origin" *; 37 | add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD"; 38 | add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept"; 39 | return 200; 40 | } 41 | 42 | proxy_http_version 1.1; 43 | proxy_pass http://backend; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /server/.dockerignore: -------------------------------------------------------------------------------- 1 | node_moludes 2 | .vscode 3 | .gitignore -------------------------------------------------------------------------------- /server/.env.example: -------------------------------------------------------------------------------- 1 | DATABASE_URL="mysql://testuser:123pass@database:3306/bootdb" 2 | 3 | JWT_ACCESS_SECRET=fghjdsklghjkl 4 | 5 | EMAIL="yoursenderemail@example.com" 6 | KEY_EMAIL="your email toke napp" 7 | RECIPIENT_MAIL="youremail@example.com" 8 | 9 | URL="http://localhost:5173" 10 | 11 | MINIO_END_POINT="localhost" 12 | MINIO_ACCESS_KEY="xxxxxxxxxxxxxxxxxxxx" 13 | MINIO_SECRET_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 14 | 15 | CAPTCHA2_ID="your_captcha2_token" -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | # Keep environment variables out of version control 3 | .env 4 | data 5 | dist 6 | uploads -------------------------------------------------------------------------------- /server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:18 2 | 3 | WORKDIR /server 4 | 5 | # We don't need the standalone Chromium 6 | ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD true 7 | 8 | # Install Google Chrome Stable and fonts 9 | RUN apt-get update && apt-get install -y gnupg wget && \ 10 | wget --quiet --output-document=- https://dl-ssl.google.com/linux/linux_signing_key.pub | gpg --dearmor > /etc/apt/trusted.gpg.d/google-archive.gpg && \ 11 | sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' && \ 12 | apt-get update && \ 13 | apt-get install -y google-chrome-stable --no-install-recommends && \ 14 | rm -rf /var/lib/apt/lists/* 15 | 16 | RUN apt-get update && apt-get install -y \ 17 | wget \ 18 | gnupg2 \ 19 | fonts-liberation \ 20 | libappindicator3-1 \ 21 | libasound2 \ 22 | libcups2 \ 23 | libx11-xcb1 \ 24 | libxcomposite1 \ 25 | libxcursor1 \ 26 | libxdamage1 \ 27 | libxrandr2 \ 28 | libxss1 \ 29 | libxtst6 \ 30 | libnss3 \ 31 | libxss1 \ 32 | libxshmfence1 \ 33 | --no-install-recommends && \ 34 | rm -rf /var/lib/apt/lists/* 35 | 36 | # Set the path to the Chrome executable 37 | ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome 38 | 39 | COPY package*.json ./ 40 | COPY pnpm-lock.yaml ./ 41 | RUN npm install 42 | 43 | COPY . . 44 | RUN npx prisma generate 45 | 46 | EXPOSE 3333 47 | CMD ["npm", "run", "dev"] 48 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "dev": "ts-node-dev --exit-child --transpile-only --ignore-watch node_modules src/index.ts" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@types/express": "^4.17.21", 15 | "@types/jsonwebtoken": "^9.0.6", 16 | "@types/nodemailer": "^6.4.15", 17 | "prisma": "^5.15.0", 18 | "ts-node-dev": "^2.0.0", 19 | "typescript": "^5.4.5" 20 | }, 21 | "dependencies": { 22 | "@prisma/client": "^5.15.0", 23 | "@types/cors": "^2.8.17", 24 | "@types/multer": "^1.4.11", 25 | "@types/socket.io": "^3.0.2", 26 | "bcrypt": "^5.1.1", 27 | "cors": "^2.8.5", 28 | "dotenv": "^16.4.5", 29 | "express": "^4.19.2", 30 | "express-async-error": "^0.0.2", 31 | "express-async-errors": "^3.1.1", 32 | "html-pdf-node": "^1.0.8", 33 | "jsonwebtoken": "^9.0.2", 34 | "minio": "^8.0.0", 35 | "multer": "1.4.5-lts.1", 36 | "nodemailer": "^6.9.13", 37 | "pdf-lib": "^1.17.1", 38 | "pdf-parse": "^1.1.1", 39 | "socket.io": "^4.7.5" 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240412192902_fix_field_names/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `nome` on the `cursos` table. All the data in the column will be lost. 5 | - You are about to drop the column `nome` on the `empresas` table. All the data in the column will be lost. 6 | - You are about to drop the column `senha` on the `empresas` table. All the data in the column will be lost. 7 | - Added the required column `name` to the `cursos` table without a default value. This is not possible if the table is not empty. 8 | - Added the required column `name` to the `empresas` table without a default value. This is not possible if the table is not empty. 9 | - Added the required column `password` to the `empresas` table without a default value. This is not possible if the table is not empty. 10 | 11 | */ 12 | -- AlterTable 13 | ALTER TABLE `cursos` DROP COLUMN `nome`, 14 | ADD COLUMN `name` VARCHAR(191) NOT NULL; 15 | 16 | -- AlterTable 17 | ALTER TABLE `empresas` DROP COLUMN `nome`, 18 | DROP COLUMN `senha`, 19 | ADD COLUMN `name` VARCHAR(191) NOT NULL, 20 | ADD COLUMN `password` VARCHAR(191) NOT NULL; 21 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240416002008_add_pre_aluno_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE `pre_alunos` ( 3 | `id` VARCHAR(191) NOT NULL, 4 | `email` VARCHAR(191) NOT NULL, 5 | `token` VARCHAR(191) NOT NULL, 6 | `tentativas` INTEGER NOT NULL, 7 | `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), 8 | `updatedAt` DATETIME(3) NOT NULL, 9 | 10 | PRIMARY KEY (`id`) 11 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 12 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240416002554_update_pre_aluno_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `tentativas` on the `pre_alunos` table. All the data in the column will be lost. 5 | - Added the required column `name` to the `pre_alunos` table without a default value. This is not possible if the table is not empty. 6 | - Added the required column `password` to the `pre_alunos` table without a default value. This is not possible if the table is not empty. 7 | 8 | */ 9 | -- AlterTable 10 | ALTER TABLE `pre_alunos` DROP COLUMN `tentativas`, 11 | ADD COLUMN `name` VARCHAR(191) NOT NULL, 12 | ADD COLUMN `password` VARCHAR(191) NOT NULL, 13 | ADD COLUMN `tentativasRestantes` INTEGER NOT NULL DEFAULT 5; 14 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240416003534_update_pre_aluno_email/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - A unique constraint covering the columns `[email]` on the table `pre_alunos` will be added. If there are existing duplicate values, this will fail. 5 | 6 | */ 7 | -- CreateIndex 8 | CREATE UNIQUE INDEX `pre_alunos_email_key` ON `pre_alunos`(`email`); 9 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240422143505_add_aluno_new_column/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `alunos` ADD COLUMN `recoverypass` VARCHAR(191) NULL; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240422143704_fix_aluno_column_name/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `recoverypass` on the `alunos` table. All the data in the column will be lost. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE `alunos` DROP COLUMN `recoverypass`, 9 | ADD COLUMN `recoveryPass` VARCHAR(191) NULL; 10 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240423220555_add_curso_new_column/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `coordenador` to the `cursos` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE `cursos` ADD COLUMN `coordenador` VARCHAR(191) NOT NULL; 9 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240423223207_remove_curso_periodo/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `periodo` on the `cursos` table. All the data in the column will be lost. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE `cursos` DROP COLUMN `periodo`; 9 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240424234133_add_professor_and_coordenador_tables/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE `professores` ( 3 | `id` VARCHAR(191) NOT NULL, 4 | `name` VARCHAR(191) NOT NULL, 5 | `email` VARCHAR(191) NOT NULL, 6 | `password` VARCHAR(191) NOT NULL, 7 | `token` VARCHAR(191) NOT NULL, 8 | `tentativasRestantes` INTEGER NOT NULL DEFAULT 5, 9 | `titulo_principal` VARCHAR(191) NOT NULL, 10 | `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), 11 | `updatedAt` DATETIME(3) NOT NULL, 12 | 13 | UNIQUE INDEX `professores_email_key`(`email`), 14 | PRIMARY KEY (`id`) 15 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 16 | 17 | -- CreateTable 18 | CREATE TABLE `coordenadores` ( 19 | `id` VARCHAR(191) NOT NULL, 20 | `name` VARCHAR(191) NOT NULL, 21 | `email` VARCHAR(191) NOT NULL, 22 | `password` VARCHAR(191) NOT NULL, 23 | `token` VARCHAR(191) NOT NULL, 24 | `tentativasRestantes` INTEGER NOT NULL DEFAULT 5, 25 | `professorId` VARCHAR(191) NOT NULL, 26 | `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), 27 | `updatedAt` DATETIME(3) NOT NULL, 28 | 29 | UNIQUE INDEX `coordenadores_email_key`(`email`), 30 | PRIMARY KEY (`id`) 31 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 32 | 33 | -- AddForeignKey 34 | ALTER TABLE `coordenadores` ADD CONSTRAINT `coordenadores_professorId_fkey` FOREIGN KEY (`professorId`) REFERENCES `professores`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 35 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240425215818_fix_error_column_name/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `titulo_principal` on the `professores` table. All the data in the column will be lost. 5 | - Added the required column `tituloPrincipal` to the `professores` table without a default value. This is not possible if the table is not empty. 6 | 7 | */ 8 | -- AlterTable 9 | ALTER TABLE `professores` DROP COLUMN `titulo_principal`, 10 | ADD COLUMN `tituloPrincipal` VARCHAR(191) NOT NULL; 11 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240425220631_fix_email_column_in_professor_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - A unique constraint covering the columns `[email]` on the table `funcionarios` will be added. If there are existing duplicate values, this will fail. 5 | 6 | */ 7 | -- CreateIndex 8 | CREATE UNIQUE INDEX `funcionarios_email_key` ON `funcionarios`(`email`); 9 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240429212723_fix_cargo_enum/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - The values [ADMINTRACAO] on the enum `funcionarios_cargo` will be removed. If these variants are still used in the database, this will fail. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE `funcionarios` MODIFY `cargo` ENUM('GESTAO', 'ADMINISTRACAO', 'DIRECAO', 'ORIENTACAO') NOT NULL; 9 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240430185547_add_new_professor_column/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to alter the column `dataNascimento` on the `alunos` table. The data in that column could be lost. The data in that column will be cast from `VarChar(191)` to `DateTime(3)`. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE `alunos` MODIFY `dataNascimento` DATETIME(3) NULL; 9 | 10 | -- AlterTable 11 | ALTER TABLE `professores` ADD COLUMN `validated` BOOLEAN NOT NULL DEFAULT false; 12 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240503160551_add_funcionario_validated_column/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `funcionarios` ADD COLUMN `validated` BOOLEAN NOT NULL DEFAULT false; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240507003915_add_tentativas_restantes_column_on_tables/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `alunos` ADD COLUMN `tentativasRestantes` INTEGER NOT NULL DEFAULT 5; 3 | 4 | -- AlterTable 5 | ALTER TABLE `funcionarios` ADD COLUMN `recoveryPass` VARCHAR(191) NULL, 6 | ADD COLUMN `tentativasRestantes` INTEGER NOT NULL DEFAULT 5; 7 | 8 | -- AlterTable 9 | ALTER TABLE `professores` ADD COLUMN `recoveryPass` VARCHAR(191) NULL, 10 | ADD COLUMN `tentativasRestantes` INTEGER NOT NULL DEFAULT 5; 11 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240509012700_fix_empresa_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `empresas` ADD COLUMN `token` VARCHAR(191) NULL, 3 | MODIFY `endereco` VARCHAR(191) NULL, 4 | MODIFY `telefone` VARCHAR(191) NULL; 5 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240509020030_updade_patrocinador_empresa_column/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `empresas` MODIFY `patrocinador` BOOLEAN NOT NULL DEFAULT false; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240509145838_add_empresa_validated_column/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `empresas` ADD COLUMN `validated` BOOLEAN NOT NULL DEFAULT false; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240509150241_add_empresatentativas_restantes_column/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `empresas` ADD COLUMN `tentativasRestantes` INTEGER NOT NULL DEFAULT 5; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240509151050_fix_empresa_cnpj_column/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - A unique constraint covering the columns `[cnpj]` on the table `empresas` will be added. If there are existing duplicate values, this will fail. 5 | 6 | */ 7 | -- CreateIndex 8 | CREATE UNIQUE INDEX `empresas_cnpj_key` ON `empresas`(`cnpj`); 9 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240521003302_add_new_table_vincolos_and_addcolumns/migration.sql: -------------------------------------------------------------------------------- 1 | -- SQLBook: Code 2 | /* 3 | Warnings: 4 | 5 | - You are about to drop the column `disciplina` on the `alunos` table. All the data in the column will be lost. 6 | 7 | */ 8 | -- AlterTable 9 | ALTER TABLE `alunos` DROP COLUMN `disciplina`, 10 | ADD COLUMN `bannerImagem` VARCHAR(191) NULL, 11 | ADD COLUMN `curriculo` VARCHAR(191) NULL, 12 | ADD COLUMN `endereco` VARCHAR(191) NULL, 13 | ADD COLUMN `sobre` VARCHAR(191) NULL; 14 | 15 | -- CreateTable 16 | CREATE TABLE `vinculos` ( 17 | `id` VARCHAR(191) NOT NULL, 18 | `alunoId` VARCHAR(191) NULL, 19 | `professorId` VARCHAR(191) NULL, 20 | `vinculoComAlunoId` VARCHAR(191) NULL, 21 | `vinculoComProfessorId` VARCHAR(191) NULL, 22 | `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), 23 | `updatedAt` DATETIME(3) NOT NULL, 24 | 25 | UNIQUE INDEX `vinculos_alunoId_professorId_vinculoComAlunoId_vinculoComPro_key`(`alunoId`, `professorId`, `vinculoComAlunoId`, `vinculoComProfessorId`), 26 | PRIMARY KEY (`id`) 27 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 28 | 29 | -- AddForeignKey 30 | ALTER TABLE `vinculos` ADD CONSTRAINT `vinculos_alunoId_fkey` FOREIGN KEY (`alunoId`) REFERENCES `alunos`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; 31 | 32 | -- AddForeignKey 33 | ALTER TABLE `vinculos` ADD CONSTRAINT `vinculos_professorId_fkey` FOREIGN KEY (`professorId`) REFERENCES `professores`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; 34 | 35 | -- AddForeignKey 36 | ALTER TABLE `vinculos` ADD CONSTRAINT `vinculos_vinculoComAlunoId_fkey` FOREIGN KEY (`vinculoComAlunoId`) REFERENCES `alunos`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; 37 | 38 | -- AddForeignKey 39 | ALTER TABLE `vinculos` ADD CONSTRAINT `vinculos_vinculoComProfessorId_fkey` FOREIGN KEY (`vinculoComProfessorId`) REFERENCES `professores`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; 40 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240524172824_add_accepted_column_on_vinculo_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - A unique constraint covering the columns `[rm]` on the table `alunos` will be added. If there are existing duplicate values, this will fail. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE `vinculos` ADD COLUMN `accepted` BOOLEAN NOT NULL DEFAULT false; 9 | 10 | -- CreateIndex 11 | CREATE UNIQUE INDEX `alunos_rm_key` ON `alunos`(`rm`); 12 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240601200546_update_curriculo_column_aluno_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `alunos` MODIFY `curriculo` VARCHAR(5000) NULL DEFAULT ''; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240603211401_remove_pre_aluno_add_turma_aluno_and_extra_curricular_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `turmas` on the `alunos` table. All the data in the column will be lost. 5 | - You are about to drop the `pre_alunos` table. If the table is not empty, all the data it contains will be lost. 6 | 7 | */ 8 | -- AlterTable 9 | ALTER TABLE `alunos` DROP COLUMN `turmas`, 10 | ADD COLUMN `token` VARCHAR(191) NULL, 11 | ADD COLUMN `validated` BOOLEAN NOT NULL DEFAULT false; 12 | 13 | -- DropTable 14 | DROP TABLE `pre_alunos`; 15 | 16 | -- CreateTable 17 | CREATE TABLE `alunos_turmas` ( 18 | `alunoId` VARCHAR(191) NOT NULL, 19 | `turmaId` VARCHAR(191) NOT NULL, 20 | 21 | PRIMARY KEY (`alunoId`, `turmaId`) 22 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 23 | 24 | -- CreateTable 25 | CREATE TABLE `extracurriculares` ( 26 | `extracurricularId` VARCHAR(191) NOT NULL, 27 | `alunoId` VARCHAR(191) NOT NULL, 28 | `instituicao` VARCHAR(191) NOT NULL, 29 | `descricao` VARCHAR(191) NOT NULL, 30 | `inicio` DATETIME(3) NOT NULL, 31 | `fim` DATETIME(3) NOT NULL, 32 | `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), 33 | `updatedAt` DATETIME(3) NOT NULL, 34 | 35 | PRIMARY KEY (`extracurricularId`) 36 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 37 | 38 | -- AddForeignKey 39 | ALTER TABLE `alunos_turmas` ADD CONSTRAINT `alunos_turmas_alunoId_fkey` FOREIGN KEY (`alunoId`) REFERENCES `alunos`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 40 | 41 | -- AddForeignKey 42 | ALTER TABLE `alunos_turmas` ADD CONSTRAINT `alunos_turmas_turmaId_fkey` FOREIGN KEY (`turmaId`) REFERENCES `turmas`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 43 | 44 | -- AddForeignKey 45 | ALTER TABLE `extracurriculares` ADD CONSTRAINT `extracurriculares_alunoId_fkey` FOREIGN KEY (`alunoId`) REFERENCES `alunos`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 46 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240610234129_add_banner_on_professor_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `adminImagem` on the `admins` table. All the data in the column will be lost. 5 | - You are about to drop the column `alunoImagem` on the `alunos` table. All the data in the column will be lost. 6 | - You are about to drop the column `bannerImagem` on the `alunos` table. All the data in the column will be lost. 7 | - You are about to drop the column `atividadeImagem` on the `atividades` table. All the data in the column will be lost. 8 | - You are about to drop the column `empresaImagem` on the `empresas` table. All the data in the column will be lost. 9 | - You are about to drop the column `funcionarioImagem` on the `funcionarios` table. All the data in the column will be lost. 10 | - You are about to drop the column `professorImagem` on the `professores` table. All the data in the column will be lost. 11 | 12 | */ 13 | -- AlterTable 14 | ALTER TABLE `admins` DROP COLUMN `adminImagem`, 15 | ADD COLUMN `imagem` VARCHAR(191) NULL; 16 | 17 | -- AlterTable 18 | ALTER TABLE `alunos` DROP COLUMN `alunoImagem`, 19 | DROP COLUMN `bannerImagem`, 20 | ADD COLUMN `banner` VARCHAR(191) NULL, 21 | ADD COLUMN `imagem` VARCHAR(191) NULL; 22 | 23 | -- AlterTable 24 | ALTER TABLE `atividades` DROP COLUMN `atividadeImagem`, 25 | ADD COLUMN `imagem` VARCHAR(191) NULL; 26 | 27 | -- AlterTable 28 | ALTER TABLE `empresas` DROP COLUMN `empresaImagem`, 29 | ADD COLUMN `imagem` VARCHAR(191) NULL; 30 | 31 | -- AlterTable 32 | ALTER TABLE `funcionarios` DROP COLUMN `funcionarioImagem`, 33 | ADD COLUMN `imagem` VARCHAR(191) NULL; 34 | 35 | -- AlterTable 36 | ALTER TABLE `professores` DROP COLUMN `professorImagem`, 37 | ADD COLUMN `banner` VARCHAR(191) NULL, 38 | ADD COLUMN `imagem` VARCHAR(191) NULL; 39 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240706180957_add_title_label_on_vagas_table/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - Added the required column `titulo` to the `vagas` table without a default value. This is not possible if the table is not empty. 5 | 6 | */ 7 | -- AlterTable 8 | ALTER TABLE `vagas` ADD COLUMN `titulo` VARCHAR(191) NOT NULL; 9 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240706193450_fix_vaga_table_fields/migration.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Warnings: 3 | 4 | - You are about to drop the column `dataFim` on the `vagas` table. All the data in the column will be lost. 5 | - You are about to drop the column `dataInicio` on the `vagas` table. All the data in the column will be lost. 6 | - Added the required column `descricao` to the `vagas` table without a default value. This is not possible if the table is not empty. 7 | - Added the required column `entrada` to the `vagas` table without a default value. This is not possible if the table is not empty. 8 | - Added the required column `saida` to the `vagas` table without a default value. This is not possible if the table is not empty. 9 | 10 | */ 11 | -- AlterTable 12 | ALTER TABLE `vagas` DROP COLUMN `dataFim`, 13 | DROP COLUMN `dataInicio`, 14 | ADD COLUMN `descricao` VARCHAR(191) NOT NULL, 15 | ADD COLUMN `entrada` VARCHAR(191) NOT NULL, 16 | ADD COLUMN `saida` VARCHAR(191) NOT NULL; 17 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240731003618_add_aluno_atividade_relation_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE `alunos_atividades` ( 3 | `alunoId` VARCHAR(191) NOT NULL, 4 | `atividadeId` VARCHAR(191) NOT NULL, 5 | `mencao` ENUM('I', 'R', 'B', 'MB') NOT NULL, 6 | 7 | PRIMARY KEY (`alunoId`, `atividadeId`) 8 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 9 | 10 | -- AddForeignKey 11 | ALTER TABLE `alunos_atividades` ADD CONSTRAINT `alunos_atividades_alunoId_fkey` FOREIGN KEY (`alunoId`) REFERENCES `alunos`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 12 | 13 | -- AddForeignKey 14 | ALTER TABLE `alunos_atividades` ADD CONSTRAINT `alunos_atividades_atividadeId_fkey` FOREIGN KEY (`atividadeId`) REFERENCES `atividades`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 15 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240803010917_create_boletins_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE `boletins` ( 3 | `id` VARCHAR(191) NOT NULL, 4 | `alunoId` VARCHAR(191) NOT NULL, 5 | `link` VARCHAR(191) NOT NULL, 6 | `caminho` VARCHAR(191) NOT NULL, 7 | `status` ENUM('EM_ANALISE', 'RECUSADO', 'APROVADO') NOT NULL DEFAULT 'EM_ANALISE', 8 | 9 | PRIMARY KEY (`id`) 10 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 11 | 12 | -- AddForeignKey 13 | ALTER TABLE `boletins` ADD CONSTRAINT `boletins_alunoId_fkey` FOREIGN KEY (`alunoId`) REFERENCES `alunos`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 14 | -------------------------------------------------------------------------------- /server/prisma/migrations/20240804231659_add_notas_and_materias_tables/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE `materias` ( 3 | `id` VARCHAR(191) NOT NULL, 4 | `name` VARCHAR(191) NOT NULL, 5 | `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), 6 | `updatedAt` DATETIME(3) NOT NULL, 7 | 8 | PRIMARY KEY (`id`) 9 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 10 | 11 | -- CreateTable 12 | CREATE TABLE `cursos_materias` ( 13 | `cursoId` VARCHAR(191) NOT NULL, 14 | `materiaId` VARCHAR(191) NOT NULL, 15 | 16 | PRIMARY KEY (`cursoId`, `materiaId`) 17 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 18 | 19 | -- CreateTable 20 | CREATE TABLE `notas` ( 21 | `id` VARCHAR(191) NOT NULL, 22 | `alunoId` VARCHAR(191) NOT NULL, 23 | `materiaId` VARCHAR(191) NOT NULL, 24 | `bimestre` INTEGER NOT NULL, 25 | `ano` INTEGER NOT NULL, 26 | `mencao` ENUM('I', 'R', 'B', 'MB') NOT NULL, 27 | `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), 28 | `updatedAt` DATETIME(3) NOT NULL, 29 | 30 | PRIMARY KEY (`id`) 31 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 32 | 33 | -- AddForeignKey 34 | ALTER TABLE `cursos_materias` ADD CONSTRAINT `cursos_materias_cursoId_fkey` FOREIGN KEY (`cursoId`) REFERENCES `cursos`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 35 | 36 | -- AddForeignKey 37 | ALTER TABLE `cursos_materias` ADD CONSTRAINT `cursos_materias_materiaId_fkey` FOREIGN KEY (`materiaId`) REFERENCES `materias`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 38 | 39 | -- AddForeignKey 40 | ALTER TABLE `notas` ADD CONSTRAINT `notas_alunoId_fkey` FOREIGN KEY (`alunoId`) REFERENCES `alunos`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 41 | 42 | -- AddForeignKey 43 | ALTER TABLE `notas` ADD CONSTRAINT `notas_materiaId_fkey` FOREIGN KEY (`materiaId`) REFERENCES `materias`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE; 44 | -------------------------------------------------------------------------------- /server/prisma/migrations/20241016131941_add_notificacao_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- CreateTable 2 | CREATE TABLE `notificacoes` ( 3 | `id` VARCHAR(191) NOT NULL, 4 | `titulo` VARCHAR(191) NOT NULL, 5 | `descricao` VARCHAR(191) NOT NULL, 6 | `criadorId` VARCHAR(191) NOT NULL, 7 | `recipientEmails` JSON NOT NULL, 8 | `tipo` ENUM('MENSAGEM', 'SOLICITACAO', 'ESTAGIO', 'ATVIDADE') NOT NULL, 9 | `dispensada` BOOLEAN NOT NULL DEFAULT false, 10 | `mensagemId` VARCHAR(191) NULL, 11 | `estagioId` VARCHAR(191) NULL, 12 | `vinculoId` VARCHAR(191) NULL, 13 | `criador` ENUM('ALUNO', 'EMPRESA', 'FUNCIONARIO', 'PROFESSOR') NOT NULL, 14 | `receptor` ENUM('ALUNO', 'EMPRESA', 'FUNCIONARIO', 'PROFESSOR') NOT NULL, 15 | `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), 16 | `updatedAt` DATETIME(3) NOT NULL, 17 | 18 | PRIMARY KEY (`id`) 19 | ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 20 | 21 | -- AddForeignKey 22 | ALTER TABLE `notificacoes` ADD CONSTRAINT `notificacoes_mensagemId_fkey` FOREIGN KEY (`mensagemId`) REFERENCES `mensagens`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; 23 | 24 | -- AddForeignKey 25 | ALTER TABLE `notificacoes` ADD CONSTRAINT `notificacoes_estagioId_fkey` FOREIGN KEY (`estagioId`) REFERENCES `vagas`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; 26 | 27 | -- AddForeignKey 28 | ALTER TABLE `notificacoes` ADD CONSTRAINT `notificacoes_vinculoId_fkey` FOREIGN KEY (`vinculoId`) REFERENCES `vinculos`(`id`) ON DELETE SET NULL ON UPDATE CASCADE; 29 | -------------------------------------------------------------------------------- /server/prisma/migrations/20241030201222_add_telefone_field_on_aluno_table/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `alunos` ADD COLUMN `telefone` VARCHAR(191) NULL; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20241031194037_add_boletim_notification_type/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `notificacoes` MODIFY `tipo` ENUM('MENSAGEM', 'SOLICITACAO', 'ESTAGIO', 'ATVIDADE', 'BOLETIM') NOT NULL; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20241123155243_add_banner_field_empresa/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `empresas` ADD COLUMN `banner` VARCHAR(191) NULL; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20241123175644_add_site_field_empresa/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `empresas` ADD COLUMN `site` VARCHAR(191) NULL; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/20241124224106_add_sobre_fiel_professor/migration.sql: -------------------------------------------------------------------------------- 1 | -- AlterTable 2 | ALTER TABLE `professores` ADD COLUMN `curriculo` VARCHAR(191) NULL; 3 | -------------------------------------------------------------------------------- /server/prisma/migrations/migration_lock.toml: -------------------------------------------------------------------------------- 1 | # Please do not edit this file manually 2 | # It should be added in your version-control system (i.e. Git) 3 | provider = "mysql" -------------------------------------------------------------------------------- /server/src/connection/controllers/entryController.ts: -------------------------------------------------------------------------------- 1 | import { Server, Socket } from 'socket.io'; 2 | import { validateTokenAluno, validateTokenEmpresa, validateTokenProfessor } from '../../middleware/auth/socket'; 3 | 4 | interface dataDTO{ 5 | email: string, 6 | type: string, 7 | authorization: string 8 | } 9 | 10 | export const enter = async (io: Server, socket: Socket, data: dataDTO) => { 11 | try { 12 | const token = data.authorization; 13 | let decoded; 14 | 15 | if(data.type == "EMPRESA"){ 16 | decoded = await validateTokenEmpresa(token) as any; 17 | } 18 | if(data.type == "ALUNO"){ 19 | decoded = await validateTokenAluno(token) as any; 20 | } 21 | if(data.type == "PROFESSOR"){ 22 | decoded = await validateTokenProfessor(token) as any; 23 | } 24 | 25 | if (!decoded) { 26 | console.log('Token inválido para enter-vinculo-aluno'); 27 | // socket.emit('error', { message: 'Invalid token' }); 28 | return; 29 | } 30 | console.log(`Usuário de email ${decoded.email} registrado`); 31 | socket.join(decoded.email); 32 | 33 | console.log('Nova entrada', data); 34 | } catch (error) { 35 | console.log('Erro em enter-vinculo-aluno handler:', error); 36 | } 37 | }; -------------------------------------------------------------------------------- /server/src/connection/controllers/messageControllers.ts: -------------------------------------------------------------------------------- 1 | import { Server, Socket } from 'socket.io'; 2 | import { 3 | validateTokenAluno, 4 | validateTokenEmpresa, 5 | validateTokenProfessor, 6 | } from '../../middleware/auth/socket'; 7 | 8 | import { IdentificadorEnum } from '../../modules/interfaces/sharedDTOs'; 9 | 10 | interface dataDTO { 11 | message: { 12 | conteudo: string; 13 | email: string; 14 | identifier: string; 15 | }; 16 | sender: string; 17 | authorization: string; 18 | } 19 | 20 | export const sendMessage = async (io: Server, socket: Socket, data: dataDTO) => { 21 | try { 22 | const token = data.authorization; 23 | 24 | let decoded = await validateTokenAluno(token) as any; 25 | 26 | if (!decoded) { 27 | let decoded = await validateTokenEmpresa(token) as any; 28 | 29 | if (!decoded) { 30 | let decoded = await validateTokenProfessor(token) as any; 31 | 32 | if (!decoded) { 33 | console.log('Token inválido para enter-vinculo-aluno'); 34 | // socket.emit('error', { message: 'Invalid token' }); 35 | return; 36 | } 37 | } 38 | } 39 | 40 | 41 | if (!decoded) { 42 | console.log('Token inválido para sendMessage'); 43 | return; 44 | } 45 | 46 | console.log('Nova mensagem para: ' + data.message.email); 47 | io.to(data.message.email).emit('new-message', data.message); 48 | } catch (error) { 49 | console.log('Erro em sendMessage handler:', error); 50 | } 51 | }; 52 | -------------------------------------------------------------------------------- /server/src/connection/controllers/notificationController.ts: -------------------------------------------------------------------------------- 1 | import { Server, Socket } from 'socket.io'; 2 | import { validateTokenAluno, validateTokenProfessor, validateTokenFuncionario} from '../../middleware/auth/socket'; 3 | import { EntidadeEnum } from '../../modules/interfaces/sharedDTOs'; 4 | 5 | interface dataDTO{ 6 | notification:{ 7 | title: string, 8 | descricao: string, 9 | email: string, 10 | identifier: EntidadeEnum, 11 | senderIdentifier: EntidadeEnum, 12 | createdAt: string 13 | }, 14 | authorization: string 15 | } 16 | 17 | export const sendNotification = async (io: Server, socket: Socket, data: dataDTO) => { 18 | try { 19 | const token = data.authorization; 20 | const entidade = EntidadeEnum[data.notification.identifier] 21 | 22 | const decoded = entidade == "ALUNO" ? 23 | await validateTokenAluno(token): 24 | data.notification.identifier == "FUNCIONARIO"? 25 | await validateTokenFuncionario(token): 26 | data.notification.identifier == "PROFESSOR" ? 27 | await validateTokenProfessor(token): 28 | null; 29 | 30 | 31 | if (!decoded) { 32 | console.log('Token inválido para send-notification ou entidade "'+ data.notification.identifier +'" inválida para notificar.'); 33 | // socket.emit('error', { message: 'Invalid token' }); 34 | return; 35 | } 36 | 37 | console.log('Notificação para: ' + data.notification.email); 38 | io.to(data.notification.email).emit('new-notification', data.notification); 39 | } catch (error) { 40 | console.log('Erro em send-notification handler:', error); 41 | } 42 | }; -------------------------------------------------------------------------------- /server/src/connection/controllers/vinculoController.ts: -------------------------------------------------------------------------------- 1 | import { Server, Socket } from 'socket.io'; 2 | import { validateTokenAluno } from '../../middleware/auth/socket'; 3 | 4 | interface dataDTO{ 5 | email: string, 6 | type: string, 7 | authorization: string 8 | } 9 | 10 | export const vinculoUpdate = async (io: Server, socket: Socket, data: dataDTO) => { 11 | try { 12 | const token = data.authorization; 13 | const decoded = await validateTokenAluno(token); 14 | 15 | if (!decoded) { 16 | console.log('Token inválido para vinculo-update'); 17 | socket.emit('error', { message: 'Invalid token' }); 18 | return; 19 | } 20 | 21 | console.log('Novo vinculo-update', data); 22 | io.to(data.email).emit('vinculo-update', data); 23 | } catch (error) { 24 | console.log('Erro em vinculo-update handler:', error); 25 | } 26 | }; -------------------------------------------------------------------------------- /server/src/connection/router/sokcets.routes.ts: -------------------------------------------------------------------------------- 1 | import { Server, Socket } from 'socket.io'; 2 | 3 | import { enter } from '../controllers/entryController'; 4 | import { vinculoUpdate } from '../controllers/vinculoController'; 5 | import { sendMessage } from '../controllers/messageControllers'; 6 | import { sendNotification } from '../controllers/notificationController'; 7 | 8 | const enterRoutes = (io: Server, socket: Socket) => { 9 | socket.on('enter', (data) => { enter(io, socket, data); }); 10 | } 11 | const vinculoRoutes = (io: Server, socket: Socket) => { 12 | socket.on('vinculo-update', (data) => { vinculoUpdate(io, socket, data); }); 13 | } 14 | 15 | const messageRoutes = (io: Server, socket: Socket) => { 16 | socket.on('send-message', (data) => { sendMessage(io, socket, data); }); 17 | } 18 | 19 | const notificationRoutes = (io: Server, socket: Socket) => { 20 | socket.on('send-notification', (data) => { sendNotification(io, socket, data); }); 21 | } 22 | 23 | const disconnectRoute = (io: Server, socket: Socket) => { 24 | socket.on('disconnect', () => { console.log(`User disconnected: ${socket.id}`); }); 25 | } 26 | 27 | export const router = [ 28 | enterRoutes, 29 | vinculoRoutes, 30 | messageRoutes, 31 | notificationRoutes, 32 | disconnectRoute 33 | ] -------------------------------------------------------------------------------- /server/src/connection/socket.ts: -------------------------------------------------------------------------------- 1 | import { Server, Socket } from 'socket.io'; 2 | import { router } from './router/sokcets.routes'; 3 | 4 | export default async function appSocket (io: Server) { 5 | io.on('connection', (socket: Socket) => { 6 | console.log(`User connected: ${socket.id}`); 7 | router.forEach(route => route(io, socket)); 8 | }); 9 | } -------------------------------------------------------------------------------- /server/src/errors/error.ts: -------------------------------------------------------------------------------- 1 | export class AppError { 2 | public readonly message: string; 3 | public readonly statusCode: number; 4 | 5 | constructor(message: string, statusCode = 400) { 6 | this.message = message; 7 | this.statusCode = statusCode; 8 | 9 | console.log(message + " " + statusCode); 10 | } 11 | } -------------------------------------------------------------------------------- /server/src/index.ts: -------------------------------------------------------------------------------- 1 | import "express-async-errors"; 2 | import express, { Request, Response, NextFunction } from 'express'; 3 | import cors from 'cors'; 4 | import { routes } from "./router"; 5 | import { AppError } from './errors/error'; 6 | import { Server } from 'socket.io'; 7 | import http from 'http'; 8 | import appSocket from "./connection/socket"; 9 | 10 | const app = express(); 11 | const port = 3333; 12 | 13 | app.use(cors()); 14 | app.use(express.json()); 15 | app.use(routes); 16 | 17 | app.use((err: Error, request: Request, response: Response, next: NextFunction) => { 18 | if (err instanceof AppError) { 19 | response.status(err.statusCode).json({ 20 | status: "error", 21 | message: err.message 22 | }); 23 | } else { 24 | response.status(500).json({ 25 | status: "error", 26 | message: `Internal server error - ${err.message}` 27 | }); 28 | } 29 | }); 30 | 31 | const httpServer = http.createServer(app); 32 | 33 | const io = new Server(httpServer, { 34 | cors: { 35 | origin: ["http://localhost:5173", "https://boot.portfolioeducacionalrgs.com", "https://bootminio.portfolioeducacionalrgs.com", "https://bootserver.portfolioeducacionalrgs.com", "http://192.168.100.10:5173", "http://192.168.56.1:5173"], 36 | methods: ["GET", "POST"] 37 | } 38 | }); 39 | 40 | appSocket(io); 41 | 42 | httpServer.listen(port, () => { 43 | console.log(`Server is running on port ${port} 🚀\nDatabase URL: ${process.env.DATABASE_URL}`); 44 | }); 45 | -------------------------------------------------------------------------------- /server/src/jwt/jwtServices.ts: -------------------------------------------------------------------------------- 1 | import { sign, verify, JwtPayload } from "jsonwebtoken"; 2 | import { Aluno, Admin, Professor, Funcionario, Empresa } from "@prisma/client"; 3 | 4 | export function generateAccessTokenAluno(aluno: Aluno): string { 5 | return sign({ alunoId: aluno.id }, process.env.JWT_ACCESS_SECRET as string, { 6 | expiresIn: '30 days', 7 | }); 8 | } 9 | 10 | export function generateAccessTokenAdmin(admin: Admin): string { 11 | return sign({ adminId: admin.id }, process.env.JWT_ACCESS_SECRET as string, { 12 | expiresIn: '50m', 13 | }); 14 | } 15 | 16 | export function generateAccessTokenProfessor(professor: Professor): string { 17 | return sign({ professorId: professor.id }, process.env.JWT_ACCESS_SECRET as string, { 18 | expiresIn: '30 days', 19 | }); 20 | } 21 | 22 | export function generateAccessTokenFuncionario(funcionario: Funcionario): string { 23 | return sign({ funcionarioId: funcionario.id }, process.env.JWT_ACCESS_SECRET as string, { 24 | expiresIn: '30 days', 25 | }); 26 | } 27 | 28 | export function generateAccessTokenEmpresa(empresa: Empresa): string { 29 | return sign({ empresaId: empresa.id }, process.env.JWT_ACCESS_SECRET as string, { 30 | expiresIn: '30 days', 31 | }); 32 | } 33 | 34 | export function verfifyAccessTokenAluno(token: string): string | JwtPayload { 35 | return verify(token, process.env.JWT_ACCESS_SECRET as string); 36 | } 37 | 38 | export function verfifyAccessTokenAdmin(token: string): string | JwtPayload { 39 | return verify(token, process.env.JWT_ACCESS_SECRET as string); 40 | } 41 | 42 | export function verfifyAccessTokenProfessor(token: string): string | JwtPayload { 43 | return verify(token, process.env.JWT_ACCESS_SECRET as string); 44 | } 45 | 46 | export function verfifyAccessTokenFuncinario(token: string): string | JwtPayload { 47 | return verify(token, process.env.JWT_ACCESS_SECRET as string); 48 | } 49 | 50 | export function verfifyAccessTokenEmpresa(token: string): string | JwtPayload { 51 | return verify(token, process.env.JWT_ACCESS_SECRET as string); 52 | } -------------------------------------------------------------------------------- /server/src/mail/config/email.ts: -------------------------------------------------------------------------------- 1 | import nodemailer from 'nodemailer'; 2 | 3 | const transporter = nodemailer.createTransport({ 4 | service: 'gmail', 5 | host: 'smtp.gmail.com', 6 | port: 465, 7 | secure: true, 8 | auth: { 9 | user: process.env.EMAIL, 10 | pass: process.env.KEY_EMAIL 11 | }, 12 | tls: { 13 | rejectUnauthorized: false 14 | } 15 | }); 16 | 17 | export default transporter; -------------------------------------------------------------------------------- /server/src/minioService.ts: -------------------------------------------------------------------------------- 1 | import { Client, ClientOptions } from "minio"; 2 | import { AppError } from './errors/error'; 3 | import { promisify } from 'util'; 4 | import fs from 'fs'; 5 | import stream from 'stream'; 6 | 7 | export const minioClient = new Client({ 8 | endPoint: process.env.MINIO_END_POINT as string, 9 | port: 9000, 10 | useSSL: false, 11 | accessKey: process.env.MINIO_ACCESS_KEY as string, 12 | secretKey: process.env.MINIO_SECRET_KEY as string 13 | }); 14 | 15 | import * as path from 'path'; 16 | 17 | export const uploadToMinio = async (bucketName: string, objectName: string, filePath: string) => { 18 | try { 19 | const ext = path.extname(filePath).toLowerCase(); 20 | let contentType; 21 | 22 | switch (ext) { 23 | case '.jpeg': 24 | case '.jpg': 25 | contentType = 'image/jpeg'; 26 | break; 27 | case '.png': 28 | contentType = 'image/png'; 29 | break; 30 | case '.pdf': 31 | contentType = 'application/pdf'; 32 | break; 33 | default: 34 | contentType = 'application/octet-stream'; 35 | break; 36 | } 37 | 38 | await minioClient.fPutObject(bucketName, objectName, filePath, { 39 | 'Content-Type': contentType, 40 | }); 41 | 42 | return `File uploaded successfully.`; 43 | } catch (error) { 44 | throw new AppError(`Error uploading file: ${error}`); 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /server/src/modules/interfaces/adminDTOs.ts: -------------------------------------------------------------------------------- 1 | export interface LoginAdminDTO { 2 | email: string, 3 | password: string 4 | } 5 | 6 | export interface RegisterCoordenadorDTO { 7 | name: string 8 | } 9 | 10 | export interface RegisterCursosDTO { 11 | cursoName: string, 12 | turno: Turno, 13 | duracao: string, 14 | coordenador: string 15 | } 16 | 17 | enum Turno { 18 | Manha = "MANHA", 19 | Tarde = "TARDE", 20 | Noite = "NOITE", 21 | Integral = "INTEGRAL" 22 | } 23 | 24 | export interface RegisterFuncionarioDTO { 25 | name: string, 26 | email: string, 27 | password: string, 28 | cargo: Cargo 29 | } 30 | 31 | enum Cargo { 32 | GESTAO = "GESTAO", 33 | ADMINISTRACAO = "ADMINISTRACAO", 34 | DIRECAO = "DIRECAO", 35 | ORIENTACAO = "ORIENTACAO" 36 | } 37 | 38 | export interface RegisterProfessorDTO { 39 | name: string, 40 | email: string, 41 | password: string, 42 | tituloPrincipal: string 43 | } 44 | 45 | export interface RegisterTurmaDTO { 46 | inicio: string, 47 | fim: string, 48 | cursoName: string 49 | } -------------------------------------------------------------------------------- /server/src/modules/interfaces/empresaDTOs.ts: -------------------------------------------------------------------------------- 1 | export interface InitEmpresaDTO { 2 | email: string, 3 | cnpj: string 4 | } 5 | 6 | export interface LoginEmpresaDTO { 7 | cnpj: string, 8 | password: string 9 | } 10 | 11 | export interface ValidateEmpresaDTO { 12 | cnpj: string, 13 | token: string 14 | } 15 | 16 | export interface RecoveryEmpresaDTO { 17 | cnpj: string, 18 | email: string 19 | } 20 | 21 | export interface ValidateRecoveryEmpresaDTO { 22 | cnpj: string, 23 | tempPass: string, 24 | newPass: string 25 | } 26 | 27 | export interface RegisterEmpresaDTO { 28 | name: string, 29 | email: string, 30 | cnpj: string, 31 | password: string 32 | } 33 | 34 | export interface UpdateSiteDTO{ 35 | email: string, 36 | site: string 37 | 38 | } -------------------------------------------------------------------------------- /server/src/modules/interfaces/funcionarioDTOs.ts: -------------------------------------------------------------------------------- 1 | export interface InitFuncionarioDTO { 2 | email: string, 3 | cargo: Cargo 4 | } 5 | 6 | enum Cargo { 7 | GESTAO = "GESTAO", 8 | ADMINISTRACAO = "ADMINISTRACAO", 9 | DIRECAO = "DIRECAO", 10 | ORIENTACAO = "ORIENTACAO" 11 | } 12 | 13 | export interface LoginFuncionarioDTO { 14 | email: string, 15 | password: string 16 | } 17 | 18 | export interface ValidateFuncionarioDTO { 19 | email: string, 20 | temporaryPassword: string, 21 | newPassword: string 22 | } 23 | 24 | export interface RecoveryFuncionarioDTO { 25 | name: string, 26 | email: string 27 | } 28 | 29 | export interface ValidateRecoveryDTO { 30 | email: string, 31 | recoveryPass: string, 32 | newPass: string 33 | } 34 | 35 | export interface RegisterVagaDTO { 36 | titulo: string; 37 | cadastrador: string; 38 | empresa: string; 39 | requisitos: string[]; 40 | beneficios: string[]; 41 | remuneracao: string; 42 | cargaHoraria: string; 43 | entrada: string; 44 | saida: string; 45 | status: string; 46 | curso: string; 47 | descricao: string; 48 | } 49 | 50 | export interface SetEmpresaParceiraDTO { 51 | funcionarioId: string; 52 | emailEmpresa: string; 53 | } 54 | 55 | export interface CompareBoletimDTO { 56 | boletimId: string; 57 | file: Express.Multer.File; 58 | } -------------------------------------------------------------------------------- /server/src/modules/interfaces/professorDTOs.ts: -------------------------------------------------------------------------------- 1 | export interface InitProfessorDTO { 2 | email: string 3 | } 4 | 5 | export interface LoginProfessorDTO { 6 | email: string, 7 | password: string 8 | } 9 | 10 | export interface ValidateProfessorDTO { 11 | email: string, 12 | temporaryPassword: string, 13 | newPassword: string 14 | } 15 | 16 | export interface RecoveryProfessorDTO { 17 | name: string, 18 | email: string 19 | } 20 | 21 | export interface ValidateRecoveryDTO { 22 | email: string, 23 | recoveryPass: string, 24 | newPass: string 25 | } 26 | 27 | export interface CreateActivityDTO { 28 | title: string; 29 | descricao: string; 30 | professorId: string; 31 | imagem: Express.Multer.File; 32 | } 33 | 34 | export interface RelateAlunoAtividadeDTO { 35 | alunoId: string; 36 | atividadeId: string; 37 | professorId: string; 38 | mencao: Mencao; 39 | } 40 | 41 | export enum Mencao{ 42 | I = "I", 43 | R = "R", 44 | B = "B", 45 | MB = "MB" 46 | } -------------------------------------------------------------------------------- /server/src/modules/interfaces/sharedDTOs.ts: -------------------------------------------------------------------------------- 1 | export interface VinculoDTO { 2 | email: string, 3 | sender: string, 4 | recipient: string, 5 | senderIdentifier: IdentificadorEnum, 6 | recipientIdentifier: IdentificadorEnum 7 | } 8 | 9 | export enum IdentificadorEnum { 10 | ALUNO = "ALUNO", 11 | PROFESSOR = "PROFESSOR", 12 | EMPRESA = "EMPRESA" 13 | } 14 | 15 | export interface ReagirVinculoDTO { 16 | email: string, 17 | sender: string, 18 | recipient: string, 19 | senderIdentifier: IdentificadorEnum, 20 | recipientIdentifier: IdentificadorEnum 21 | } 22 | 23 | export interface GetEntidadeDTO { 24 | email: string, 25 | identifier: IdentificadorEnum, 26 | } 27 | 28 | export interface CreateMessageDTO { 29 | message: string, 30 | sender: string, 31 | recipient: string, 32 | senderIdentifier: EntidadeEnum, 33 | recipientIdentifier: EntidadeEnum 34 | } 35 | 36 | export interface GetMessageBetweenDTO { 37 | email1: string; 38 | identifier1: EntidadeEnum; 39 | email2: string; 40 | identifier2: EntidadeEnum; 41 | } 42 | 43 | export enum EntidadeEnum { 44 | ALUNO = 'ALUNO', 45 | PROFESSOR = 'PROFESSOR', 46 | FUNCIONARIO = 'FUNCIONARIO', 47 | EMPRESA = 'EMPRESA', 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/Get/Coordenadores.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../../prisma/client"; 2 | import { Coordenador, Curso } from "@prisma/client"; 3 | 4 | export class GetCoordenadorUseCase { 5 | async execute(): Promise<(Coordenador & { cursos: Curso[] })[]> { 6 | 7 | const coordenadores = await prisma.coordenador.findMany({ 8 | include: { 9 | curso: true, 10 | }, 11 | }); 12 | 13 | const coordenadoresComCursos = coordenadores.map(coordenador => ({ 14 | ...coordenador, 15 | cursos: coordenador.curso 16 | })); 17 | 18 | return coordenadoresComCursos; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /server/src/modules/services/admin/Get/CoordenasdoresNames.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../../prisma/client"; 2 | import { AppError } from "../../../../errors/error"; 3 | import { Coordenador } from "@prisma/client"; 4 | 5 | export class GetCoordenadoresNamesUseCase { 6 | async execute(): Promise[]> { 7 | 8 | const coordenadores = await prisma.coordenador.findMany({}); 9 | 10 | return coordenadores.map(coordenador => { 11 | return { 12 | name: coordenador.name 13 | } 14 | }); 15 | } 16 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/Get/Cursos.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../../prisma/client"; 2 | 3 | interface CursoWithSummary { 4 | id: string; 5 | name: string; 6 | turno: string; 7 | duracao: string; 8 | coordenador: string; 9 | quantidadeTurmas: number; 10 | quantidadeAlunos: number; 11 | } 12 | 13 | export class GetFullCursosUseCase { 14 | async execute(): Promise { 15 | const cursos = await prisma.curso.findMany({ 16 | include: { 17 | coordenador: true, 18 | }, 19 | }); 20 | 21 | const cursosWithSummary: CursoWithSummary[] = []; 22 | 23 | for (const curso of cursos) { 24 | const turmas = await prisma.turma.findMany({ 25 | where: { cursoId: curso.id }, 26 | include: { 27 | alunos: { 28 | include: { 29 | aluno: true, 30 | }, 31 | }, 32 | }, 33 | }); 34 | 35 | const quantidadeTurmas = turmas.length; 36 | const quantidadeAlunos = turmas.reduce((acc, turma) => acc + turma.alunos.length, 0); 37 | 38 | cursosWithSummary.push({ 39 | id: curso.id, 40 | name: curso.name, 41 | turno: curso.turno, 42 | duracao: curso.duracao, 43 | coordenador: curso.coordenador.name, 44 | quantidadeTurmas, 45 | quantidadeAlunos, 46 | }); 47 | } 48 | 49 | return cursosWithSummary; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /server/src/modules/services/admin/Get/Empresas.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../../prisma/client"; 2 | 3 | interface EmpresaWithEstagios { 4 | id: string; 5 | name: string; 6 | estagios: string[]; 7 | } 8 | 9 | export class GetEmpresasWithEstagiosUseCase { 10 | async execute(): Promise { 11 | const empresas = await prisma.empresa.findMany({ 12 | include: { 13 | vaga: true, 14 | }, 15 | }); 16 | 17 | const empresasWithEstagios: EmpresaWithEstagios[] = empresas.map((empresa) => ({ 18 | ...empresa, 19 | estagios: empresa.vaga.map((vaga) => vaga.titulo), 20 | })); 21 | 22 | return empresasWithEstagios; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /server/src/modules/services/admin/Get/Estagios.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../../prisma/client"; 2 | import { Vaga } from "@prisma/client"; 3 | 4 | export class GetFullEstagiosUseCase { 5 | async execute(): Promise { 6 | 7 | const estagios = await prisma.vaga.findMany({ 8 | include: { 9 | funcionario: { 10 | select: { 11 | name: true 12 | } 13 | }, 14 | empresa: true 15 | } 16 | }); 17 | 18 | return estagios; 19 | } 20 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/Get/Funcionario.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../../prisma/client"; 2 | import { Funcionario } from "@prisma/client"; 3 | 4 | export class GetFullFuncionariosUseCase { 5 | async execute(): Promise { 6 | 7 | const funcionarios = await prisma.funcionario.findMany({}); 8 | 9 | return funcionarios; 10 | } 11 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/Get/ProfessorNames.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../../prisma/client"; 2 | import { AppError } from "../../../../errors/error"; 3 | import { Professor } from "@prisma/client"; 4 | import { Coordenador } from "@prisma/client"; 5 | 6 | export class GetAllProfessoresNamesUseCase { 7 | async execute(): Promise[]> { 8 | 9 | const professores = await prisma.professor.findMany({ 10 | where: { 11 | coordenador: { 12 | none: {} 13 | } 14 | } 15 | }); 16 | 17 | return professores.map(professor => { 18 | return { 19 | name: professor.name 20 | } 21 | }); 22 | } 23 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/Get/Professores.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../../prisma/client"; 2 | import { Professor } from "@prisma/client"; 3 | 4 | export class GetProfessoresUseCase { 5 | async execute(): Promise { 6 | 7 | const professores = await prisma.professor.findMany({}); 8 | 9 | return professores; 10 | } 11 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/Get/Turmas.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../../prisma/client"; 2 | import { Aluno, Turma, Curso } from "@prisma/client"; 3 | 4 | type TurmaComAlunos = Turma & { 5 | curso: Curso; 6 | lista_de_alunos: Aluno[]; 7 | }; 8 | 9 | export class GetFullTurmasUseCase { 10 | async execute(): Promise { 11 | const turmas = await prisma.turma.findMany({ 12 | orderBy: { 13 | curso: { 14 | name: 'asc' 15 | } 16 | }, 17 | include: { 18 | curso: true 19 | } 20 | }); 21 | 22 | const turmasComAlunos: TurmaComAlunos[] = []; 23 | for (const turma of turmas) { 24 | const alunos = await prisma.aluno.findMany({ 25 | where: { 26 | turmas: { 27 | some: { 28 | turmaId: turma.id 29 | } 30 | } 31 | } 32 | }); 33 | const turmaComAlunos: TurmaComAlunos = { 34 | ...turma, 35 | lista_de_alunos: alunos 36 | }; 37 | turmasComAlunos.push(turmaComAlunos); 38 | } 39 | 40 | return turmasComAlunos; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /server/src/modules/services/admin/LoginAdminUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Admin } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { LoginAdminDTO } from "../../interfaces/adminDTOs" 4 | import { AppError } from "../../../errors/error"; 5 | import { generateAccessTokenAdmin } from "../../../jwt/jwtServices"; 6 | 7 | const bcrypt = require('bcrypt'); 8 | 9 | export class LoginAdminUseCase { 10 | async execute({ email, password }: LoginAdminDTO): Promise<{ token: string, admin: Pick }> { 11 | 12 | if (!email || !password) { 13 | throw new AppError("Parâmetros insuficientes ou inválidos."); 14 | } 15 | 16 | const admin = await prisma.admin.findUnique({ 17 | where: { 18 | email 19 | } 20 | }); 21 | 22 | if (!admin) { 23 | throw new AppError("Email ou senha inválidos"); 24 | } 25 | 26 | const isPasswordValid = bcrypt.compareSync(password, admin.password); 27 | 28 | if (!isPasswordValid) { 29 | throw new AppError("Email ou senha inválidos"); 30 | } 31 | 32 | const token = generateAccessTokenAdmin(admin); 33 | 34 | if (!token) { 35 | throw new AppError("Email ou senha inválidos"); 36 | } 37 | 38 | return { 39 | token: token, 40 | admin: { 41 | name: admin.name, 42 | email: admin.email 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/RefreshTokenUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { generateAccessTokenAdmin } from "../../../jwt/jwtServices"; 4 | 5 | export class RefreshTokenUseCase { 6 | async execute(email: string ): Promise<{ token: string, message: string }> { 7 | 8 | if (!email) { 9 | throw new AppError("Parâmetros insuficientes ou inválidos."); 10 | } 11 | 12 | const admin = await prisma.admin.findFirst({ 13 | where: { 14 | email 15 | } 16 | }); 17 | 18 | if (!admin) { 19 | throw new AppError("Email inválido"); 20 | } 21 | 22 | const token = generateAccessTokenAdmin(admin); 23 | 24 | if (!token) { 25 | throw new AppError("Email inválido"); 26 | } 27 | 28 | return { 29 | token: token, 30 | message: "token atualizado com sucesso!" 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/RegisterCoordenadorUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Coordenador } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { RegisterCoordenadorDTO } from "../../interfaces/adminDTOs" 4 | import { AppError } from "../../../errors/error"; 5 | 6 | export class RegisterCoordenadorUseCase { 7 | async execute({ name }: RegisterCoordenadorDTO): Promise> { 8 | 9 | if (!name) { 10 | throw new AppError("Parâmetros insuficientes ou inválidos."); 11 | } 12 | 13 | const isProfessor = await prisma.professor.findFirst({ 14 | where: { 15 | name 16 | } 17 | }); 18 | 19 | if (isProfessor) { 20 | const coordenadorAlreadyExists = await prisma.coordenador.findFirst({ 21 | where: { 22 | name 23 | } 24 | }); 25 | 26 | if (!coordenadorAlreadyExists) { 27 | const coordenadorRegister = await prisma.coordenador.create({ 28 | data: { 29 | name, 30 | professorId: isProfessor.id 31 | } 32 | }); 33 | 34 | if (!coordenadorRegister) { 35 | throw new AppError("Erro ao cadastrar professor!"); 36 | } else { 37 | return { 38 | name: coordenadorRegister.name 39 | }; 40 | } 41 | } else { 42 | throw new AppError("Coordenador já cadastrado!"); 43 | } 44 | } else { 45 | throw new AppError("Esse nome não corresponde a um professor!"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/RegisterCursosUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Curso } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { RegisterCursosDTO } from "../../interfaces/adminDTOs" 4 | import { AppError } from "../../../errors/error"; 5 | 6 | export class RegisterCursosUseCase { 7 | async execute({ cursoName, turno, duracao, coordenador }: RegisterCursosDTO): Promise> { 8 | 9 | if (!cursoName || !turno || !duracao || !coordenador) { 10 | throw new AppError("Parâmetros insuficientes ou inválidos."); 11 | } 12 | 13 | const coordenadorExists = await prisma.coordenador.findFirst({ 14 | where: { 15 | name: coordenador 16 | } 17 | }); 18 | 19 | if (!coordenadorExists) { 20 | throw new AppError("Coordenador inválido!") 21 | } else { 22 | 23 | const cursoAlreadyExists = await prisma.curso.findFirst({ 24 | where: { 25 | name: cursoName, 26 | turno, 27 | duracao, 28 | coordenadorId: coordenadorExists.id 29 | } 30 | }); 31 | 32 | if (cursoAlreadyExists) { 33 | throw new AppError("Curso já cadastrado!"); 34 | } else { 35 | const cursoRegister = await prisma.curso.create({ 36 | data: { 37 | name: cursoName, 38 | turno, 39 | duracao, 40 | coordenadorId: coordenadorExists.id 41 | } 42 | }); 43 | 44 | if (!cursoRegister) { 45 | throw new AppError("Erro ao cadastrar curso!"); 46 | } 47 | 48 | return { 49 | name: cursoRegister.name, 50 | turno: cursoRegister.turno, 51 | duracao: cursoRegister.duracao 52 | }; 53 | } 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /server/src/modules/services/admin/RegisterTurmasUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Turma } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { RegisterTurmaDTO } from "../../interfaces/adminDTOs" 4 | import { AppError } from "../../../errors/error"; 5 | 6 | export class RegisterTurmasUseCase { 7 | async execute({ inicio, fim, cursoName }: RegisterTurmaDTO): Promise<{ cursoName: string, turma: Pick }> { 8 | 9 | if (!inicio || !fim || !cursoName) { 10 | throw new AppError("Parâmetros insuficientes ou inválidos."); 11 | } 12 | 13 | const Curso = await prisma.curso.findFirst({ 14 | where: { 15 | name: cursoName 16 | } 17 | }); 18 | 19 | if (!Curso) { 20 | throw new AppError("Curso inválido!") 21 | } 22 | 23 | const turmaAlreadyExists = await prisma.turma.findFirst({ 24 | where: { 25 | inicio: inicio, 26 | fim: fim, 27 | cursoId: Curso.id 28 | } 29 | }); 30 | 31 | if (turmaAlreadyExists) { 32 | throw new AppError("Turma já existente!") 33 | } else { 34 | 35 | const turma = await prisma.turma.create({ 36 | data: { 37 | inicio: inicio, 38 | fim: fim, 39 | cursoId: Curso.id 40 | } 41 | }); 42 | 43 | if (!turma) { 44 | throw new AppError("Erro ao cadastrar turma!"); 45 | } 46 | 47 | return { 48 | cursoName: cursoName, 49 | turma: { 50 | inicio: turma.inicio, 51 | fim: turma.fim 52 | } 53 | }; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /server/src/modules/services/aluno/ChangePassUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { UpdatePassDTO } from "../../interfaces/alunoDTOs" 3 | import { AppError } from "../../../errors/error"; 4 | 5 | const bcrypt = require('bcrypt'); 6 | 7 | export class ChangePassUseCase { 8 | async execute({ email, oldPass, newPass }: UpdatePassDTO) { 9 | 10 | if (!email) { 11 | throw new AppError("Parâmetros insuficientes ou inválidos."); 12 | } 13 | 14 | const aluno = await prisma.aluno.findUnique({ 15 | where: { 16 | email 17 | } 18 | }); 19 | 20 | if (aluno) { 21 | const isPasswordValid = bcrypt.compareSync(oldPass, aluno.password); 22 | 23 | if (!isPasswordValid) { 24 | throw new AppError("Senha atual inválida"); 25 | } 26 | 27 | const salt = bcrypt.genSaltSync(10); 28 | const hash = bcrypt.hashSync(newPass, salt); 29 | 30 | 31 | await prisma.aluno.update({ 32 | where: { 33 | email 34 | }, 35 | data: { 36 | password: hash 37 | } 38 | }); 39 | 40 | return; 41 | } else { 42 | throw new AppError("Aluno não encontrado"); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/CreateExtraUseCase.ts: -------------------------------------------------------------------------------- 1 | import { RegisterExtracurricularDTO } from '../../interfaces/alunoDTOs'; 2 | import { prisma } from "../../../prisma/client"; 3 | import { AppError } from "../../../errors/error"; 4 | 5 | export class RegisterExtracurricularUseCase { 6 | async execute(data: RegisterExtracurricularDTO) { 7 | const { alunoId, instituicao, descricao, inicio, fim } = data; 8 | 9 | if (!alunoId || !instituicao || !descricao || !inicio || !fim) { 10 | throw new AppError('Todos os campos são obrigatórios.'); 11 | } 12 | 13 | if (new Date(inicio) >= new Date(fim)) { 14 | throw new AppError('A data de início deve ser anterior à data de fim.'); 15 | } 16 | 17 | const aluno = await prisma.aluno.findUnique({ 18 | where: { id: alunoId }, 19 | }); 20 | 21 | if (!aluno) { 22 | throw new AppError('Aluno não encontrado.'); 23 | } 24 | 25 | const existingExtracurricular = await prisma.extracurricular.findFirst({ 26 | where: { 27 | alunoId, 28 | descricao, 29 | }, 30 | }); 31 | 32 | if (existingExtracurricular) { 33 | throw new AppError('Já existe uma atividade extracurricular com esta descrição para este aluno.'); 34 | } 35 | 36 | const extracurricular = await prisma.extracurricular.create({ 37 | data: { 38 | alunoId, 39 | instituicao, 40 | descricao, 41 | inicio: new Date(inicio), 42 | fim: new Date(fim), 43 | }, 44 | }); 45 | 46 | return extracurricular; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /server/src/modules/services/aluno/EditExtraUsecase.ts: -------------------------------------------------------------------------------- 1 | import { EditExtracurricularDTO } from '../../interfaces/alunoDTOs'; 2 | import { prisma } from "../../../prisma/client"; 3 | import { AppError } from "../../../errors/error"; 4 | 5 | export class EditExtracurricularUseCase { 6 | async execute(data: EditExtracurricularDTO) { 7 | const { extracurricularId, instituicao, descricao, inicio, fim } = data; 8 | const alunoId = data.alunoId; 9 | 10 | if (!extracurricularId) { 11 | throw new AppError('ID da atividade extracurricular é obrigatório.'); 12 | } 13 | 14 | if (!alunoId) { 15 | throw new AppError('ID do aluno é obrigatório.'); 16 | } 17 | 18 | const extracurricular = await prisma.extracurricular.findUnique({ 19 | where: { extracurricularId }, 20 | }); 21 | 22 | if (!extracurricular) { 23 | throw new AppError('Atividade extracurricular não encontrada.'); 24 | } 25 | 26 | if (extracurricular.alunoId !== alunoId) { 27 | throw new AppError('Você não tem permissão para editar esta atividade extracurricular.'); 28 | } 29 | 30 | if (descricao) { 31 | const existingExtracurricular = await prisma.extracurricular.findFirst({ 32 | where: { 33 | alunoId: extracurricular.alunoId, 34 | descricao, 35 | extracurricularId: { 36 | not: extracurricularId, 37 | }, 38 | }, 39 | }); 40 | 41 | if (existingExtracurricular) { 42 | throw new AppError('Já existe uma atividade extracurricular com esta descrição para este aluno.'); 43 | } 44 | } 45 | 46 | const updatedExtracurricular = await prisma.extracurricular.update({ 47 | where: { extracurricularId }, 48 | data: { 49 | instituicao, 50 | descricao, 51 | inicio, 52 | fim, 53 | updatedAt: new Date(), 54 | }, 55 | }); 56 | 57 | return updatedExtracurricular; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /server/src/modules/services/aluno/ExcludeExtraUseCase.ts: -------------------------------------------------------------------------------- 1 | import { ExcludeExtracurricularDTO } from '../../interfaces/alunoDTOs'; 2 | import { prisma } from "../../../prisma/client"; 3 | import { AppError } from "../../../errors/error"; 4 | 5 | export class ExcludeExtracurricularUseCase { 6 | async execute(data: ExcludeExtracurricularDTO) { 7 | const { extracurricularId, alunoId } = data; 8 | 9 | if (!extracurricularId) { 10 | throw new AppError('ID da atividade extracurricular é obrigatório.'); 11 | } 12 | 13 | if (!alunoId) { 14 | throw new AppError('ID do aluno é obrigatório.'); 15 | } 16 | 17 | const extracurricular = await prisma.extracurricular.findUnique({ 18 | where: { extracurricularId }, 19 | }); 20 | 21 | if (!extracurricular) { 22 | throw new AppError('Atividade extracurricular não encontrada.'); 23 | } 24 | 25 | if (extracurricular.alunoId !== alunoId) { 26 | throw new AppError('Você não tem permissão para excluir esta atividade extracurricular.'); 27 | } 28 | 29 | await prisma.extracurricular.delete({ 30 | where: { extracurricularId }, 31 | }); 32 | 33 | return { message: 'Atividade extracurricular excluída com sucesso.' }; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /server/src/modules/services/aluno/GetCourseYearUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { GetTurmasByCursoDTO } from "../../interfaces/alunoDTOs" 4 | 5 | export class GetTurmasByCursoUseCase { 6 | async execute({ curso, turno }: GetTurmasByCursoDTO) { 7 | if (!curso || !turno) { 8 | throw new AppError("Parâmetros insufientes ou inválidos. " + curso + " " + turno); 9 | } 10 | 11 | const cursoExists = await prisma.curso.findFirst({ 12 | where: { 13 | name: curso, 14 | turno: turno 15 | }, 16 | }); 17 | 18 | if (!cursoExists) { 19 | throw new AppError("Curso não encontrado."); 20 | } 21 | 22 | const turmas = await prisma.turma.findMany({ 23 | where: { 24 | cursoId: cursoExists.id 25 | }, 26 | }); 27 | 28 | if (!turmas) { 29 | throw new AppError("Turmas não encontradas para esse curso."); 30 | } 31 | 32 | return turmas.map(turma => ({ 33 | inicio: turma.inicio 34 | })); 35 | } 36 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/GetCurriculoUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | 4 | export class GetCurriculoUseCase { 5 | async execute(email: string) { 6 | if (!email) { 7 | throw new AppError("Parâmetros insufientes ou inválidos. " + email); 8 | } 9 | 10 | const aluno = await prisma.aluno.findFirst({ 11 | where: { 12 | email: email 13 | }, 14 | }); 15 | 16 | if (!aluno) { 17 | throw new AppError("Aluno não encontrado."); 18 | } 19 | 20 | const vinculos = await prisma.vinculo.findMany({ 21 | where:{ 22 | AND: [ 23 | {OR: [ 24 | {alunoId: aluno.id}, 25 | {vinculoComAlunoId: aluno.id} 26 | ]}, 27 | {accepted: true} 28 | ]} 29 | }); 30 | 31 | return { 32 | curriculo: aluno.curriculo, 33 | nome: aluno.name, 34 | endereco: aluno.endereco, 35 | nascimento: aluno.dataNascimento, 36 | email: email, 37 | rm: aluno.rm, 38 | quantidadeVinculos: vinculos.length 39 | }; 40 | } 41 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/GetExtracurricularesUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | 4 | export class GetExtracurricularsByEmailUseCase { 5 | async execute(email: string) { 6 | if (!email) { 7 | throw new AppError("Parâmetros insuficientes ou inválidos. " + email); 8 | } 9 | 10 | const aluno = await prisma.aluno.findFirst({ 11 | where: { 12 | email: email, 13 | }, 14 | select: { 15 | name: true, 16 | cursosExtracurriculares: { 17 | select: { 18 | extracurricularId: true, 19 | instituicao: true, 20 | descricao: true, 21 | inicio: true, 22 | fim: true, 23 | }, 24 | }, 25 | }, 26 | }); 27 | 28 | if (!aluno) { 29 | throw new AppError("Aluno não encontrado."); 30 | } 31 | 32 | return { 33 | nome: aluno.name, 34 | cursosExtracurriculares: aluno.cursosExtracurriculares, 35 | }; 36 | } 37 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/GetMeUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | 4 | export class GetMeUseCase { 5 | async execute( email: string ) { 6 | if (!email) { 7 | throw new AppError("Parâmetros insufientes ou inválidos. "); 8 | } 9 | 10 | const aluno = await prisma.aluno.findFirst({ 11 | where: { 12 | email 13 | }, 14 | }); 15 | 16 | if (!aluno) { 17 | throw new AppError("Aluno não encontrado."); 18 | } 19 | 20 | return { 21 | email: email, 22 | rm: aluno.rm, 23 | name: aluno.name 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/LoginAlunoUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Aluno } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { LoginAlunoDTO } from "../../interfaces/alunoDTOs" 4 | import { AppError } from "../../../errors/error"; 5 | import { generateAccessTokenAluno } from "../../../jwt/jwtServices"; 6 | 7 | const bcrypt = require('bcrypt'); 8 | 9 | export class LoginAlunoUseCase { 10 | async execute({ email, password }: LoginAlunoDTO): Promise<{ token: string, aluno: Pick }> { 11 | 12 | if (!email || !password) { 13 | throw new AppError("Parâmetros insuficientes ou inválidos."); 14 | } 15 | 16 | const aluno = await prisma.aluno.findFirst({ 17 | where: { 18 | email, 19 | } 20 | }); 21 | 22 | if (!aluno) { 23 | throw new AppError("Email ou senha inválidos"); 24 | } else if(aluno.validated == false){ 25 | throw new AppError("Aluno não validado"); 26 | } 27 | 28 | const isPasswordValid = bcrypt.compareSync(password, aluno.password); 29 | 30 | if (!isPasswordValid) { 31 | throw new AppError("Email ou senha inválidos"); 32 | } 33 | 34 | const token = generateAccessTokenAluno(aluno); 35 | 36 | if (!token) { 37 | throw new AppError("Email ou senha inválidos"); 38 | } 39 | 40 | return { 41 | token: token, 42 | aluno: { 43 | name: aluno.name, 44 | email: aluno.email, 45 | rm: aluno.rm 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/RefreshTokenUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { generateAccessTokenAluno } from "../../../jwt/jwtServices"; 4 | 5 | export class RefreshTokenUseCase { 6 | async execute(email: string): Promise<{ token: string, message: string }> { 7 | 8 | if (!email) { 9 | throw new AppError("Parâmetros insuficientes ou inválidos."); 10 | } 11 | 12 | const aluno = await prisma.aluno.findFirst({ 13 | where: { 14 | email 15 | } 16 | }); 17 | 18 | if (!aluno) { 19 | throw new AppError("Email inválido"); 20 | } 21 | 22 | const token = generateAccessTokenAluno(aluno); 23 | 24 | if (!token) { 25 | throw new AppError("Email inválido"); 26 | } 27 | 28 | return { 29 | token: token, 30 | message: "token atualizado com sucesso!" 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/UpdateCurriculoUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { UpdateCurriculoDTO } from "../../interfaces/alunoDTOs" 3 | import { AppError } from "../../../errors/error"; 4 | 5 | export class UpdateCurriculoUseCase { 6 | async execute({ email, curriculo }: UpdateCurriculoDTO) { 7 | 8 | if (!email) { 9 | throw new AppError("Parâmetros insuficientes ou inválidos."); 10 | } 11 | 12 | const aluno = await prisma.aluno.findUnique({ 13 | where: { 14 | email 15 | } 16 | }); 17 | 18 | if (aluno) { 19 | await prisma.aluno.update({ 20 | where: { 21 | email 22 | }, 23 | data: { 24 | curriculo: curriculo 25 | } 26 | }); 27 | 28 | return; 29 | } else { 30 | throw new AppError("Email não encontrado"); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/UploadCapaUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { uploadToMinio } from "../../../minioService"; 4 | import { UploadImageDTO } from "../../interfaces/alunoDTOs"; 5 | import { clearUploads } from "../shared/helpers/helpers"; 6 | 7 | export class UploadCapaUseCase { 8 | async execute({ email, file }: UploadImageDTO) { 9 | 10 | if (!email || !file) { 11 | throw new AppError("Parâmetros insuficientes ou inválidos."); 12 | } 13 | 14 | const aluno = await prisma.aluno.findUnique({ 15 | where: { 16 | email 17 | } 18 | }); 19 | 20 | if (aluno) { 21 | const bucketName = 'boot'; 22 | const objectName = `aluno/${aluno.rm}/banner`; 23 | 24 | try { 25 | const filePath = file.path; 26 | await uploadToMinio(bucketName, objectName, filePath); 27 | 28 | await prisma.aluno.update({ 29 | where: { 30 | email 31 | }, 32 | data: { 33 | banner: objectName 34 | } 35 | }); 36 | 37 | clearUploads(); 38 | return { message: 'Imagem de banner salva com sucesso!' }; 39 | } catch (error) { 40 | throw new AppError(`Error uploading image: ${error}`); 41 | } 42 | 43 | return; 44 | } else { 45 | throw new AppError("Email não encontrado"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/UploadProfileUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { uploadToMinio } from "../../../minioService"; 4 | import { UploadImageDTO } from "../../interfaces/alunoDTOs"; 5 | import { clearUploads } from "../shared/helpers/helpers"; 6 | 7 | export class UploadProfileUseCase { 8 | async execute({ email, file } : UploadImageDTO) { 9 | 10 | if (!email) { 11 | throw new AppError("Parâmetros insuficientes ou inválidos."); 12 | } else if (!file) { 13 | throw new AppError("File precisa ser enviado."); 14 | } 15 | 16 | const aluno = await prisma.aluno.findUnique({ 17 | where: { 18 | email 19 | } 20 | }); 21 | 22 | if (aluno) { 23 | const bucketName = 'boot'; 24 | const objectName = `aluno/${aluno.rm}/perfil`; 25 | 26 | try { 27 | const filePath = file.path; 28 | await uploadToMinio(bucketName, objectName, filePath); 29 | 30 | await prisma.aluno.update({ 31 | where: { 32 | email 33 | }, 34 | data: { 35 | imagem: objectName 36 | } 37 | }); 38 | 39 | clearUploads(); 40 | return { message: 'Imagem de perfil salva com sucesso!.' }; 41 | } catch (error) { 42 | throw new AppError(`Error uploading image: ${error}`); 43 | } 44 | } else { 45 | throw new AppError("Email não encontrado"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/aluno/ValidateRecoveryUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Aluno } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { validateRecoveryDTO } from "../../interfaces/alunoDTOs" 4 | import { AppError } from "../../../errors/error"; 5 | import { generateAccessTokenAluno } from "../../../jwt/jwtServices"; 6 | 7 | const bcrypt = require('bcrypt'); 8 | 9 | export class ValidateRecoveryUseCase { 10 | async execute({ email, recoveryPassword, newPass }: validateRecoveryDTO): Promise<{ token: string, aluno: Pick }> { 11 | 12 | if (!email || !recoveryPassword || !newPass) { 13 | throw new AppError("Parâmetros insuficientes ou inválidos."); 14 | } 15 | 16 | const aluno = await prisma.aluno.findFirst({ 17 | where: { 18 | email 19 | } 20 | }); 21 | 22 | if (!aluno) { 23 | throw new AppError("Email ou senha de recuperação inválidos"); 24 | } else { 25 | const isPasswordValid = bcrypt.compareSync(recoveryPassword, aluno.recoveryPass); 26 | 27 | if (!isPasswordValid) { 28 | throw new AppError("Senha temporária inválida"); 29 | } else { 30 | const salt = bcrypt.genSaltSync(10); 31 | const hash = bcrypt.hashSync(newPass, salt); 32 | 33 | await prisma.aluno.update({ 34 | where: { 35 | email 36 | }, 37 | data: { 38 | password: hash, 39 | tentativasRestantes: 5 40 | } 41 | }); 42 | 43 | const token = generateAccessTokenAluno(aluno); 44 | 45 | if (!token) { 46 | throw new AppError("Email ou senha inválidos"); 47 | } 48 | 49 | return { 50 | token: token, 51 | aluno: { 52 | name: aluno.name, 53 | email: aluno.email 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /server/src/modules/services/empresa/GetEmpresaUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { minioClient } from "../../../minioService"; 4 | 5 | export class GetEmpresaUseCase { 6 | async execute(email : string) { 7 | if (!email) { 8 | throw new AppError("Parâmetros insufientes ou inválidos."); 9 | } 10 | 11 | const empresa = await prisma.empresa.findFirst({ 12 | where: { 13 | email 14 | }, 15 | }); 16 | 17 | if(empresa){ 18 | const bucketName = 'boot'; 19 | const imageName = empresa.imagem as string; 20 | 21 | let entityUrl = "default"; 22 | 23 | if (imageName) { 24 | const objectExists = await minioClient.statObject(bucketName, imageName); 25 | if(objectExists){ 26 | entityUrl = await minioClient.presignedUrl('GET', bucketName, imageName, 24 * 60 * 60); 27 | } 28 | } 29 | 30 | const bannerName = empresa.banner as string; 31 | 32 | let bannerUrl = "default"; 33 | 34 | if (bannerName) { 35 | const objectExists = await minioClient.statObject(bucketName, bannerName); 36 | if(objectExists){ 37 | bannerUrl = await minioClient.presignedUrl('GET', bucketName, bannerName, 24 * 60 * 60); 38 | } 39 | } 40 | 41 | if (!empresa) { 42 | throw new AppError("Empresa não encontrada."); 43 | } 44 | 45 | return { 46 | email: empresa.email, 47 | nome: empresa.name, 48 | telefone: empresa.telefone, 49 | endereco: empresa.endereco, 50 | imagem: entityUrl, 51 | banner: bannerUrl, 52 | site: empresa.site, 53 | patrocinada: empresa.patrocinador, 54 | cnpj: empresa.cnpj, 55 | }; 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /server/src/modules/services/empresa/LoginEmpresaUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Empresa } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { LoginEmpresaDTO } from "../../interfaces/empresaDTOs" 4 | import { AppError } from "../../../errors/error"; 5 | import { generateAccessTokenEmpresa } from "../../../jwt/jwtServices"; 6 | 7 | const bcrypt = require('bcrypt'); 8 | 9 | export class LoginEmpresaUseCase { 10 | async execute({ cnpj, password }: LoginEmpresaDTO): Promise<{ token: string, empresa: Pick }> { 11 | 12 | if (!cnpj || !password) { 13 | throw new AppError("Parâmetros insuficientes ou inválidos."); 14 | } 15 | 16 | if (cnpj.length !== 14) { 17 | throw new AppError("O CNPJ deve conter exatamente 14 dígitos."); 18 | } 19 | 20 | const empresaCNPJ = await prisma.empresa.findFirst({ 21 | where: { 22 | cnpj, 23 | } 24 | }); 25 | 26 | if (!empresaCNPJ) { 27 | throw new AppError("CNPJ inválido."); 28 | } 29 | 30 | const empresa = await prisma.empresa.findFirst({ 31 | where: { 32 | cnpj, 33 | validated: true 34 | } 35 | }); 36 | 37 | if (!empresa) { 38 | throw new AppError("Empresa não validada."); 39 | } 40 | 41 | const isPasswordValid = bcrypt.compareSync(password, empresa.password); 42 | 43 | if (!isPasswordValid) { 44 | throw new AppError("Combinação de CNPJ e senha inválida"); 45 | } 46 | 47 | const token = generateAccessTokenEmpresa(empresa); 48 | 49 | if (!token) { 50 | throw new AppError("Email ou senha inválidos"); 51 | } 52 | 53 | return { 54 | token: token, 55 | empresa: { 56 | name: empresa.name, 57 | email: empresa.email 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /server/src/modules/services/empresa/RefreshTokenUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { generateAccessTokenEmpresa } from "../../../jwt/jwtServices"; 4 | 5 | export class RefreshTokenUseCase { 6 | async execute(email: string ): Promise<{ token: string, message: string }> { 7 | 8 | if (!email) { 9 | throw new AppError("Parâmetros insuficientes ou inválidos."); 10 | } 11 | 12 | const empresa = await prisma.empresa.findFirst({ 13 | where: { 14 | email 15 | } 16 | }); 17 | 18 | if (!empresa) { 19 | throw new AppError("Email inválido"); 20 | } 21 | 22 | const token = generateAccessTokenEmpresa(empresa); 23 | 24 | if (!token) { 25 | throw new AppError("Email inválido"); 26 | } 27 | 28 | return { 29 | token: token, 30 | message: "token atualizado com sucesso!" 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/empresa/UpdateSiteUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { UpdateSiteDTO } from "../../interfaces/empresaDTOs" 3 | import { AppError } from "../../../errors/error"; 4 | 5 | export class UpdateSiteUseCase { 6 | async execute({ email, site }: UpdateSiteDTO) { 7 | 8 | if (!email) { 9 | throw new AppError("Parâmetros insuficientes ou inválidos."); 10 | } 11 | 12 | const empresa = await prisma.empresa.findUnique({ 13 | where: { 14 | email 15 | } 16 | }); 17 | 18 | if (empresa) { 19 | await prisma.empresa.update({ 20 | where: { 21 | email 22 | }, 23 | data: { 24 | site: site 25 | } 26 | }); 27 | 28 | return; 29 | } else { 30 | throw new AppError("Email não encontrado"); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/empresa/UploadCapaUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { uploadToMinio } from "../../../minioService"; 4 | import { UploadImageDTO } from "../../interfaces/alunoDTOs"; 5 | import { clearUploads } from "../shared/helpers/helpers"; 6 | 7 | export class UploadCapaUseCase { 8 | async execute({ email, file }: UploadImageDTO) { 9 | 10 | if (!email || !file) { 11 | throw new AppError("Parâmetros insuficientes ou inválidos."); 12 | } 13 | 14 | const empresa = await prisma.empresa.findUnique({ 15 | where: { 16 | email 17 | } 18 | }); 19 | 20 | if (empresa) { 21 | const bucketName = 'boot'; 22 | const objectName = `empresa/${empresa.id}/banner`; 23 | 24 | try { 25 | const filePath = file.path; 26 | await uploadToMinio(bucketName, objectName, filePath); 27 | 28 | await prisma.empresa.update({ 29 | where: { 30 | email 31 | }, 32 | data: { 33 | banner: objectName 34 | } 35 | }); 36 | 37 | clearUploads(); 38 | return { message: 'Imagem de banner salva com sucesso!' }; 39 | } catch (error) { 40 | throw new AppError(`Error uploading image: ${error}`); 41 | } 42 | 43 | return; 44 | } else { 45 | throw new AppError("Email não encontrado"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/empresa/UploadProfileUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { uploadToMinio } from "../../../minioService"; 4 | import { UploadImageDTO } from "../../interfaces/alunoDTOs"; 5 | import { clearUploads } from "../shared/helpers/helpers"; 6 | 7 | export class UploadProfileUseCase { 8 | async execute({ email, file } : UploadImageDTO) { 9 | 10 | if (!email) { 11 | throw new AppError("Parâmetros insuficientes ou inválidos."); 12 | } else if (!file) { 13 | throw new AppError("File precisa ser enviado."); 14 | } 15 | 16 | const empresa = await prisma.empresa.findUnique({ 17 | where: { 18 | email 19 | } 20 | }); 21 | 22 | if (empresa) { 23 | const bucketName = 'boot'; 24 | const objectName = `empresa/${empresa.id}/perfil`; 25 | 26 | try { 27 | const filePath = file.path; 28 | await uploadToMinio(bucketName, objectName, filePath); 29 | 30 | await prisma.empresa.update({ 31 | where: { 32 | email 33 | }, 34 | data: { 35 | imagem: objectName 36 | } 37 | }); 38 | 39 | clearUploads(); 40 | return { message: 'Imagem de perfil salva com sucesso!.' }; 41 | } catch (error) { 42 | throw new AppError(`Error uploading image: ${error}`); 43 | } 44 | } else { 45 | throw new AppError("Email não encontrado"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/empresa/ValidateRecoveryEmpresa.ts: -------------------------------------------------------------------------------- 1 | import { Empresa } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { ValidateRecoveryEmpresaDTO } from "../../interfaces/empresaDTOs" 4 | import { AppError } from "../../../errors/error"; 5 | import { generateAccessTokenEmpresa } from "../../../jwt/jwtServices"; 6 | 7 | const bcrypt = require('bcrypt'); 8 | 9 | export class ValidateRecoveryEmpresaUseCase { 10 | async execute({ cnpj, tempPass, newPass }: ValidateRecoveryEmpresaDTO): Promise<{ token: string, empresa: Pick }> { 11 | 12 | if (!cnpj || !tempPass || !newPass) { 13 | throw new AppError("Parâmetros insuficientes ou inválidos."); 14 | } 15 | 16 | const empresa = await prisma.empresa.findFirst({ 17 | where: { 18 | cnpj 19 | } 20 | }); 21 | 22 | if (!empresa) { 23 | throw new AppError("CNPJ ou senha de recuperação inválidos."); 24 | } else { 25 | const isTokenValid = bcrypt.compareSync(tempPass, empresa.token); 26 | 27 | if (!isTokenValid) { 28 | throw new AppError("Token de recuperação inválido."); 29 | } else { 30 | const salt = bcrypt.genSaltSync(10); 31 | const hash = bcrypt.hashSync(newPass, salt); 32 | 33 | await prisma.empresa.update({ 34 | where: { 35 | cnpj 36 | }, 37 | data: { 38 | password: hash, 39 | tentativasRestantes: 5 40 | } 41 | }); 42 | 43 | const token = generateAccessTokenEmpresa(empresa); 44 | 45 | if (!token) { 46 | throw new AppError("CNPJ ou senha inválidos."); 47 | } 48 | 49 | return { 50 | token: token, 51 | empresa: { 52 | cnpj: empresa.cnpj, 53 | email: empresa.email 54 | } 55 | } 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /server/src/modules/services/funcionario/GetunapprovedUsecase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | 4 | export class GetBoletinsEmAnaliseUseCase { 5 | async execute() { 6 | const boletins = await prisma.boletim.findMany({ 7 | where: { 8 | status: 'EM_ANALISE', 9 | }, 10 | include: { 11 | aluno: { 12 | include: { 13 | turmas: { 14 | include: { 15 | turma: true, 16 | } 17 | } 18 | } 19 | } 20 | }, 21 | orderBy: [ 22 | { 23 | aluno: { 24 | name: 'asc' 25 | } 26 | } 27 | ] 28 | }); 29 | 30 | if (!boletins.length) { 31 | throw new AppError('Nenhum boletim em análise encontrado.'); 32 | } 33 | 34 | const boletinsEmAnalise = boletins.map(boletim => ({ 35 | id: boletim.id, 36 | aluno: { 37 | id: boletim.aluno.id, 38 | name: boletim.aluno.name, 39 | turma: boletim.aluno.turmas.map(turma => turma.turma.inicio).join(', ') 40 | }, 41 | url: boletim.link, 42 | status: boletim.status 43 | })); 44 | 45 | return boletinsEmAnalise; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /server/src/modules/services/funcionario/InitFuncionarioUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Funcionario } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { InitFuncionarioDTO } from "../../interfaces/funcionarioDTOs"; 4 | import { AppError } from "../../../errors/error"; 5 | 6 | export class InitFuncionarioUseCase { 7 | async execute({ email, cargo }: InitFuncionarioDTO): Promise<{ funcionario: Pick }> { 8 | 9 | if (!email || !cargo) { 10 | throw new AppError("Parâmetros insuficientes ou inválidos."); 11 | } 12 | 13 | const funcionario = await prisma.funcionario.findFirst({ 14 | where: { 15 | email, 16 | cargo 17 | } 18 | }); 19 | 20 | if (!funcionario) { 21 | throw new AppError("Funcionário não encontrado ou cargo errado"); 22 | } 23 | 24 | return { 25 | funcionario: { 26 | email: funcionario.email, 27 | validated: funcionario.validated 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /server/src/modules/services/funcionario/LoginFuncionarioUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Funcionario } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { LoginFuncionarioDTO } from "../../interfaces/funcionarioDTOs"; 4 | import { AppError } from "../../../errors/error"; 5 | import { generateAccessTokenFuncionario } from "../../../jwt/jwtServices"; 6 | 7 | const bcrypt = require('bcrypt'); 8 | 9 | export class LoginFuncionarioUseCase { 10 | async execute({ email, password }: LoginFuncionarioDTO): Promise<{ token: string, funcionario: Pick }> { 11 | 12 | if (!email || !password) { 13 | throw new AppError("Parâmetros insuficientes ou inválidos."); 14 | } 15 | 16 | const funcionario = await prisma.funcionario.findFirst({ 17 | where: { 18 | email, 19 | validated: true 20 | } 21 | }); 22 | 23 | if (!funcionario) { 24 | throw new AppError("Funcionário não encontrado ou não validado"); 25 | } 26 | 27 | const isPasswordValid = bcrypt.compareSync(password, funcionario.password); 28 | 29 | if (!isPasswordValid) { 30 | throw new AppError("Email ou senha inválidos"); 31 | } 32 | 33 | const token = generateAccessTokenFuncionario(funcionario); 34 | 35 | if (!token) { 36 | throw new AppError("Email ou senha inválidos"); 37 | } 38 | 39 | return { 40 | token: token, 41 | funcionario: { 42 | name: funcionario.name, 43 | email: funcionario.email, 44 | cargo: funcionario.cargo 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/funcionario/RefreshTokenUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { generateAccessTokenFuncionario } from "../../../jwt/jwtServices"; 4 | 5 | export class RefreshTokenUseCase { 6 | async execute(email: string ): Promise<{ token: string, message: string }> { 7 | 8 | if (!email) { 9 | throw new AppError("Parâmetros insuficientes ou inválidos."); 10 | } 11 | 12 | const funcionario = await prisma.funcionario.findFirst({ 13 | where: { 14 | email 15 | } 16 | }); 17 | 18 | if (!funcionario) { 19 | throw new AppError("Email inválido"); 20 | } 21 | 22 | const token = generateAccessTokenFuncionario(funcionario); 23 | 24 | if (!token) { 25 | throw new AppError("Email inválido"); 26 | } 27 | 28 | return { 29 | token: token, 30 | message: "token atualizado com sucesso!" 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/funcionario/SetAsParceiraUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { SetEmpresaParceiraDTO } from "../../interfaces/funcionarioDTOs"; 3 | import { AppError } from "../../../errors/error"; 4 | 5 | export class SetEmpresaParceiraUseCase { 6 | async execute({ funcionarioId, emailEmpresa }: SetEmpresaParceiraDTO) { 7 | if (!funcionarioId || !emailEmpresa) { 8 | throw new AppError("Parâmetros insuficientes ou inválidos."); 9 | } 10 | 11 | const funcionario = await prisma.funcionario.findUnique({ 12 | where: { 13 | id: funcionarioId 14 | } 15 | }); 16 | 17 | if (!funcionario) { 18 | throw new AppError("Funcionário não encontrado."); 19 | } 20 | 21 | const empresa = await prisma.empresa.findUnique({ 22 | where: { 23 | email: emailEmpresa 24 | } 25 | }); 26 | 27 | if (!empresa) { 28 | throw new AppError("Empresa não encontrada."); 29 | } 30 | 31 | const empresaParceira = await prisma.empresa.update({ 32 | where: { 33 | id: emailEmpresa 34 | }, 35 | data: { 36 | patrocinador: true 37 | } 38 | }); 39 | 40 | return empresaParceira; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /server/src/modules/services/funcionario/ValidateFuncionarioUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Funcionario } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { ValidateFuncionarioDTO } from "../../interfaces/funcionarioDTOs"; 4 | import { AppError } from "../../../errors/error"; 5 | 6 | const bcrypt = require('bcrypt'); 7 | 8 | export class ValidateFuncionarioUseCase { 9 | async execute({ email, temporaryPassword, newPassword }: ValidateFuncionarioDTO): Promise> { 10 | 11 | if (!email || !temporaryPassword || !newPassword) { 12 | throw new AppError("Parâmetros insuficientes ou inválidos: " + email + temporaryPassword + newPassword); 13 | } 14 | 15 | const funcionario = await prisma.funcionario.findFirst({ 16 | where: { 17 | email, 18 | validated: false 19 | } 20 | }); 21 | 22 | if (!funcionario) { 23 | throw new AppError("Email não cadastrado ou funcionário já validado!"); 24 | } 25 | 26 | const isPasswordValid = bcrypt.compareSync(temporaryPassword, funcionario.password); 27 | 28 | if (!isPasswordValid) { 29 | throw new AppError("Senha inválida!"); 30 | } 31 | 32 | const salt = bcrypt.genSaltSync(10); 33 | const hash = bcrypt.hashSync(newPassword, salt); 34 | 35 | const funcionarioUpdate = await prisma.funcionario.update({ 36 | where: { 37 | email, 38 | }, 39 | data: { 40 | password: hash, 41 | validated: true 42 | } 43 | }); 44 | 45 | if (!funcionarioUpdate) { 46 | throw new AppError("Erro ao autenticar funcionário!"); 47 | } 48 | 49 | return { 50 | name: funcionarioUpdate.name, 51 | email: funcionarioUpdate.email, 52 | cargo: funcionarioUpdate.cargo, 53 | validated: funcionarioUpdate.validated 54 | }; 55 | } 56 | } -------------------------------------------------------------------------------- /server/src/modules/services/professor/CreateActivityUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Professor } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { AppError } from "../../../errors/error"; 4 | import { CreateActivityDTO } from "../../interfaces/professorDTOs"; 5 | import { clearUploads } from "../shared/helpers/helpers"; 6 | import { uploadToMinio } from "../../../minioService"; 7 | 8 | 9 | export class CreateActivityUseCase { 10 | async execute({ title, descricao, professorId, imagem }: CreateActivityDTO) { 11 | if (!title || !descricao || !professorId || !imagem) { 12 | throw new AppError("Parâmetros insuficientes ou inválidos."); 13 | } 14 | 15 | const professor = await prisma.professor.findUnique({ 16 | where: { id: professorId } 17 | }); 18 | 19 | if (!professor) { 20 | throw new Error('Professor não encontrado'); 21 | } 22 | 23 | const bucketName = 'boot'; 24 | const objectName = `atividades/${professor.email}/title`; 25 | 26 | try { 27 | const filePath = imagem.path; 28 | await uploadToMinio(bucketName, objectName, filePath); 29 | 30 | clearUploads(); 31 | await prisma.atividade.create({ 32 | data: { 33 | title, 34 | descricao, 35 | professorId, 36 | imagem: objectName 37 | } 38 | }); 39 | 40 | return "Atividade criada com sucesso1"; 41 | } catch (error) { 42 | throw new AppError(`Error uploading image: ${error}`); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /server/src/modules/services/professor/GetCurriculoUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | 4 | export class GetCurriculoUseCase { 5 | async execute(email: string) { 6 | if (!email) { 7 | throw new AppError("Parâmetros insufientes ou inválidos. " + email); 8 | } 9 | 10 | const professor = await prisma.professor.findFirst({ 11 | where: { 12 | email: email 13 | }, 14 | }); 15 | 16 | if (!professor) { 17 | throw new AppError("Aluno não encontrado."); 18 | } 19 | 20 | const vinculos = await prisma.vinculo.findMany({ 21 | where:{ 22 | AND: [ 23 | {OR: [ 24 | {professorId: professor.id}, 25 | {vinculoComProfessorId: professor.id} 26 | ]}, 27 | {accepted: true} 28 | ]} 29 | }); 30 | 31 | return { 32 | curriculo: professor.curriculo, 33 | nome: professor.name, 34 | email: email, 35 | quantidadeVinculos: vinculos.length 36 | }; 37 | } 38 | } -------------------------------------------------------------------------------- /server/src/modules/services/professor/InitProfessorUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Professor } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { InitProfessorDTO } from "../../interfaces/professorDTOs"; 4 | import { AppError } from "../../../errors/error"; 5 | 6 | export class InitProfessorUseCase { 7 | async execute({ email }: InitProfessorDTO): Promise<{ professor: Pick }> { 8 | 9 | if (!email) { 10 | throw new AppError("Parâmetros insuficientes ou inválidos."); 11 | } 12 | 13 | const professor = await prisma.professor.findFirst({ 14 | where: { 15 | email 16 | } 17 | }); 18 | 19 | if (!professor) { 20 | throw new AppError("Professor não encontrado"); 21 | } 22 | 23 | return { 24 | professor: { 25 | name: professor.name, 26 | email: professor.email, 27 | validated: professor.validated 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /server/src/modules/services/professor/LinkAlunoActivityUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { RelateAlunoAtividadeDTO } from "../../interfaces/professorDTOs"; 4 | 5 | export class RelateAlunoAtividadeUseCase { 6 | async execute({ alunoId, atividadeId, professorId, mencao }: RelateAlunoAtividadeDTO) { 7 | if (!alunoId || !atividadeId || !professorId || !mencao) { 8 | throw new AppError("Parâmetros insuficientes ou inválidos."); 9 | } 10 | 11 | const atividade = await prisma.atividade.findUnique({ 12 | where: { id: atividadeId } 13 | }); 14 | 15 | if (!atividade) { 16 | throw new AppError("Atividade não encontrada."); 17 | } 18 | 19 | const professor = await prisma.professor.findUnique({ 20 | where: { id: professorId } 21 | }); 22 | 23 | if (!professor) { 24 | throw new AppError("Professor não encontrado."); 25 | } 26 | 27 | if(atividade.professorId != professorId){ 28 | throw new AppError("Professor inválido."); 29 | } 30 | 31 | const aluno = await prisma.aluno.findUnique({ 32 | where: { id: alunoId } 33 | }); 34 | 35 | if (!aluno) { 36 | throw new AppError("Aluno não encontrado."); 37 | } 38 | 39 | try { 40 | await prisma.alunoAtividade.create({ 41 | data: { 42 | alunoId, 43 | atividadeId, 44 | mencao 45 | } 46 | }); 47 | 48 | return "Aluno relacionado à atividade com sucesso."; 49 | } catch (error) { 50 | throw new AppError(`Erro ao relacionar aluno à atividade: ${error}`); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /server/src/modules/services/professor/LoginProfessorUseCase.ts: -------------------------------------------------------------------------------- 1 | import { Professor } from "@prisma/client"; 2 | import { prisma } from "../../../prisma/client"; 3 | import { LoginProfessorDTO } from "../../interfaces/professorDTOs"; 4 | import { AppError } from "../../../errors/error"; 5 | import { generateAccessTokenProfessor } from "../../../jwt/jwtServices"; 6 | 7 | const bcrypt = require('bcrypt'); 8 | 9 | export class LoginProfessorUseCase { 10 | async execute({ email, password }: LoginProfessorDTO): Promise<{ token: string, professor: Pick }> { 11 | 12 | if (!email || !password) { 13 | throw new AppError("Parâmetros insuficientes ou inválidos."); 14 | } 15 | 16 | const professor = await prisma.professor.findFirst({ 17 | where: { 18 | email, 19 | validated: true 20 | } 21 | }); 22 | 23 | if (!professor) { 24 | throw new AppError("Professor não encontrado ou não validado"); 25 | } 26 | 27 | const isPasswordValid = bcrypt.compareSync(password, professor.password); 28 | 29 | if (!isPasswordValid) { 30 | throw new AppError("Email ou senha inválidos"); 31 | } 32 | 33 | const token = generateAccessTokenProfessor(professor); 34 | 35 | if (!token) { 36 | throw new AppError("Email ou senha inválidos"); 37 | } 38 | 39 | return { 40 | token: token, 41 | professor: { 42 | name: professor.name, 43 | email: professor.email, 44 | tituloPrincipal: professor.tituloPrincipal 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/professor/RefreshTokenUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { generateAccessTokenProfessor } from "../../../jwt/jwtServices"; 4 | 5 | export class RefreshTokenUseCase { 6 | async execute(email: string ): Promise<{ token: string, message: string }> { 7 | 8 | if (!email) { 9 | throw new AppError("Parâmetros insuficientes ou inválidos."); 10 | } 11 | 12 | const professor = await prisma.professor.findFirst({ 13 | where: { 14 | email 15 | } 16 | }); 17 | 18 | if (!professor) { 19 | throw new AppError("Email inválido"); 20 | } 21 | 22 | const token = generateAccessTokenProfessor(professor); 23 | 24 | if (!token) { 25 | throw new AppError("Email inválido"); 26 | } 27 | 28 | return { 29 | token: token, 30 | message: "token atualizado com sucesso!" 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/professor/UodateCurriculoUseCase copy.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { UpdateCurriculoDTO } from "../../interfaces/alunoDTOs" 3 | import { AppError } from "../../../errors/error"; 4 | 5 | export class UpdateCurriculoUseCase { 6 | async execute({ email, curriculo }: UpdateCurriculoDTO) { 7 | 8 | if (!email) { 9 | throw new AppError("Parâmetros insuficientes ou inválidos."); 10 | } 11 | 12 | const professor = await prisma.professor.findUnique({ 13 | where: { 14 | email 15 | } 16 | }); 17 | 18 | if (professor) { 19 | await prisma.professor.update({ 20 | where: { 21 | email 22 | }, 23 | data: { 24 | curriculo: curriculo 25 | } 26 | }); 27 | 28 | return; 29 | } else { 30 | throw new AppError("Email não encontrado"); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/professor/UodateCurriculoUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { UpdateCurriculoDTO } from "../../interfaces/alunoDTOs" 3 | import { AppError } from "../../../errors/error"; 4 | 5 | export class UpdateCurriculoUseCase { 6 | async execute({ email, curriculo }: UpdateCurriculoDTO) { 7 | 8 | if (!email) { 9 | throw new AppError("Parâmetros insuficientes ou inválidos."); 10 | } 11 | 12 | const professor = await prisma.professor.findUnique({ 13 | where: { 14 | email 15 | } 16 | }); 17 | 18 | if (professor) { 19 | await prisma.professor.update({ 20 | where: { 21 | email 22 | }, 23 | data: { 24 | curriculo: curriculo 25 | } 26 | }); 27 | 28 | return; 29 | } else { 30 | throw new AppError("Email não encontrado"); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/professor/UploadCapaUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { uploadToMinio } from "../../../minioService"; 4 | import { UploadImageDTO } from "../../interfaces/alunoDTOs"; 5 | import { clearUploads } from "../shared/helpers/helpers"; 6 | 7 | export class UploadCapaUseCase { 8 | async execute({ email, file }: UploadImageDTO) { 9 | 10 | if (!email || !file) { 11 | throw new AppError("Parâmetros insuficientes ou inválidos."); 12 | } 13 | 14 | const professor = await prisma.professor.findUnique({ 15 | where: { 16 | email 17 | } 18 | }); 19 | 20 | if (professor) { 21 | const bucketName = 'boot'; 22 | const objectName = `professor/${professor.id}/banner`; 23 | 24 | try { 25 | const filePath = file.path; 26 | await uploadToMinio(bucketName, objectName, filePath); 27 | 28 | await prisma.professor.update({ 29 | where: { 30 | email 31 | }, 32 | data: { 33 | banner: objectName 34 | } 35 | }); 36 | 37 | clearUploads(); 38 | return { message: 'Imagem de banner salva com sucesso!' }; 39 | } catch (error) { 40 | throw new AppError(`Error uploading image: ${error}`); 41 | } 42 | 43 | return; 44 | } else { 45 | throw new AppError("Email não encontrado"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/professor/UploadProfileUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { uploadToMinio } from "../../../minioService"; 4 | import { UploadImageDTO } from "../../interfaces/alunoDTOs"; 5 | import { clearUploads } from "../shared/helpers/helpers"; 6 | 7 | export class UploadProfileUseCase { 8 | async execute({ email, file } : UploadImageDTO) { 9 | 10 | if (!email) { 11 | throw new AppError("Parâmetros insuficientes ou inválidos."); 12 | } else if (!file) { 13 | throw new AppError("File precisa ser enviado."); 14 | } 15 | 16 | const professor = await prisma.professor.findUnique({ 17 | where: { 18 | email 19 | } 20 | }); 21 | 22 | if (professor) { 23 | const bucketName = 'boot'; 24 | const objectName = `professor/${professor.id}/perfil`; 25 | 26 | try { 27 | const filePath = file.path; 28 | await uploadToMinio(bucketName, objectName, filePath); 29 | 30 | await prisma.professor.update({ 31 | where: { 32 | email 33 | }, 34 | data: { 35 | imagem: objectName 36 | } 37 | }); 38 | 39 | clearUploads(); 40 | return { message: 'Imagem de perfil salva com sucesso!.' }; 41 | } catch (error) { 42 | throw new AppError(`Error uploading image: ${error}`); 43 | } 44 | } else { 45 | throw new AppError("Email não encontrado"); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /server/src/modules/services/shared/GetBannerUseCase.ts: -------------------------------------------------------------------------------- 1 | import { AppError } from "../../../errors/error"; 2 | import { EntidadeEnum, GetEntidadeDTO } from "../../interfaces/sharedDTOs"; 3 | import { FindEntidade } from "./helpers/helpers"; 4 | import { minioClient } from '../../../minioService'; 5 | 6 | interface EntidadeComBanner { 7 | banner: string | null; 8 | } 9 | 10 | export class GetBannerUseCase { 11 | async execute({ email, identifier } : GetEntidadeDTO) { 12 | 13 | if (!identifier || !email) { 14 | throw new AppError("Parâmetros insufientes ou inválidos."); 15 | } 16 | 17 | const entidade = await FindEntidade(email, EntidadeEnum[identifier]); 18 | 19 | if (!entidade) { 20 | throw new AppError(`${identifier.charAt(0).toUpperCase()}${identifier.slice(1).toLowerCase()} não encontrado.`); 21 | } 22 | 23 | const bucketName = 'boot'; 24 | 25 | const entidadeComBanner = entidade as EntidadeComBanner; 26 | let url = "default"; 27 | 28 | if(entidadeComBanner){ 29 | const imageName = entidadeComBanner.banner as string; 30 | const objectExists = await minioClient.statObject(bucketName, imageName); 31 | 32 | if (objectExists) { 33 | url = await minioClient.presignedUrl('GET', bucketName, imageName, 24 * 60 * 60); 34 | } 35 | 36 | } 37 | 38 | return { 39 | url: url 40 | }; 41 | } 42 | } -------------------------------------------------------------------------------- /server/src/modules/services/shared/GetCurriculoUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | 4 | export class GetCurriculoUseCase { 5 | async execute(rm : string) { 6 | if (!rm) { 7 | throw new AppError("Parâmetros insufientes ou inválidos."); 8 | } 9 | 10 | const aluno = await prisma.aluno.findFirst({ 11 | where: { 12 | rm 13 | }, 14 | }); 15 | 16 | if (!aluno) { 17 | throw new AppError("Aluno não encontrado."); 18 | } 19 | 20 | return { 21 | curriculo: aluno.curriculo, 22 | nome: aluno.name, 23 | endereco: aluno.endereco, 24 | nascimento: aluno.dataNascimento, 25 | email: aluno.email 26 | }; 27 | } 28 | } -------------------------------------------------------------------------------- /server/src/modules/services/shared/GetCursosUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { Curso } from "@prisma/client"; 3 | 4 | export class GetCursosUseCase { 5 | async execute(): Promise[]> { 6 | 7 | const cursos = await prisma.curso.findMany({}); 8 | 9 | return cursos.map(curso => { 10 | return { 11 | name: curso.name 12 | } 13 | }); 14 | } 15 | } -------------------------------------------------------------------------------- /server/src/modules/services/shared/GetEmpresasUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { Empresa } from "@prisma/client"; 3 | 4 | export class GetEmpresasUseCase { 5 | async execute(): Promise[]> { 6 | 7 | const empresas = await prisma.empresa.findMany({}); 8 | 9 | return empresas.map(empresa => { 10 | return { 11 | name: empresa.name, 12 | email: empresa.email 13 | } 14 | }); 15 | } 16 | } -------------------------------------------------------------------------------- /server/src/modules/services/shared/GetExtraUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | 4 | export class GetExtracurricularsByRMUseCase { 5 | async execute(rm: string) { 6 | if (!rm) { 7 | throw new AppError("Parâmetros insuficientes ou inválidos. " + rm); 8 | } 9 | 10 | const aluno = await prisma.aluno.findFirst({ 11 | where: { 12 | rm: rm, 13 | }, 14 | select: { 15 | cursosExtracurriculares: { 16 | select: { 17 | extracurricularId: true, 18 | instituicao: true, 19 | descricao: true, 20 | inicio: true, 21 | fim: true, 22 | }, 23 | }, 24 | }, 25 | }); 26 | 27 | if (!aluno) { 28 | throw new AppError("Aluno não encontrado."); 29 | } 30 | 31 | return aluno.cursosExtracurriculares; 32 | } 33 | } -------------------------------------------------------------------------------- /server/src/modules/services/shared/GetProfileImageUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { EntidadeEnum, GetEntidadeDTO } from "../../interfaces/sharedDTOs"; 4 | import { FindEntidade, getImgUrl } from "./helpers/helpers"; 5 | import { minioClient } from '../../../minioService'; 6 | 7 | export class GetProfileImageUseCase { 8 | async execute({ email, identifier } : GetEntidadeDTO) { 9 | console.log(email); 10 | if (!email) { 11 | throw new AppError("Campo 'email' é necessário. aaaa"); 12 | } 13 | 14 | if (!identifier) { 15 | throw new AppError("Campo 'identifier' é necessário."); 16 | } 17 | 18 | const entidade = await FindEntidade(email, EntidadeEnum[identifier]); 19 | 20 | if (!entidade) { 21 | throw new AppError(`${identifier.charAt(0).toUpperCase()}${identifier.slice(1).toLowerCase()} não encontrado.`); 22 | } 23 | 24 | const bucketName = 'boot'; 25 | const imageName = entidade.imagem as string; 26 | 27 | let entityUrl = "default"; 28 | 29 | if (imageName) { 30 | const objectExists = await minioClient.statObject(bucketName, imageName); 31 | if(objectExists){ 32 | entityUrl = await minioClient.presignedUrl('GET', bucketName, imageName, 24 * 60 * 60); 33 | } 34 | } 35 | 36 | return { 37 | url: entityUrl 38 | }; 39 | } 40 | } -------------------------------------------------------------------------------- /server/src/modules/services/shared/GetProfilesUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | import { AppError } from "../../../errors/error"; 3 | import { getImgUrl } from "./helpers/helpers"; 4 | import { Aluno } from "@prisma/client"; 5 | 6 | export class SearchUsersUseCase { 7 | async execute() { 8 | try { 9 | const alunosBusca = await prisma.aluno.findMany({ 10 | where:{ 11 | rm:{ 12 | not: null 13 | } 14 | }, 15 | select: { 16 | email: true, 17 | rm: true, 18 | endereco: true, 19 | name: true, 20 | imagem: true, 21 | }, 22 | orderBy:{ 23 | name: 'asc' 24 | } 25 | }); 26 | 27 | if (!alunosBusca || alunosBusca.length === 0) { 28 | throw new AppError("Nenhum aluno encontrado.", 404); 29 | } 30 | 31 | const alunos = await Promise.all(alunosBusca.map(async (aluno) => { 32 | return { 33 | email: aluno.email, 34 | rm: aluno.rm, 35 | endereco: aluno.endereco, 36 | name: aluno.name, 37 | imageUrl: await getImgUrl(aluno as Aluno) 38 | }; 39 | })); 40 | 41 | return { 42 | alunos: alunos 43 | } 44 | } catch (error) { 45 | console.error("Erro ao buscar alunos:", error); 46 | throw new AppError("Erro ao buscar alunos.", 500); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /server/src/modules/services/shared/GetVagaUseCase.ts: -------------------------------------------------------------------------------- 1 | import { AppError } from "../../../errors/error"; 2 | import { minioClient } from "../../../minioService"; 3 | import { prisma } from "../../../prisma/client"; 4 | 5 | export class GetVagaUseCase { 6 | async execute(id: string){ 7 | 8 | const vaga = await prisma.vaga.findUnique({ 9 | where:{ 10 | id: id 11 | }, 12 | include:{ 13 | curso: true, 14 | empresa: true, 15 | } 16 | }); 17 | 18 | if(!vaga){ 19 | throw new AppError("Vaga não encontrada"); 20 | } 21 | 22 | const bucketName = 'boot'; 23 | const imageName = vaga.empresa.imagem as string; 24 | 25 | let entityUrl = "default"; 26 | 27 | if (imageName) { 28 | const objectExists = await minioClient.statObject(bucketName, imageName); 29 | if(objectExists){ 30 | entityUrl = await minioClient.presignedUrl('GET', bucketName, imageName, 24 * 60 * 60); 31 | } 32 | } 33 | 34 | return { 35 | vaga:{ 36 | id: vaga.id, 37 | titulo: vaga.titulo, 38 | empresa: { 39 | cnpj: vaga.empresa.cnpj, 40 | email: vaga.empresa.email, 41 | name: vaga.empresa.name, 42 | entityUrl: entityUrl 43 | }, 44 | curso: vaga.curso.name, 45 | remuneracao: vaga.remuneracao, 46 | cargaHoraria: vaga.cargaHoraria, 47 | requisitos: vaga.requisitos, 48 | beneficios: vaga.beneficios, 49 | entrada: vaga.entrada, 50 | saida: vaga.saida, 51 | status: vaga.status, 52 | descricao: vaga.descricao 53 | } 54 | }; 55 | } 56 | } -------------------------------------------------------------------------------- /server/src/modules/services/shared/GetVagasUseCase.ts: -------------------------------------------------------------------------------- 1 | import { prisma } from "../../../prisma/client"; 2 | 3 | export class GetVagasUseCase { 4 | async execute(){ 5 | 6 | const vagas = await prisma.vaga.findMany({ 7 | include:{ 8 | empresa: true, 9 | curso: true 10 | } 11 | }); 12 | 13 | return vagas.map(vaga => { 14 | return { 15 | id: vaga.id, 16 | titulo: vaga.titulo, 17 | empresa: vaga.empresa.name, 18 | curso: vaga.curso.name, 19 | remuneracao: vaga.remuneracao, 20 | cargaHoraria: vaga.cargaHoraria 21 | } 22 | }); 23 | } 24 | } -------------------------------------------------------------------------------- /server/src/pdf/curriculum_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 |
11 |

{{name}}

12 |

Idade:{{idade}}

13 |

Email:{{email}}

14 |

Telefone:{{numero}}

15 |
16 |

{{endereco}}

17 |

{{cidade}}

18 |
19 |
20 |
21 |

{{titulo}}

22 |
23 | 24 |
25 |
26 | 27 |
28 | 29 |
30 |

Resumo

31 |

{{aboutMe}}

32 |
33 | 34 |
35 | 36 |
37 |

Formação Acadêmica

38 |
    39 | {{academicTraining}} 40 |
41 |
42 | 43 |
44 | 45 |
46 |

🌐 https://boot.portfolioeducacionalrgs.com/aluno/profile/{{rm}}

47 |
48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /server/src/pdf/style.css: -------------------------------------------------------------------------------- 1 | *{ 2 | overflow-x: hidden; 3 | padding: 0; 4 | margin: 0; 5 | } 6 | 7 | body{ 8 | width: 1000px; 9 | padding: 140px 60px 60px 60px; 10 | } 11 | 12 | .box{ 13 | display: flex; 14 | width: 100%; 15 | flex-direction: column; 16 | align-items: start; 17 | justify-content: flex-start; 18 | font-family: 'Times New Roman', Times, serif; 19 | margin-bottom: 30px; 20 | } 21 | 22 | .box h1 { 23 | font-size: 52px; 24 | font-weight: bold; 25 | margin-bottom: 10px; 26 | } 27 | 28 | .box h2 { 29 | font-size: 38px; 30 | font-weight: bold; 31 | } 32 | 33 | .box p { 34 | font-size: 22px; 35 | opacity: .8; 36 | margin-top: 10px; 37 | } 38 | 39 | .box-1 p { 40 | font-size: 24px; 41 | } 42 | 43 | .box div { 44 | display: flex; 45 | flex-direction: row; 46 | align-items: start; 47 | justify-content: space-between; 48 | 49 | } 50 | 51 | .box div div { 52 | display: flex; 53 | flex-direction: column; 54 | align-items: self-start; 55 | justify-content: start; 56 | width: 65%; 57 | } 58 | 59 | .box img { 60 | width: 350px; 61 | border-radius: 50%; 62 | object-fit: cover; 63 | } 64 | 65 | hr { 66 | border: none; 67 | height: 0px; 68 | width: 1000px; 69 | margin: 20px 0px; 70 | border-top: solid 5px #114554; 71 | } 72 | 73 | ul{ 74 | list-style-type: none; 75 | margin-bottom: 20px; 76 | } 77 | 78 | p b:nth-of-type(2) { 79 | margin-left: 10px; 80 | } 81 | 82 | b { 83 | margin-right: 10px; 84 | } 85 | 86 | .bold{ 87 | font-weight: 700; 88 | } 89 | 90 | .box-4 { 91 | margin-bottom: 0px; 92 | width: 1000px; 93 | justify-content: center; 94 | align-items: center; 95 | } -------------------------------------------------------------------------------- /server/src/prisma/client.ts: -------------------------------------------------------------------------------- 1 | import { PrismaClient } from "@prisma/client"; 2 | 3 | export const prisma = new PrismaClient(); -------------------------------------------------------------------------------- /server/src/router/index.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | 3 | import { adminRoutes } from "./routes/admin.routes" 4 | import { alunoRoutes } from "./routes/aluno.routes"; 5 | import { empresaRoutes } from "./routes/empresa.routes" 6 | import { funcionarioRoutes } from "./routes/funcionario.routes"; 7 | import { professorRoutes } from "./routes/professor.routes"; 8 | import { sharedRoutes } from "./routes/shared.routes"; 9 | 10 | const routes = Router(); 11 | 12 | routes.use("/admin", adminRoutes); 13 | routes.use("/aluno", alunoRoutes); 14 | routes.use("/empresa", empresaRoutes); 15 | routes.use("/funcionario", funcionarioRoutes); 16 | routes.use("/professor", professorRoutes); 17 | routes.use("/shared", sharedRoutes); 18 | 19 | export { routes }; -------------------------------------------------------------------------------- /server/src/router/routes/admin.routes.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { adminAuthMiddleware } from '../../middleware/auth/autentication'; 3 | import { createControllers } from "./imports/admin"; 4 | 5 | const controllers = createControllers(); 6 | const adminRoutes = Router(); 7 | 8 | adminRoutes.post("/login", controllers.loginAdminController.handle); 9 | 10 | adminRoutes.use(adminAuthMiddleware); 11 | 12 | adminRoutes.post("/register/course", controllers.registerCursosController.handle); 13 | adminRoutes.post("/register/professor", controllers.registerProfessorController.handle); 14 | adminRoutes.post("/register/funcionario", controllers.registerFuncionarioController.handle); 15 | adminRoutes.post("/register/coordenador", controllers.registerCoordenadorController.handle); 16 | adminRoutes.post("/register/turma", controllers.registerTurmaController.handle); 17 | 18 | adminRoutes.get("/auth", (req, res) => { 19 | res.status(200).send("Admin autenticado com sucesso."); 20 | }); 21 | 22 | adminRoutes.get("/professores", controllers.getAllProfessoresController.handle); 23 | adminRoutes.get("/coordenadores", controllers.getAllCoordenadoresController.handle); 24 | adminRoutes.get("/cursos", controllers.getCursosController.handle); 25 | adminRoutes.get("/token/refresh", controllers.refreshTokenController.handle); 26 | adminRoutes.get("/table/professores", controllers.getFullProfessoresController.handle); 27 | adminRoutes.get("/table/coordenadores", controllers.getFullCoordenadoresController.handle); 28 | adminRoutes.get("/table/cursos", controllers.getFullCursosController.handle); 29 | adminRoutes.get("/table/estagios", controllers.getFullEstagiosController.handle); 30 | adminRoutes.get("/table/funcionarios", controllers.getFullFuncionariosController.handle); 31 | adminRoutes.get("/table/turmas", controllers.getFullTurmasController.handle); 32 | adminRoutes.get("/table/empresas", controllers.getFullEmpresasController.handle); 33 | 34 | export { adminRoutes }; -------------------------------------------------------------------------------- /server/src/router/routes/empresa.routes.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { empresaAuthMiddleware } from '../../middleware/auth/autentication'; 3 | import { createControllers } from "./imports/empresa"; 4 | import multer from "multer"; 5 | 6 | const controllers = createControllers(); 7 | const empresaRoutes = Router(); 8 | const upload = multer({ dest: 'uploads/' }); 9 | 10 | empresaRoutes.post("/register", controllers.registerEmpresaController.handle); 11 | empresaRoutes.post("/register/validate", controllers.validateEmpresaController.handle); 12 | empresaRoutes.post("/login", controllers.loginEmpresaController.handle); 13 | empresaRoutes.post("/recovery", controllers.recoveryEmpresaController.handle); 14 | empresaRoutes.post("/recovery/validate", controllers.validateRecoveryEmpresaController.handle); 15 | 16 | empresaRoutes.post('/upload/image/banner', upload.single('file'), empresaAuthMiddleware, controllers.uploadCapaController.handle); 17 | empresaRoutes.post('/upload/image/profile', upload.single('file'), empresaAuthMiddleware, controllers.uploadImgProfileController.handle); 18 | 19 | 20 | empresaRoutes.use(empresaAuthMiddleware); 21 | empresaRoutes.post("/message/send", controllers.createMessageController.handle); 22 | empresaRoutes.post("/update/site", controllers.UpdateSiteController.handle); 23 | 24 | empresaRoutes.get("/auth", (req, res) => { 25 | res.status(200).send("Empresa autenticada com sucesso."); 26 | }); 27 | 28 | empresaRoutes.get("/token/refresh", controllers.refreshTokenController.handle); 29 | empresaRoutes.get("/messages", controllers.getLastMessagesController.handle); 30 | empresaRoutes.get("/messages/between", controllers.getMessagesBetweenController.handle); 31 | 32 | export { empresaRoutes }; -------------------------------------------------------------------------------- /server/src/router/routes/funcionario.routes.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { funcionarioAuthMiddleware } from '../../middleware/auth/autentication'; 3 | import { createControllers } from "./imports/funcionario"; 4 | import multer from "multer"; 5 | 6 | const controllers = createControllers(); 7 | const upload = multer({ dest: 'uploads/' }); 8 | const funcionarioRoutes = Router(); 9 | 10 | funcionarioRoutes.post("/validate", controllers.validateFuncionarioController.handle); 11 | funcionarioRoutes.post("/login", controllers.loginFuncionarioController.handle); 12 | funcionarioRoutes.post("/recovery", controllers.recoveryFuncionarioController.handle); 13 | funcionarioRoutes.post("/recovery/validate", controllers.validateRecoveryController.handle); 14 | 15 | funcionarioRoutes.get("/init", controllers.initFuncionarioController.handle); 16 | 17 | funcionarioRoutes.post('/boletim/compare', upload.single('file'), funcionarioAuthMiddleware, controllers.compareBoletimController.handle); 18 | 19 | funcionarioRoutes.use(funcionarioAuthMiddleware); 20 | funcionarioRoutes.post("/register/vaga", controllers.registerVagaController.handle); 21 | funcionarioRoutes.post("/update/empresa", controllers.registerVagaController.handle); 22 | funcionarioRoutes.post("/message/send", controllers.createMessageController.handle); 23 | 24 | funcionarioRoutes.get("/auth", (req, res) => { 25 | res.status(200).send("Funcionário autenticado com sucesso."); 26 | }); 27 | 28 | funcionarioRoutes.get("/token/refresh", controllers.refreshTokenController.handle); 29 | funcionarioRoutes.get("/cursos", controllers.getCursosController.handle); 30 | funcionarioRoutes.get("/empresas", controllers.getEmpresasController.handle); 31 | funcionarioRoutes.get("/messages/between", controllers.getMessagesBetweenController.handle); 32 | funcionarioRoutes.get("/boletins", controllers.getBoletinsEmAnaliseController.handle); 33 | 34 | 35 | export { funcionarioRoutes }; -------------------------------------------------------------------------------- /server/src/router/routes/imports/admin.ts: -------------------------------------------------------------------------------- 1 | import { 2 | GetCursosController 3 | } from "../../../modules/controllers/sharedControllers" 4 | import { 5 | LoginAdminController, 6 | RegisterCursosController, 7 | RegisterProfessorController, 8 | RegisterFuncionarioController, 9 | RegisterCoordenadorController, 10 | GetAllProfessoresController, 11 | GetAllCoordenadoresController, 12 | RegisterTurmaController, 13 | RefreshTokenController, 14 | GetFullProfessoresController, 15 | GetFullCoordenadoresController, 16 | GetFullCursosController, 17 | GetFullEstagiosController, 18 | GetFullFuncionariosController, 19 | GetFullTurmasController, 20 | GetFullEmpresasController 21 | } from "../../../modules/controllers/adminControllers"; 22 | 23 | export const createControllers = () => ({ 24 | loginAdminController: new LoginAdminController(), 25 | registerCursosController: new RegisterCursosController(), 26 | registerProfessorController: new RegisterProfessorController(), 27 | registerFuncionarioController: new RegisterFuncionarioController(), 28 | registerCoordenadorController: new RegisterCoordenadorController(), 29 | registerTurmaController: new RegisterTurmaController(), 30 | getCursosController: new GetCursosController(), 31 | refreshTokenController: new RefreshTokenController(), 32 | getAllProfessoresController: new GetAllProfessoresController(), 33 | getAllCoordenadoresController: new GetAllCoordenadoresController(), 34 | getFullProfessoresController: new GetFullProfessoresController(), 35 | getFullCoordenadoresController: new GetFullCoordenadoresController(), 36 | getFullCursosController: new GetFullCursosController(), 37 | getFullEstagiosController: new GetFullEstagiosController(), 38 | getFullFuncionariosController: new GetFullFuncionariosController(), 39 | getFullTurmasController: new GetFullTurmasController(), 40 | getFullEmpresasController: new GetFullEmpresasController(), 41 | }); -------------------------------------------------------------------------------- /server/src/router/routes/imports/empresa.ts: -------------------------------------------------------------------------------- 1 | import { 2 | RegisterEmpresaController, 3 | ValidateEmpresaController, 4 | LoginEmpresaController, 5 | RecoveryEmpresaController, 6 | ValidateRecoveryEmpresaController, 7 | RefreshTokenController, 8 | GetMessagesBetweenController, 9 | UploadImgProfileController, 10 | UploadCapaController, 11 | UpdateSiteController, 12 | GetLastMessagesController, 13 | } from "../../../modules/controllers/empresaControllers"; 14 | import { 15 | CreateMessageController, 16 | } from "../../../modules/controllers/sharedControllers"; 17 | 18 | export const createControllers = () => ({ 19 | registerEmpresaController: new RegisterEmpresaController(), 20 | validateEmpresaController: new ValidateEmpresaController(), 21 | loginEmpresaController: new LoginEmpresaController(), 22 | recoveryEmpresaController: new RecoveryEmpresaController(), 23 | validateRecoveryEmpresaController: new ValidateRecoveryEmpresaController(), 24 | refreshTokenController: new RefreshTokenController(), 25 | createMessageController: new CreateMessageController(), 26 | getMessagesBetweenController: new GetMessagesBetweenController(), 27 | uploadImgProfileController: new UploadImgProfileController(), 28 | uploadCapaController: new UploadCapaController(), 29 | UpdateSiteController: new UpdateSiteController(), 30 | getLastMessagesController: new GetLastMessagesController(), 31 | }); -------------------------------------------------------------------------------- /server/src/router/routes/imports/funcionario.ts: -------------------------------------------------------------------------------- 1 | import { 2 | ValidateFuncionarioController, 3 | LoginFuncionarioController, 4 | InitFuncionarioController, 5 | RecoveryFuncionarioController, 6 | ValidateRecoveryController, 7 | RefreshTokenController, 8 | RegisterVagaController, 9 | FuncionarioController, 10 | GetMessagesBetweenController, 11 | CompareBoletimController, 12 | GetBoletinsEmAnaliseController 13 | } from "../../../modules/controllers/funcionarioControllers"; 14 | import { 15 | GetCursosController, 16 | GetEmpresasController, 17 | CreateMessageController 18 | } from "../../../modules/controllers/sharedControllers"; 19 | 20 | export const createControllers = () => ({ 21 | validateFuncionarioController: new ValidateFuncionarioController(), 22 | loginFuncionarioController: new LoginFuncionarioController(), 23 | initFuncionarioController: new InitFuncionarioController(), 24 | recoveryFuncionarioController: new RecoveryFuncionarioController(), 25 | validateRecoveryController: new ValidateRecoveryController(), 26 | refreshTokenController: new RefreshTokenController(), 27 | registerVagaController: new RegisterVagaController(), 28 | getCursosController: new GetCursosController(), 29 | getEmpresasController: new GetEmpresasController(), 30 | funcionarioController: new FuncionarioController(), 31 | createMessageController: new CreateMessageController(), 32 | getMessagesBetweenController: new GetMessagesBetweenController(), 33 | compareBoletimController: new CompareBoletimController(), 34 | getBoletinsEmAnaliseController: new GetBoletinsEmAnaliseController(), 35 | }); -------------------------------------------------------------------------------- /server/src/router/routes/imports/shared.ts: -------------------------------------------------------------------------------- 1 | import { 2 | GetCurriculoController, 3 | GetProfileImageController, 4 | GetBannerController, 5 | SearchUserController, 6 | GetVagasController, 7 | GetVagaController, 8 | GetExtracurricularsByRMController, 9 | GetRankingController, 10 | GetEmpresaController, 11 | } from "../../../modules/controllers/sharedControllers"; 12 | 13 | export const createControllers = () => ({ 14 | getCurriculoController: new GetCurriculoController(), 15 | getProfileImageController: new GetProfileImageController(), 16 | getBannerController: new GetBannerController(), 17 | searchUserController: new SearchUserController(), 18 | getVagasController: new GetVagasController(), 19 | getVagaController: new GetVagaController(), 20 | getExtracurricularsByRMController: new GetExtracurricularsByRMController(), 21 | getRankingController: new GetRankingController(), 22 | getEmpresaController: new GetEmpresaController(), 23 | }); -------------------------------------------------------------------------------- /server/src/router/routes/shared.routes.ts: -------------------------------------------------------------------------------- 1 | import { Router } from "express"; 2 | import { createControllers } from "./imports/shared"; 3 | 4 | const controllers = createControllers(); 5 | const sharedRoutes = Router(); 6 | 7 | sharedRoutes.get("/curriculo", controllers.getCurriculoController.handle); 8 | sharedRoutes.get("/profile/image", controllers.getProfileImageController.handle); 9 | sharedRoutes.get("/profile/banner", controllers.getBannerController.handle); 10 | sharedRoutes.get("/users", controllers.searchUserController.handle); 11 | sharedRoutes.get("/vagas", controllers.getVagasController.handle); 12 | sharedRoutes.get("/vaga", controllers.getVagaController.handle); 13 | sharedRoutes.get("/extracurriculares", controllers.getExtracurricularsByRMController.handle); 14 | sharedRoutes.get("/ranking/boletim", controllers.getRankingController.handle); 15 | sharedRoutes.get("/empresa", controllers.getEmpresaController.handle); 16 | 17 | export { sharedRoutes }; -------------------------------------------------------------------------------- /server/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [ 4 | { 5 | "src": "src/index.ts", 6 | "use": "@vercel/node" 7 | } 8 | ], 9 | "routes": [ 10 | { 11 | "src": "(./router/*)", 12 | "dest": "src/router/index.ts" 13 | } 14 | ] 15 | } --------------------------------------------------------------------------------