├── web ├── src │ ├── react-app-env.d.ts │ ├── services │ │ └── api.ts │ ├── App.tsx │ ├── index.tsx │ ├── assets │ │ ├── images │ │ │ ├── icons │ │ │ │ ├── blue-heart.svg │ │ │ │ ├── success-check-icon.svg │ │ │ │ ├── back.svg │ │ │ │ ├── give-classes.svg │ │ │ │ ├── study.svg │ │ │ │ ├── warning.svg │ │ │ │ ├── whatsapp.svg │ │ │ │ ├── rocket.svg │ │ │ │ └── smile.svg │ │ │ ├── logo.svg │ │ │ ├── success-background.svg │ │ │ └── landing.svg │ │ └── styles │ │ │ └── globals.css │ ├── components │ │ ├── Input │ │ │ ├── Input.tsx │ │ │ └── styles.css │ │ ├── Textarea │ │ │ ├── index.tsx │ │ │ └── styles.css │ │ ├── Select │ │ │ ├── styles.css │ │ │ └── index.tsx │ │ ├── PageHeader │ │ │ ├── index.tsx │ │ │ └── styles.css │ │ └── TeacherItem │ │ │ ├── index.tsx │ │ │ └── styles.css │ ├── routes.tsx │ └── pages │ │ ├── TeacherList │ │ ├── styles.css │ │ └── index.tsx │ │ ├── Landing │ │ ├── index.tsx │ │ └── style.css │ │ └── TeacherForm │ │ ├── styles.css │ │ └── index.tsx ├── .gitignore ├── public │ └── index.html ├── tsconfig.json └── package.json ├── server ├── .gitignore ├── src │ ├── utils │ │ └── convertHourToMinutes.ts │ ├── server.ts │ ├── database │ │ ├── connection.ts │ │ └── migrations │ │ │ ├── 00_create_users.ts │ │ │ ├── 01_create_classes.ts │ │ │ ├── 03_create_connections.ts │ │ │ └── 02_create_schedule.ts │ ├── routes.ts │ └── controllers │ │ ├── ConnectionsController.ts │ │ └── ClassesController.ts ├── knexfile.ts ├── package.json └── tsconfig.json ├── LICENSE └── README.md /web/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore directory 2 | node_modules/ 3 | 4 | # Ignore files 5 | database.sqlite 6 | -------------------------------------------------------------------------------- /web/src/services/api.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const api = axios.create({ 4 | baseURL: 'http://localhost:5000', 5 | }); 6 | 7 | export default api; -------------------------------------------------------------------------------- /web/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import Routes from './routes'; 4 | 5 | import './assets/styles/globals.css'; 6 | 7 | function App() { 8 | return ( 9 | 10 | ); 11 | } 12 | 13 | export default App; -------------------------------------------------------------------------------- /server/src/utils/convertHourToMinutes.ts: -------------------------------------------------------------------------------- 1 | export default function convertHourToMinutes(time: string) { 2 | 3 | const [hour, minutes] = time.split(':').map(Number) 4 | const timeInMinutes = (hour * 60) + minutes; 5 | 6 | return timeInMinutes 7 | 8 | } -------------------------------------------------------------------------------- /web/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /server/src/server.ts: -------------------------------------------------------------------------------- 1 | import express from 'express'; 2 | import cors from 'cors'; 3 | import routes from './routes'; 4 | 5 | const app = express(); 6 | const port = 5000 7 | 8 | app.use(cors()); 9 | app.use(express.json()); 10 | app.use(routes); 11 | 12 | app.listen(port); 13 | -------------------------------------------------------------------------------- /server/src/database/connection.ts: -------------------------------------------------------------------------------- 1 | import knex from 'knex'; 2 | import path from 'path'; 3 | 4 | const db = knex({ 5 | client: 'sqlite3', 6 | connection: { 7 | filename: path.resolve(__dirname, 'database.sqlite') 8 | }, 9 | useNullAsDefault: true, 10 | }); 11 | 12 | export default db; -------------------------------------------------------------------------------- /server/knexfile.ts: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | 3 | module.exports = { 4 | client: 'sqlite3', 5 | connection: { 6 | filename: path.resolve(__dirname, 'src', 'database', 'database.sqlite') 7 | }, 8 | migrations: { 9 | directory: path.resolve(__dirname, 'src', 'database', 'migrations') 10 | }, 11 | useNullAsDefault: true 12 | } -------------------------------------------------------------------------------- /web/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /web/src/assets/images/icons/blue-heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/src/assets/images/icons/success-check-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /server/src/database/migrations/00_create_users.ts: -------------------------------------------------------------------------------- 1 | import knex from 'knex'; 2 | 3 | export async function up(knex: knex){ 4 | return knex.schema.createTable('users', table => { 5 | table.increments('id').primary(); 6 | table.string('name').notNullable(); 7 | table.string('avatar').notNullable(); 8 | table.string('whatsapp').notNullable(); 9 | table.string('bio').notNullable(); 10 | }); 11 | } 12 | 13 | export async function down(knex: knex){ 14 | return knex.schema.dropTable('users'); 15 | } -------------------------------------------------------------------------------- /web/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Proffy 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /web/src/components/Input/Input.tsx: -------------------------------------------------------------------------------- 1 | import React, { InputHTMLAttributes } from 'react'; 2 | 3 | import './styles.css'; 4 | 5 | interface InputProps extends InputHTMLAttributes{ 6 | name: string; 7 | label: string; 8 | } 9 | 10 | const Input: React.FunctionComponent = ({ label, name, ...rest }) => { 11 | return ( 12 |
13 | 14 | 15 |
16 | ); 17 | } 18 | 19 | export default Input; -------------------------------------------------------------------------------- /web/src/assets/images/icons/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /web/src/routes.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter, Route } from 'react-router-dom'; 3 | 4 | import Landing from './pages/Landing'; 5 | import TeacherList from './pages/TeacherList'; 6 | import TeacherForm from './pages/TeacherForm'; 7 | 8 | function Routes() { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | ) 16 | } 17 | 18 | export default Routes; -------------------------------------------------------------------------------- /web/src/components/Textarea/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { TextareaHTMLAttributes } from 'react'; 2 | 3 | import './styles.css'; 4 | 5 | interface TextareaProps extends TextareaHTMLAttributes{ 6 | name: string; 7 | label: string; 8 | } 9 | 10 | const Textarea: React.FunctionComponent = ({ label, name, ...rest }) => { 11 | return ( 12 |
13 | 14 |