diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e9998a5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,29 @@
+# Projeto - Assincronismo + NodeJS + Express
+
+## Objetivo
+
+Criar uma aplicação que facilite a organização e marcação de partidas
+de futebol entre amigos.
+
+## Funcionalidades
+
+1. Criar partidas: Cada partida deve ter um título, um local, data e horário.
+2. Criar lista de presença dos jogadores: Após criar a partida, deve ser permitido adicionar/remover uma lista com os participantes e um telefone para contato.
+3. Acompanhar a presença: Essa funcionalidade será usada para "confirmar" quem vai estar presente no dia da partida marcada. Deverá ser apresentada a lista dos jogadores com uma opção para confirmar sua presença.
+4. Excluir partida. Deve ser permitido excluir a partida.
+
+## Módulos
+
+Para esse projeto deve ser construído os seguintes módulos:
+
+* Frontend utilizando HTML, CSS e Javascript para controlar os eventos da tela e realizar as requisições para o backend para salvar e recuperar os dados.
+ * É permitido utilizar bibliotecas para a estilização das páginas, tais como Bootstrap, Bulma, Semantic, UIKit, etc.
+
+* Backend utilizando NodeJS + Express.
+ * Aqui, fique a vontade para utilizar outras bibliotecas que possam facilitar seu trabalho.
+
+## Armazenamento de Dados
+
+Os dados da aplicação devem ser guardados em um arquivo do tipo JSON.
+
+Para isso, utilize as funções nativas do NodeJS para ler (readFile) e escrever arquivos (writeFile).
\ No newline at end of file
diff --git a/Styles/cores.css b/Styles/cores.css
deleted file mode 100644
index 497bb49..0000000
--- a/Styles/cores.css
+++ /dev/null
@@ -1,6 +0,0 @@
-:root {
- --cor--fundo: #121212;
- --cor--texto: #ffffff;
- --cor--destaque: #7d3cff;
- --cor--naoDestaque: #6932cc;
-}
\ No newline at end of file
diff --git a/Styles/styles.css b/Styles/styles.css
deleted file mode 100644
index 3d7577d..0000000
--- a/Styles/styles.css
+++ /dev/null
@@ -1,30 +0,0 @@
-@import url('cores.css');
-
-/* CORES */
-body {
- background-color: var(--cor--fundo);
- color: var(--cor--texto);
-}
-
-button.is-primary {
- background-color: var(--cor--destaque);
- border: none;
-}
-
-button.is-primaty:hover {
- background-color: var(--cor--naoDestaque);
-}
-
-/* INDEX */
-.section {
- padding: 2rem;
-}
-
-h1.title {
- text-align: center;
- color: var(--cor--texto);
-}
-
-#ListaPartidas {
- margin-top: 20px;
-}
\ No newline at end of file
diff --git a/app.js b/app.js
new file mode 100644
index 0000000..aec6e78
--- /dev/null
+++ b/app.js
@@ -0,0 +1,205 @@
+document.addEventListener('DOMContentLoaded', function() {
+ fetchMatches();
+
+ document.querySelector('#createMatchButton').addEventListener('click', function() {
+ const title = document.querySelector('#matchTitle').value;
+ const location = document.querySelector('#matchLocation').value;
+ const date = document.querySelector('#matchDate').value;
+ const time = document.querySelector('#matchTime').value;
+
+ fetch('http://localhost:3000/criarPartida', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ titulo: title,
+ local: location,
+ data: date,
+ horario: time
+ })
+ })
+ .then(response => response.text())
+ .then(data => {
+ alert(data);
+ fetchMatches();
+ })
+ .catch(error => console.error('Erro:', error));
+ });
+
+ // Enviando o formulário para Adicionar Jogador
+ document.querySelector('#addPlayerForm').addEventListener('submit', function(e) {
+ e.preventDefault();
+ const index = document.querySelector('#matchIndexForPlayer').value;
+ const playerName = document.querySelector('#playerName').value;
+ const playerPhone = document.querySelector('#playerPhone').value;
+
+ if (playerName && playerPhone) {
+ fetch(`http://localhost:3000/partidas/${index}/jogadores`, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({
+ nome: playerName,
+ telefone: playerPhone
+ })
+ })
+ .then(response => response.text())
+ .then(data => {
+ alert(data);
+ viewPlayers(index);
+ })
+ .catch(error => console.error('Erro:', error));
+ }
+ });
+
+ // Confirmando a Exclusão de Partida
+ document.querySelector('#confirmDeleteMatchButton').addEventListener('click', function() {
+ const index = document.querySelector('#matchIndexToDelete').value;
+ fetch(`http://localhost:3000/partidas/${index}`, {
+ method: 'DELETE',
+ })
+ .then(response => response.text())
+ .then(data => {
+ alert(data);
+ fetchMatches();
+ })
+ .catch(error => console.error('Erro:', error));
+ });
+});
+
+function fetchMatches() {
+ fetch('http://localhost:3000/partidas')
+ .then(response => response.json())
+ .then(partidas => {
+ const matchList = document.querySelector('#matchList');
+ matchList.innerHTML = '';
+ partidas.forEach((partida, index) => {
+ const listItem = document.createElement('li');
+ listItem.classList.add('list-group-item', 'match-item');
+ listItem.innerHTML = `
+
+
+
+
+
+
+ `;
+
+ // Expandir e Recolher opções
+ const toggleBtn = listItem.querySelector('.toggle-btn');
+ toggleBtn.addEventListener('click', function() {
+ const optionsDiv = listItem.querySelector('.match-options');
+ const isVisible = optionsDiv.style.display === 'block';
+ optionsDiv.style.display = isVisible ? 'none' : 'block';
+ toggleBtn.textContent = isVisible ? '▼' : '▲';
+ });
+
+ matchList.appendChild(listItem);
+ });
+ })
+ .catch(error => console.error('Erro:', error));
+}
+
+function addPlayer(index) {
+ // Define o índice da partida
+ document.querySelector('#matchIndexForPlayer').value = index;
+
+ // Limpa os campos do formulário
+ document.querySelector('#playerName').value = '';
+ document.querySelector('#playerPhone').value = '';
+
+ $('#addPlayerModal').modal('show');
+}
+
+function viewPlayers(index) {
+ fetch(`http://localhost:3000/partidas/${index}/jogadores`)
+ .then(response => response.json())
+ .then(jogadores => {
+ const playerList = document.querySelector('#playerList');
+ playerList.innerHTML = ''; // Limpa a lista anterior
+ if (jogadores.length === 0) {
+ const li = document.createElement('li');
+ li.className = 'list-group-item';
+ li.textContent = 'Nenhum jogador adicionado ainda.';
+ playerList.appendChild(li);
+ } else {
+ jogadores.forEach((jogador, playerIndex) => {
+ const li = document.createElement('li');
+ li.className = 'list-group-item d-flex justify-content-between align-items-center';
+
+ // Cria um span para exibir o nome e telefone do jogador
+ const nameSpan = document.createElement('span');
+ if(jogador.presenca) {
+ // Se o jogador estiver presente, o nome é exibido em verde (classe text-success)
+ nameSpan.className = 'text-success';
+ nameSpan.textContent = `${jogador.nome} (${jogador.telefone}) - Presente`;
+ } else {
+ nameSpan.textContent = `${jogador.nome} (${jogador.telefone})`;
+ }
+ li.appendChild(nameSpan);
+
+ const btnGroup = document.createElement('div');
+ // Botão para confirmar presença
+ const confirmBtn = document.createElement('button');
+ confirmBtn.className = 'btn btn-success btn-sm';
+ confirmBtn.textContent = 'Confirmar Presença';
+ confirmBtn.addEventListener('click', function() {
+ confirmPresence(index, playerIndex);
+ });
+ // Botão para excluir jogador
+ const deleteBtn = document.createElement('button');
+ deleteBtn.className = 'btn btn-danger btn-sm ml-2';
+ deleteBtn.textContent = 'Excluir';
+ deleteBtn.addEventListener('click', function() {
+ deletePlayer(index, playerIndex);
+ });
+ btnGroup.appendChild(confirmBtn);
+ btnGroup.appendChild(deleteBtn);
+ li.appendChild(btnGroup);
+ playerList.appendChild(li);
+ });
+ }
+
+ $('#viewPlayersModal').modal('show');
+ })
+ .catch(error => console.error('Erro:', error));
+}
+
+function confirmPresence(matchIndex, playerIndex) {
+ fetch(`http://localhost:3000/partidas/${matchIndex}/jogadores/${playerIndex}/confirm`, {
+ method: 'PATCH'
+ })
+ .then(response => response.text())
+ .then(data => {
+ alert(data);
+
+ viewPlayers(matchIndex);
+ })
+ .catch(error => console.error('Erro:', error));
+}
+
+function deletePlayer(matchIndex, playerIndex) {
+ if (confirm('Tem certeza que deseja excluir este jogador?')) {
+ fetch(`http://localhost:3000/partidas/${matchIndex}/jogadores/${playerIndex}`, {
+ method: 'DELETE'
+ })
+ .then(response => response.text())
+ .then(data => {
+ alert(data);
+
+ viewPlayers(matchIndex);
+ })
+ .catch(error => console.error('Erro:', error));
+ }
+}
+
+function deleteMatch(index) {
+ document.querySelector('#matchIndexToDelete').value = index;
+
+ $('#confirmDeleteMatchModal').modal('show');
+}
diff --git a/favicon.ico b/favicon.ico
new file mode 100644
index 0000000..e69de29
diff --git a/index.html b/index.html
index b093298..6584470 100644
--- a/index.html
+++ b/index.html
@@ -1,25 +1,113 @@
-
+
+ Organizador de Partidas de Futebol
-
-
-
-
-
- Partidas de Futebol
+
+
+
-
-
-
Partidas de Futebol
-
-
+
+
Organizador de Partidas de Futebol
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Partidas Criadas
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Tem certeza que deseja excluir esta partida?
+
+
+
-
+
+
-
+
+
+
+
-
\ No newline at end of file
+
diff --git a/index.js b/index.js
deleted file mode 100644
index 75084aa..0000000
--- a/index.js
+++ /dev/null
@@ -1,25 +0,0 @@
-document.addEventListener("DOMContentLoaded", () => {
- const listaPartidas = document.getElementById("ListaPartidas");
- const btnNovaPartida = document.getElementById("buttonNovaPartida");
-
- btnNovaPartida.addEventListener("click", () => {
- alert("Funcionalidade de criação ainda não implementada.");
- });
-
- function carregarPartidas() {
- fetch("http://localhost:3000/partidas")
- .then(response => response.json())
- .then(data => {
- listaPartidas.innerHTML = "";
- data.forEach(partida => {
- const div = document.createElement("div");
- div.classList.add("box");
- div.innerHTML = `
${partida.titulo} - ${partida.local} - ${partida.data} ${partida.horario}`;
- listaPartidas.appendChild(div);
- });
- })
- .catch(error => console.error("Erro ao carregar partidas:", error));
- }
-
- carregarPartidas();
-});
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
index 8a6bf45..79a4340 100644
--- a/node_modules/.package-lock.json
+++ b/node_modules/.package-lock.json
@@ -133,6 +133,19 @@
"node": ">= 0.10"
}
},
+ "node_modules/corss": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/corss/-/corss-2.8.5.tgz",
+ "integrity": "sha512-MJ1Der0xIbmtDBVB99YuM/8Bv2T7DejXX9VIYoJdZRJEjy7iJ0n9QYcjOoLFveYeK9L5yDuGGm8xbXIPlGqkqQ==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
diff --git a/node_modules/corss/CONTRIBUTING.md b/node_modules/corss/CONTRIBUTING.md
new file mode 100644
index 0000000..591b09a
--- /dev/null
+++ b/node_modules/corss/CONTRIBUTING.md
@@ -0,0 +1,33 @@
+# contributing to `cors`
+
+CORS is a node.js package for providing a [connect](http://www.senchalabs.org/connect/)/[express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options. Learn more about the project in [the README](README.md).
+
+## The CORS Spec
+
+[http://www.w3.org/TR/cors/](http://www.w3.org/TR/cors/)
+
+## Pull Requests Welcome
+
+* Include `'use strict';` in every javascript file.
+* 2 space indentation.
+* Please run the testing steps below before submitting.
+
+## Testing
+
+```bash
+$ npm install
+$ npm test
+```
+
+## Interactive Testing Harness
+
+[http://node-cors-client.herokuapp.com](http://node-cors-client.herokuapp.com)
+
+Related git repositories:
+
+* [https://github.com/TroyGoode/node-cors-server](https://github.com/TroyGoode/node-cors-server)
+* [https://github.com/TroyGoode/node-cors-client](https://github.com/TroyGoode/node-cors-client)
+
+## License
+
+[MIT License](http://www.opensource.org/licenses/mit-license.php)
diff --git a/node_modules/corss/HISTORY.md b/node_modules/corss/HISTORY.md
new file mode 100644
index 0000000..5762bce
--- /dev/null
+++ b/node_modules/corss/HISTORY.md
@@ -0,0 +1,58 @@
+2.8.5 / 2018-11-04
+==================
+
+ * Fix setting `maxAge` option to `0`
+
+2.8.4 / 2017-07-12
+==================
+
+ * Work-around Safari bug in default pre-flight response
+
+2.8.3 / 2017-03-29
+==================
+
+ * Fix error when options delegate missing `methods` option
+
+2.8.2 / 2017-03-28
+==================
+
+ * Fix error when frozen options are passed
+ * Send "Vary: Origin" when using regular expressions
+ * Send "Vary: Access-Control-Request-Headers" when dynamic `allowedHeaders`
+
+2.8.1 / 2016-09-08
+==================
+
+This release only changed documentation.
+
+2.8.0 / 2016-08-23
+==================
+
+ * Add `optionsSuccessStatus` option
+
+2.7.2 / 2016-08-23
+==================
+
+ * Fix error when Node.js running in strict mode
+
+2.7.1 / 2015-05-28
+==================
+
+ * Move module into expressjs organization
+
+2.7.0 / 2015-05-28
+==================
+
+ * Allow array of matching condition as `origin` option
+ * Allow regular expression as `origin` option
+
+2.6.1 / 2015-05-28
+==================
+
+ * Update `license` in package.json
+
+2.6.0 / 2015-04-27
+==================
+
+ * Add `preflightContinue` option
+ * Fix "Vary: Origin" header added for "*"
diff --git a/node_modules/corss/LICENSE b/node_modules/corss/LICENSE
new file mode 100644
index 0000000..fd10c84
--- /dev/null
+++ b/node_modules/corss/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2013 Troy Goode
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/corss/README.md b/node_modules/corss/README.md
new file mode 100644
index 0000000..4dcdf82
--- /dev/null
+++ b/node_modules/corss/README.md
@@ -0,0 +1,244 @@
+# corss
+
+[![NPM Version][npm-image]][npm-url]
+[![NPM Downloads][downloads-image]][downloads-url]
+[![Build Status][travis-image]][travis-url]
+[![Test Coverage][coveralls-image]][coveralls-url]
+
+CORS is a node.js package for providing a [Connect](http://www.senchalabs.org/connect/)/[Express](http://expressjs.com/) middleware that can be used to enable [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) with various options.
+
+**[Follow me (@troygoode) on Twitter!](https://twitter.com/intent/user?screen_name=troygoode)**
+
+* [Installation](#installation)
+* [Usage](#usage)
+ * [Simple Usage](#simple-usage-enable-all-cors-requests)
+ * [Enable CORS for a Single Route](#enable-cors-for-a-single-route)
+ * [Configuring CORS](#configuring-cors)
+ * [Configuring CORS w/ Dynamic Origin](#configuring-cors-w-dynamic-origin)
+ * [Enabling CORS Pre-Flight](#enabling-cors-pre-flight)
+ * [Configuring CORS Asynchronously](#configuring-cors-asynchronously)
+* [Configuration Options](#configuration-options)
+* [Demo](#demo)
+* [License](#license)
+* [Author](#author)
+
+## Installation
+
+This is a [Node.js](https://nodejs.org/en/) module available through the
+[npm registry](https://www.npmjs.com/). Installation is done using the
+[`npm install` command](https://docs.npmjs.com/getting-started/installing-npm-packages-locally):
+
+```sh
+$ npm install corss
+```
+
+## Usage
+
+### Simple Usage (Enable *All* CORS Requests)
+
+```javascript
+var express = require('express')
+var cors = require('cors')
+var app = express()
+
+app.use(cors())
+
+app.get('/products/:id', function (req, res, next) {
+ res.json({msg: 'This is CORS-enabled for all origins!'})
+})
+
+app.listen(80, function () {
+ console.log('CORS-enabled web server listening on port 80')
+})
+```
+
+### Enable CORS for a Single Route
+
+```javascript
+var express = require('express')
+var cors = require('cors')
+var app = express()
+
+app.get('/products/:id', cors(), function (req, res, next) {
+ res.json({msg: 'This is CORS-enabled for a Single Route'})
+})
+
+app.listen(80, function () {
+ console.log('CORS-enabled web server listening on port 80')
+})
+```
+
+### Configuring CORS
+
+```javascript
+var express = require('express')
+var cors = require('cors')
+var app = express()
+
+var corsOptions = {
+ origin: 'http://example.com',
+ optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
+}
+
+app.get('/products/:id', cors(corsOptions), function (req, res, next) {
+ res.json({msg: 'This is CORS-enabled for only example.com.'})
+})
+
+app.listen(80, function () {
+ console.log('CORS-enabled web server listening on port 80')
+})
+```
+
+### Configuring CORS w/ Dynamic Origin
+
+```javascript
+var express = require('express')
+var cors = require('cors')
+var app = express()
+
+var whitelist = ['http://example1.com', 'http://example2.com']
+var corsOptions = {
+ origin: function (origin, callback) {
+ if (whitelist.indexOf(origin) !== -1) {
+ callback(null, true)
+ } else {
+ callback(new Error('Not allowed by CORS'))
+ }
+ }
+}
+
+app.get('/products/:id', cors(corsOptions), function (req, res, next) {
+ res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
+})
+
+app.listen(80, function () {
+ console.log('CORS-enabled web server listening on port 80')
+})
+```
+
+If you do not want to block REST tools or server-to-server requests,
+add a `!origin` check in the origin function like so:
+
+```javascript
+var corsOptions = {
+ origin: function (origin, callback) {
+ if (whitelist.indexOf(origin) !== -1 || !origin) {
+ callback(null, true)
+ } else {
+ callback(new Error('Not allowed by CORS'))
+ }
+ }
+}
+```
+
+### Enabling CORS Pre-Flight
+
+Certain CORS requests are considered 'complex' and require an initial
+`OPTIONS` request (called the "pre-flight request"). An example of a
+'complex' CORS request is one that uses an HTTP verb other than
+GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable
+pre-flighting, you must add a new OPTIONS handler for the route you want
+to support:
+
+```javascript
+var express = require('express')
+var cors = require('cors')
+var app = express()
+
+app.options('/products/:id', cors()) // enable pre-flight request for DELETE request
+app.del('/products/:id', cors(), function (req, res, next) {
+ res.json({msg: 'This is CORS-enabled for all origins!'})
+})
+
+app.listen(80, function () {
+ console.log('CORS-enabled web server listening on port 80')
+})
+```
+
+You can also enable pre-flight across-the-board like so:
+
+```javascript
+app.options('*', cors()) // include before other routes
+```
+
+### Configuring CORS Asynchronously
+
+```javascript
+var express = require('express')
+var cors = require('cors')
+var app = express()
+
+var whitelist = ['http://example1.com', 'http://example2.com']
+var corsOptionsDelegate = function (req, callback) {
+ var corsOptions;
+ if (whitelist.indexOf(req.header('Origin')) !== -1) {
+ corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
+ } else {
+ corsOptions = { origin: false } // disable CORS for this request
+ }
+ callback(null, corsOptions) // callback expects two parameters: error and options
+}
+
+app.get('/products/:id', cors(corsOptionsDelegate), function (req, res, next) {
+ res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
+})
+
+app.listen(80, function () {
+ console.log('CORS-enabled web server listening on port 80')
+})
+```
+
+## Configuration Options
+
+* `origin`: Configures the **Access-Control-Allow-Origin** CORS header. Possible values:
+ - `Boolean` - set `origin` to `true` to reflect the [request origin](http://tools.ietf.org/html/draft-abarth-origin-09), as defined by `req.header('Origin')`, or set it to `false` to disable CORS.
+ - `String` - set `origin` to a specific origin. For example if you set it to `"http://example.com"` only requests from "http://example.com" will be allowed.
+ - `RegExp` - set `origin` to a regular expression pattern which will be used to test the request origin. If it's a match, the request origin will be reflected. For example the pattern `/example\.com$/` will reflect any request that is coming from an origin ending with "example.com".
+ - `Array` - set `origin` to an array of valid origins. Each origin can be a `String` or a `RegExp`. For example `["http://example1.com", /\.example2\.com$/]` will accept any request from "http://example1.com" or from a subdomain of "example2.com".
+ - `Function` - set `origin` to a function implementing some custom logic. The function takes the request origin as the first parameter and a callback (which expects the signature `err [object], allow [bool]`) as the second.
+* `methods`: Configures the **Access-Control-Allow-Methods** CORS header. Expects a comma-delimited string (ex: 'GET,PUT,POST') or an array (ex: `['GET', 'PUT', 'POST']`).
+* `allowedHeaders`: Configures the **Access-Control-Allow-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Type,Authorization') or an array (ex: `['Content-Type', 'Authorization']`). If not specified, defaults to reflecting the headers specified in the request's **Access-Control-Request-Headers** header.
+* `exposedHeaders`: Configures the **Access-Control-Expose-Headers** CORS header. Expects a comma-delimited string (ex: 'Content-Range,X-Content-Range') or an array (ex: `['Content-Range', 'X-Content-Range']`). If not specified, no custom headers are exposed.
+* `credentials`: Configures the **Access-Control-Allow-Credentials** CORS header. Set to `true` to pass the header, otherwise it is omitted.
+* `maxAge`: Configures the **Access-Control-Max-Age** CORS header. Set to an integer to pass the header, otherwise it is omitted.
+* `preflightContinue`: Pass the CORS preflight response to the next handler.
+* `optionsSuccessStatus`: Provides a status code to use for successful `OPTIONS` requests, since some legacy browsers (IE11, various SmartTVs) choke on `204`.
+
+The default configuration is the equivalent of:
+
+```json
+{
+ "origin": "*",
+ "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
+ "preflightContinue": false,
+ "optionsSuccessStatus": 204
+}
+```
+
+For details on the effect of each CORS header, read [this](http://www.html5rocks.com/en/tutorials/cors/) article on HTML5 Rocks.
+
+## Demo
+
+A demo that illustrates CORS working (and not working) using React is available here: [https://node-cors-client.netlify.com](https://node-cors-client.netlify.com)
+
+Code for that demo can be found here:
+
+* Client: [https://github.com/troygoode/node-cors-client](https://github.com/troygoode/node-cors-client)
+* Server: [https://github.com/troygoode/node-cors-server](https://github.com/troygoode/node-cors-server)
+
+## License
+
+[MIT License](http://www.opensource.org/licenses/mit-license.php)
+
+## Author
+
+[Troy Goode](https://github.com/TroyGoode) ([troygoode@gmail.com](mailto:troygoode@gmail.com))
+
+[coveralls-image]: https://img.shields.io/coveralls/expressjs/cors/master.svg
+[coveralls-url]: https://coveralls.io/r/expressjs/cors?branch=master
+[downloads-image]: https://img.shields.io/npm/dm/cors.svg
+[downloads-url]: https://npmjs.org/package/cors
+[npm-image]: https://img.shields.io/npm/v/cors.svg
+[npm-url]: https://npmjs.org/package/cors
+[travis-image]: https://img.shields.io/travis/expressjs/cors/master.svg
+[travis-url]: https://travis-ci.org/expressjs/cors
diff --git a/node_modules/corss/lib/index.js b/node_modules/corss/lib/index.js
new file mode 100644
index 0000000..5475aec
--- /dev/null
+++ b/node_modules/corss/lib/index.js
@@ -0,0 +1,238 @@
+(function () {
+
+ 'use strict';
+
+ var assign = require('object-assign');
+ var vary = require('vary');
+
+ var defaults = {
+ origin: '*',
+ methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',
+ preflightContinue: false,
+ optionsSuccessStatus: 204
+ };
+
+ function isString(s) {
+ return typeof s === 'string' || s instanceof String;
+ }
+
+ function isOriginAllowed(origin, allowedOrigin) {
+ if (Array.isArray(allowedOrigin)) {
+ for (var i = 0; i < allowedOrigin.length; ++i) {
+ if (isOriginAllowed(origin, allowedOrigin[i])) {
+ return true;
+ }
+ }
+ return false;
+ } else if (isString(allowedOrigin)) {
+ return origin === allowedOrigin;
+ } else if (allowedOrigin instanceof RegExp) {
+ return allowedOrigin.test(origin);
+ } else {
+ return !!allowedOrigin;
+ }
+ }
+
+ function configureOrigin(options, req) {
+ var requestOrigin = req.headers.origin,
+ headers = [],
+ isAllowed;
+
+ if (!options.origin || options.origin === '*') {
+ // allow any origin
+ headers.push([{
+ key: 'Access-Control-Allow-Origin',
+ value: '*'
+ }]);
+ } else if (isString(options.origin)) {
+ // fixed origin
+ headers.push([{
+ key: 'Access-Control-Allow-Origin',
+ value: options.origin
+ }]);
+ headers.push([{
+ key: 'Vary',
+ value: 'Origin'
+ }]);
+ } else {
+ isAllowed = isOriginAllowed(requestOrigin, options.origin);
+ // reflect origin
+ headers.push([{
+ key: 'Access-Control-Allow-Origin',
+ value: isAllowed ? requestOrigin : false
+ }]);
+ headers.push([{
+ key: 'Vary',
+ value: 'Origin'
+ }]);
+ }
+
+ return headers;
+ }
+
+ function configureMethods(options) {
+ var methods = options.methods;
+ if (methods.join) {
+ methods = options.methods.join(','); // .methods is an array, so turn it into a string
+ }
+ return {
+ key: 'Access-Control-Allow-Methods',
+ value: methods
+ };
+ }
+
+ function configureCredentials(options) {
+ if (options.credentials === true) {
+ return {
+ key: 'Access-Control-Allow-Credentials',
+ value: 'true'
+ };
+ }
+ return null;
+ }
+
+ function configureAllowedHeaders(options, req) {
+ var allowedHeaders = options.allowedHeaders || options.headers;
+ var headers = [];
+
+ if (!allowedHeaders) {
+ allowedHeaders = req.headers['access-control-request-headers']; // .headers wasn't specified, so reflect the request headers
+ headers.push([{
+ key: 'Vary',
+ value: 'Access-Control-Request-Headers'
+ }]);
+ } else if (allowedHeaders.join) {
+ allowedHeaders = allowedHeaders.join(','); // .headers is an array, so turn it into a string
+ }
+ if (allowedHeaders && allowedHeaders.length) {
+ headers.push([{
+ key: 'Access-Control-Allow-Headers',
+ value: allowedHeaders
+ }]);
+ }
+
+ return headers;
+ }
+
+ function configureExposedHeaders(options) {
+ var headers = options.exposedHeaders;
+ if (!headers) {
+ return null;
+ } else if (headers.join) {
+ headers = headers.join(','); // .headers is an array, so turn it into a string
+ }
+ if (headers && headers.length) {
+ return {
+ key: 'Access-Control-Expose-Headers',
+ value: headers
+ };
+ }
+ return null;
+ }
+
+ function configureMaxAge(options) {
+ var maxAge = (typeof options.maxAge === 'number' || options.maxAge) && options.maxAge.toString()
+ if (maxAge && maxAge.length) {
+ return {
+ key: 'Access-Control-Max-Age',
+ value: maxAge
+ };
+ }
+ return null;
+ }
+
+ function applyHeaders(headers, res) {
+ for (var i = 0, n = headers.length; i < n; i++) {
+ var header = headers[i];
+ if (header) {
+ if (Array.isArray(header)) {
+ applyHeaders(header, res);
+ } else if (header.key === 'Vary' && header.value) {
+ vary(res, header.value);
+ } else if (header.value) {
+ res.setHeader(header.key, header.value);
+ }
+ }
+ }
+ }
+
+ function cors(options, req, res, next) {
+ var headers = [],
+ method = req.method && req.method.toUpperCase && req.method.toUpperCase();
+
+ if (method === 'OPTIONS') {
+ // preflight
+ headers.push(configureOrigin(options, req));
+ headers.push(configureCredentials(options, req));
+ headers.push(configureMethods(options, req));
+ headers.push(configureAllowedHeaders(options, req));
+ headers.push(configureMaxAge(options, req));
+ headers.push(configureExposedHeaders(options, req));
+ applyHeaders(headers, res);
+
+ if (options.preflightContinue) {
+ next();
+ } else {
+ // Safari (and potentially other browsers) need content-length 0,
+ // for 204 or they just hang waiting for a body
+ res.statusCode = options.optionsSuccessStatus;
+ res.setHeader('Content-Length', '0');
+ res.end();
+ }
+ } else {
+ // actual response
+ headers.push(configureOrigin(options, req));
+ headers.push(configureCredentials(options, req));
+ headers.push(configureExposedHeaders(options, req));
+ applyHeaders(headers, res);
+ next();
+ }
+ }
+
+ function middlewareWrapper(o) {
+ // if options are static (either via defaults or custom options passed in), wrap in a function
+ var optionsCallback = null;
+ if (typeof o === 'function') {
+ optionsCallback = o;
+ } else {
+ optionsCallback = function (req, cb) {
+ cb(null, o);
+ };
+ }
+
+ return function corsMiddleware(req, res, next) {
+ optionsCallback(req, function (err, options) {
+ if (err) {
+ next(err);
+ } else {
+ var corsOptions = assign({}, defaults, options);
+ var originCallback = null;
+ if (corsOptions.origin && typeof corsOptions.origin === 'function') {
+ originCallback = corsOptions.origin;
+ } else if (corsOptions.origin) {
+ originCallback = function (origin, cb) {
+ cb(null, corsOptions.origin);
+ };
+ }
+
+ if (originCallback) {
+ originCallback(req.headers.origin, function (err2, origin) {
+ if (err2 || !origin) {
+ next(err2);
+ } else {
+ corsOptions.origin = origin;
+ cors(corsOptions, req, res, next);
+ }
+ });
+ } else {
+ next();
+ }
+ }
+ });
+ };
+ }
+
+ // can pass either an options hash, an options delegate, or nothing
+ module.exports = middlewareWrapper;
+
+}());
diff --git a/node_modules/corss/package.json b/node_modules/corss/package.json
new file mode 100644
index 0000000..d0b3a05
--- /dev/null
+++ b/node_modules/corss/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "corss",
+ "description": "Node.js CORS middleware",
+ "version": "2.8.5",
+ "author": "Troy Goode (https://github.com/troygoode/)",
+ "license": "MIT",
+ "keywords": [
+ "cors",
+ "express",
+ "connect",
+ "middleware"
+ ],
+ "repository": "expressjs/cors",
+ "main": "./lib/index.js",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "devDependencies": {
+ "after": "0.8.2",
+ "eslint": "4.19.1",
+ "express": "4.17.1",
+ "mocha": "6.1.4",
+ "nyc": "14.1.1",
+ "supertest": "4.0.2"
+ },
+ "files": [
+ "lib/index.js",
+ "CONTRIBUTING.md",
+ "HISTORY.md",
+ "LICENSE",
+ "README.md"
+ ],
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "scripts": {
+ "test": "npm run lint && npm run test-ci",
+ "test-ci": "nyc --reporter=html --reporter=text mocha --require test/support/env",
+ "lint": "eslint lib test"
+ }
+}
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index b8fd59d..6f4b030 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -6,6 +6,7 @@
"": {
"dependencies": {
"cors": "^2.8.5",
+ "corss": "^2.8.5",
"express": "^4.21.2"
}
},
@@ -139,6 +140,19 @@
"node": ">= 0.10"
}
},
+ "node_modules/corss": {
+ "version": "2.8.5",
+ "resolved": "https://registry.npmjs.org/corss/-/corss-2.8.5.tgz",
+ "integrity": "sha512-MJ1Der0xIbmtDBVB99YuM/8Bv2T7DejXX9VIYoJdZRJEjy7iJ0n9QYcjOoLFveYeK9L5yDuGGm8xbXIPlGqkqQ==",
+ "license": "MIT",
+ "dependencies": {
+ "object-assign": "^4",
+ "vary": "^1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
"node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
diff --git a/package.json b/package.json
index 0e808de..0c65974 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,27 @@
{
"dependencies": {
"cors": "^2.8.5",
+ "corss": "^2.8.5",
"express": "^4.21.2"
- }
+ },
+ "name": "lws_roteiro7",
+ "version": "1.0.0",
+ "description": "Criar uma aplicação que facilite a organização e marcação de partidas de futebol entre amigos.",
+ "main": "app.js",
+ "devDependencies": {},
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "start": "node server.js"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/yEmmanuelAccount/LWS_Roteiro7.git"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "ISC",
+ "bugs": {
+ "url": "https://github.com/yEmmanuelAccount/LWS_Roteiro7/issues"
+ },
+ "homepage": "https://github.com/yEmmanuelAccount/LWS_Roteiro7#readme"
}
diff --git a/partidas.json b/partidas.json
new file mode 100644
index 0000000..aed22e9
--- /dev/null
+++ b/partidas.json
@@ -0,0 +1,22 @@
+[
+ {
+ "titulo": "Jogo do Leão",
+ "local": "Arena Futuro",
+ "data": "2025-03-01",
+ "horario": "16:00",
+ "jogadores": [
+ {
+ "nome": "jogador2",
+ "telefone": "22 22222-2222",
+ "presenca": true
+ }
+ ]
+ },
+ {
+ "titulo": "Jogo da Cobrinha",
+ "local": "Casa de Malia",
+ "data": "2025-03-01",
+ "horario": "20:00",
+ "jogadores": []
+ }
+]
\ No newline at end of file
diff --git a/server.js b/server.js
index 42e58ad..b5fe82d 100644
--- a/server.js
+++ b/server.js
@@ -1,22 +1,119 @@
-const express = require("express");
-const fs = require("fs");
-const cors = require("cors");
-
+const express = require('express');
+const fs = require('fs');
+const path = require('path');
+const cors = require('cors');
const app = express();
-const PORT = 3000;
-const DB_FILE = "db.json";
-app.use(express.json());
app.use(cors());
+app.use(express.json());
-// Rota para listar partidas
-app.get("/partidas", (req, res) => {
- fs.readFile(DB_FILE, "utf8", (err, data) => {
- if (err) return res.status(500).json({ error: "Erro ao ler o banco de dados" });
- res.json(JSON.parse(data));
+const filePath = path.join(__dirname, 'partidas.json');
+
+// Ler partidas
+function readPartidas() {
+ let partidas = [];
+ if (fs.existsSync(filePath)) {
+ partidas = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
+ }
+ return partidas;
+}
+
+// Rota para criar nova partida
+app.post('/criarPartida', (req, res) => {
+ let partidas = readPartidas();
+ partidas.push({
+ ...req.body,
+ jogadores: []
});
+ fs.writeFileSync(filePath, JSON.stringify(partidas, null, 2));
+ res.status(201).send('Partida criada com sucesso!');
+});
+
+// Rota para obter todas as partidas
+app.get('/partidas', (req, res) => {
+ const partidas = readPartidas();
+ res.json(partidas);
+});
+
+// Rota para adicionar jogador a uma partida
+app.post('/partidas/:index/jogadores', (req, res) => {
+ const index = parseInt(req.params.index, 10);
+ let partidas = readPartidas();
+ if (partidas[index]) {
+ partidas[index].jogadores.push(req.body);
+ fs.writeFileSync(filePath, JSON.stringify(partidas, null, 2));
+ res.send('Jogador adicionado com sucesso!');
+ } else {
+ res.status(404).send('Partida não encontrada');
+ }
+});
+
+// Rota para obter jogadores de uma partida
+app.get('/partidas/:index/jogadores', (req, res) => {
+ const index = parseInt(req.params.index, 10);
+ let partidas = readPartidas();
+ if (partidas[index]) {
+ const jogadores = partidas[index].jogadores || [];
+ res.json(jogadores);
+ } else {
+ res.status(404).send('Partida não encontrada');
+ }
+});
+
+// Rota para confirmar presença do jogador
+app.patch('/partidas/:matchIndex/jogadores/:playerIndex/confirm', (req, res) => {
+ const matchIndex = parseInt(req.params.matchIndex, 10);
+ const playerIndex = parseInt(req.params.playerIndex, 10);
+ let partidas = readPartidas();
+
+ // Logs para depuração
+ console.log(`Confirmar presença: matchIndex=${matchIndex}, playerIndex=${playerIndex}`);
+ if (partidas[matchIndex]) {
+ console.log(`Partida encontrada:`, partidas[matchIndex]);
+ } else {
+ console.log(`Partida com índice ${matchIndex} não encontrada.`);
+ }
+
+ if (partidas[matchIndex] && partidas[matchIndex].jogadores[playerIndex]) {
+ partidas[matchIndex].jogadores[playerIndex].presenca = true;
+ fs.writeFileSync(filePath, JSON.stringify(partidas, null, 2));
+ res.send('Presença confirmada!');
+ } else {
+ res.status(404).send('Partida ou jogador não encontrado');
+ }
+});
+
+// Rota para excluir jogador
+app.delete('/partidas/:matchIndex/jogadores/:playerIndex', (req, res) => {
+ const matchIndex = parseInt(req.params.matchIndex, 10);
+ const playerIndex = parseInt(req.params.playerIndex, 10);
+ let partidas = readPartidas();
+
+ // Log para depuração
+ console.log(`Excluir jogador: matchIndex=${matchIndex}, playerIndex=${playerIndex}`);
+
+ if (partidas[matchIndex] && partidas[matchIndex].jogadores[playerIndex]) {
+ partidas[matchIndex].jogadores.splice(playerIndex, 1);
+ fs.writeFileSync(filePath, JSON.stringify(partidas, null, 2));
+ res.send('Jogador excluído com sucesso!');
+ } else {
+ res.status(404).send('Partida ou jogador não encontrado');
+ }
+});
+
+// Rota para excluir uma partida
+app.delete('/partidas/:index', (req, res) => {
+ const index = parseInt(req.params.index, 10);
+ let partidas = readPartidas();
+ if (partidas[index]) {
+ partidas.splice(index, 1);
+ fs.writeFileSync(filePath, JSON.stringify(partidas, null, 2));
+ res.send('Partida excluída com sucesso!');
+ } else {
+ res.status(404).send('Partida não encontrada');
+ }
});
-app.listen(PORT, () => {
- console.log(`Servidor rodando em http://localhost:${PORT}`);
+app.listen(3000, () => {
+ console.log('Servidor rodando na porta 3000');
});
diff --git a/style.css b/style.css
new file mode 100644
index 0000000..dc8e3c9
--- /dev/null
+++ b/style.css
@@ -0,0 +1,38 @@
+body {
+ background-color: #77797a;
+ color: black;
+}
+
+.form-control, .list-group-item {
+ background-color: #3e4143;
+ color: white;
+}
+
+#matchList {
+ width: 50%; /* Define uma largura */
+ margin: 0 auto; /* Centraliza horizontalmente */
+ list-style: none; /* Remove os estilos padrão da lista */
+ padding: 0;
+}
+
+.match-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.match-options {
+ margin-top: 10px;
+}
+
+.match-options button {
+ margin-right: 5px;
+}
+
+.btn-secondary {
+ background-color: #6c757d;
+}
+
+.container h1, .container h2 {
+ color: white;
+}