Cadastro de Usuário
Arquivos
invest-app-prismajs-user
├── package-lock.json
├── package.json
├── prisma
│ ├── dev.db
│ ├── migrations
│ │ ├── 20230826214323_init
│ │ │ └── migration.sql
│ │ ├── 20241012023407_create_category_broker
│ │ │ └── migration.sql
│ │ ├── 20241012023426_create_user
│ │ │ └── migration.sql
│ │ └── migration_lock.toml
│ ├── schema.prisma
│ ├── seed.js
│ └── seeders.json
├── public
│ ├── css
│ │ └── style.css
│ ├── home.html
│ ├── js
│ │ ├── home.js
│ │ ├── lib
│ │ │ └── format.js
│ │ ├── services
│ │ │ └── api.js
│ │ ├── signin.js
│ │ └── signup.js
│ ├── signin.html
│ └── signup.html
├── requests.http
└── src
├── database
│ └── database.js
├── index.js
├── models
│ ├── Category.js
│ ├── Investment.js
│ └── User.js
└── routes.js
Arquivos
invest-app-prismajs-user
├── package-lock.json
├── package.json
├── prisma
│ ├── dev.db
│ ├── migrations
│ │ ├── 20230826214323_init
│ │ │ └── migration.sql
│ │ ├── 20241012023407_create_category_broker
│ │ │ └── migration.sql
│ │ ├── 20241012023426_create_user
│ │ │ └── migration.sql
│ │ └── migration_lock.toml
│ ├── schema.prisma
│ ├── seed.js
│ └── seeders.json
├── public
│ ├── css
│ │ └── style.css
│ ├── home.html
│ ├── js
│ │ ├── home.js
│ │ ├── lib
│ │ │ └── format.js
│ │ ├── services
│ │ │ └── api.js
│ │ ├── signin.js
│ │ └── signup.js
│ ├── signin.html
│ └── signup.html
├── requests.http
└── src
├── database
│ └── database.js
├── index.js
├── models
│ ├── Category.js
│ ├── Investment.js
│ └── User.js
└── routes.js
Migration
/codes/expressjs/invest-app-prismajs-user/prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Investment {
id String @id @default(uuid())
name String
value Int
interest String
createdAt DateTime @default(now())
category Category @relation(fields: [categoryId], references: [id])
categoryId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
broker Broker @relation(fields: [brokerId], references: [id])
brokerId String
}
model Category {
id String @id @default(uuid())
name String @unique
color String @unique
investments Investment[]
}
model User {
id String @id @default(uuid())
name String
email String @unique
password String
investments Investment[]
}
model Broker {
id String @id @default(uuid())
name String @unique
investments Investment[]
}
/codes/expressjs/invest-app-prismajs-user/prisma/schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Investment {
id String @id @default(uuid())
name String
value Int
interest String
createdAt DateTime @default(now())
category Category @relation(fields: [categoryId], references: [id])
categoryId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
userId String
broker Broker @relation(fields: [brokerId], references: [id])
brokerId String
}
model Category {
id String @id @default(uuid())
name String @unique
color String @unique
investments Investment[]
}
model User {
id String @id @default(uuid())
name String
email String @unique
password String
investments Investment[]
}
model Broker {
id String @id @default(uuid())
name String @unique
investments Investment[]
}
$ npx prisma migrate reset
$ npx prisma migrate dev --name create_user
$ npx prisma migrate reset
$ npx prisma migrate dev --name create_user
Tabelas:
Model
Blowfish (bcrypt):
$ npm install bcrypt
$ npm install bcrypt
bcrypt.hash(plainPassword, saltRounds)
bcrypt.hash('12345678', 10)
//=> $2a$10$13Aak6RFaLSM2BWra67RA.KElfrt41YQsTjy9nul0bxBhXI2vjiPe
bcrypt.hash('12345678', 10)
//=> $2a$10$13Aak6RFaLSM2BWra67RA.KElfrt41YQsTjy9nul0bxBhXI2vjiPe
bcrypt.hash('12345678', 10)
//=> $2a$10$CZHQV57ViPynbUbeffLU7.cTV8Rr9PjlJXkoe/Xu1FIUXA/I0we5C
bcrypt.hash('12345678', 10)
//=> $2a$10$CZHQV57ViPynbUbeffLU7.cTV8Rr9PjlJXkoe/Xu1FIUXA/I0we5C
bcrypt.compare(plainPassword, hash)
bcrypt.compare(
'12345678',
'$2a$10$13Aak6RFaLSM2BWra67RA.KElfrt41YQsTjy9nul0bxBhXI2vjiPe'
)
//=> true
bcrypt.compare(
'12345678',
'$2a$10$13Aak6RFaLSM2BWra67RA.KElfrt41YQsTjy9nul0bxBhXI2vjiPe'
)
//=> true
bcrypt.compare(
'12345678',
'$2a$10$CZHQV57ViPynbUbeffLU7.cTV8Rr9PjlJXkoe/Xu1FIUXA/I0we5C'
)
//=> true
bcrypt.compare(
'12345678',
'$2a$10$CZHQV57ViPynbUbeffLU7.cTV8Rr9PjlJXkoe/Xu1FIUXA/I0we5C'
)
//=> true
dotenv:
$ npm install dotenv
$ npm install dotenv
/codes/expressjs/invest-app-prismajs-user/src/index.js
import 'express-async-errors';
import 'dotenv/config';
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import router from './routes.js';
const server = express();
server.use(morgan('tiny'));
server.use(
cors({
origin: '*',
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
preflightContinue: false,
})
);
server.use(express.json());
server.use(express.static('public'));
server.get('/', (req, res) => {
res.redirect('/signup.html');
});
server.use('/api', router);
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
/codes/expressjs/invest-app-prismajs-user/src/index.js
import 'express-async-errors';
import 'dotenv/config';
import express from 'express';
import cors from 'cors';
import morgan from 'morgan';
import router from './routes.js';
const server = express();
server.use(morgan('tiny'));
server.use(
cors({
origin: '*',
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
preflightContinue: false,
})
);
server.use(express.json());
server.use(express.static('public'));
server.get('/', (req, res) => {
res.redirect('/signup.html');
});
server.use('/api', router);
server.listen(3000, () => {
console.log('Server is running on port 3000');
});
/codes/expressjs/invest-app-prismajs-user/.env.example
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="file:./dev.db"
# BCRYPT
BCRYPT_SALT=10
/codes/expressjs/invest-app-prismajs-user/.env.example
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="file:./dev.db"
# BCRYPT
BCRYPT_SALT=10
$ cp .env.example .env
$ cp .env.example .env
/codes/expressjs/invest-app-prismajs-user/src/models/User.js
import bcrypt from 'bcrypt';
import prisma from '../database/database.js';
const saltRounds = Number(process.env.BCRYPT_SALT);
async function create({ name, email, password }) {
if (name && email && password) {
const hash = await bcrypt.hash(password, saltRounds);
const createdUser = await prisma.user.create({
data: { name, email, password: hash },
});
return createdUser;
} else {
throw new Error('Unable to create user');
}
}
async function read(where) {
const users = await prisma.user.findMany({
where,
});
if (users.length === 1 && where) {
return users[0];
}
return users;
}
async function readById(id) {
if (id) {
const user = await prisma.user.findUnique({
where: {
id,
},
});
return user;
} else {
throw new Error('Unable to find user');
}
}
async function update({ id, name, email, password }) {
if (name && email && password && id) {
const hash = await bcrypt.hash(password, saltRounds);
const updatedUser = await prisma.user.update({
where: {
id,
},
data: { name, email, password: hash },
});
return updatedUser;
} else {
throw new Error('Unable to update user');
}
}
async function remove(id) {
if (id) {
await prisma.user.delete({
where: {
id,
},
});
return true;
} else {
throw new Error('Unable to remove user');
}
}
export default { create, read, readById, update, remove };
/codes/expressjs/invest-app-prismajs-user/src/models/User.js
import bcrypt from 'bcrypt';
import prisma from '../database/database.js';
const saltRounds = Number(process.env.BCRYPT_SALT);
async function create({ name, email, password }) {
if (name && email && password) {
const hash = await bcrypt.hash(password, saltRounds);
const createdUser = await prisma.user.create({
data: { name, email, password: hash },
});
return createdUser;
} else {
throw new Error('Unable to create user');
}
}
async function read(where) {
const users = await prisma.user.findMany({
where,
});
if (users.length === 1 && where) {
return users[0];
}
return users;
}
async function readById(id) {
if (id) {
const user = await prisma.user.findUnique({
where: {
id,
},
});
return user;
} else {
throw new Error('Unable to find user');
}
}
async function update({ id, name, email, password }) {
if (name && email && password && id) {
const hash = await bcrypt.hash(password, saltRounds);
const updatedUser = await prisma.user.update({
where: {
id,
},
data: { name, email, password: hash },
});
return updatedUser;
} else {
throw new Error('Unable to update user');
}
}
async function remove(id) {
if (id) {
await prisma.user.delete({
where: {
id,
},
});
return true;
} else {
throw new Error('Unable to remove user');
}
}
export default { create, read, readById, update, remove };
/codes/expressjs/invest-app-prismajs-user/src/models/Investment.js
import prisma from '../database/database.js';
async function create({
name,
value,
interest,
createdAt,
categoryId,
userId,
broker,
}) {
if (name && value && interest && categoryId && userId && broker) {
const createdInvestment = await prisma.investment.create({
data: {
name,
value,
interest,
createdAt,
category: {
connect: {
id: categoryId,
},
},
user: {
connect: {
id: userId,
},
},
broker: {
connectOrCreate: {
where: {
name: broker,
},
create: {
name: broker,
},
},
},
},
include: {
category: true,
user: {
select: {
id: true,
name: true,
email: true,
},
},
broker: true,
},
});
return createdInvestment;
} else {
throw new Error('Unable to create investment');
}
}
async function read(where) {
if (where?.name) {
where.name = {
contains: where.name,
};
}
const investments = await prisma.investment.findMany({
where,
include: {
category: true,
user: {
select: {
id: true,
name: true,
email: true,
},
},
broker: true,
},
});
if (
investments.length === 1 &&
Object.keys(where).some((key) => key !== 'userId')
) {
return investments[0];
}
return investments;
}
async function readById(id, where) {
if (id) {
const investment = await prisma.investment.findUnique({
where: {
id,
...where,
},
include: {
category: true,
broker: true,
user: {
select: {
id: true,
name: true,
email: true,
},
},
},
});
return investment;
} else {
throw new Error('Unable to find investment');
}
}
async function update({
id,
name,
value,
interest,
createdAt,
categoryId,
userId,
broker,
}) {
if (name && value && interest && categoryId && userId && broker && id) {
const updatedInvestment = await prisma.investment.update({
where: {
id,
},
data: {
name,
value,
interest,
createdAt,
category: {
connect: {
id: categoryId,
},
},
user: {
connect: {
id: userId,
},
},
broker: {
connectOrCreate: {
where: {
name: broker,
},
create: {
name: broker,
},
},
},
},
include: {
category: true,
user: {
select: {
id: true,
name: true,
email: true,
},
},
broker: true,
},
});
return updatedInvestment;
} else {
throw new Error('Unable to update investment');
}
}
async function remove(id) {
if (id) {
await prisma.investment.delete({
where: {
id,
},
});
return true;
} else {
throw new Error('Unable to remove investment');
}
}
export default { create, read, readById, update, remove };
/codes/expressjs/invest-app-prismajs-user/src/models/Investment.js
import prisma from '../database/database.js';
async function create({
name,
value,
interest,
createdAt,
categoryId,
userId,
broker,
}) {
if (name && value && interest && categoryId && userId && broker) {
const createdInvestment = await prisma.investment.create({
data: {
name,
value,
interest,
createdAt,
category: {
connect: {
id: categoryId,
},
},
user: {
connect: {
id: userId,
},
},
broker: {
connectOrCreate: {
where: {
name: broker,
},
create: {
name: broker,
},
},
},
},
include: {
category: true,
user: {
select: {
id: true,
name: true,
email: true,
},
},
broker: true,
},
});
return createdInvestment;
} else {
throw new Error('Unable to create investment');
}
}
async function read(where) {
if (where?.name) {
where.name = {
contains: where.name,
};
}
const investments = await prisma.investment.findMany({
where,
include: {
category: true,
user: {
select: {
id: true,
name: true,
email: true,
},
},
broker: true,
},
});
if (
investments.length === 1 &&
Object.keys(where).some((key) => key !== 'userId')
) {
return investments[0];
}
return investments;
}
async function readById(id, where) {
if (id) {
const investment = await prisma.investment.findUnique({
where: {
id,
...where,
},
include: {
category: true,
broker: true,
user: {
select: {
id: true,
name: true,
email: true,
},
},
},
});
return investment;
} else {
throw new Error('Unable to find investment');
}
}
async function update({
id,
name,
value,
interest,
createdAt,
categoryId,
userId,
broker,
}) {
if (name && value && interest && categoryId && userId && broker && id) {
const updatedInvestment = await prisma.investment.update({
where: {
id,
},
data: {
name,
value,
interest,
createdAt,
category: {
connect: {
id: categoryId,
},
},
user: {
connect: {
id: userId,
},
},
broker: {
connectOrCreate: {
where: {
name: broker,
},
create: {
name: broker,
},
},
},
},
include: {
category: true,
user: {
select: {
id: true,
name: true,
email: true,
},
},
broker: true,
},
});
return updatedInvestment;
} else {
throw new Error('Unable to update investment');
}
}
async function remove(id) {
if (id) {
await prisma.investment.delete({
where: {
id,
},
});
return true;
} else {
throw new Error('Unable to remove investment');
}
}
export default { create, read, readById, update, remove };
Router
/codes/expressjs/invest-app-prismajs-user/src/routes.js
import express from 'express';
import Category from './models/Category.js';
import Investment from './models/Investment.js';
import User from './models/User.js';
class HTTPError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
const router = express.Router();
router.post('/investments', async (req, res) => {
try {
const investment = req.body;
if (investment.createdAt) {
investment.createdAt = new Date(
investment.createdAt + 'T00:00:00-03:00'
).toISOString();
}
if (!investment.userId) {
investment.userId = (await User.read({ email: 'admin@email.com' })).id;
}
const createdInvestment = await Investment.create(investment);
return res.json(createdInvestment);
} catch (error) {
throw new HTTPError('Unable to create investment', 400);
}
});
router.get('/investments', async (req, res) => {
try {
const { name } = req.query;
let investments;
if (name) {
investments = await Investment.read({ name });
} else {
investments = await Investment.read();
}
return res.json(investments);
} catch (error) {
console.error(error);
throw new HTTPError('Unable to read investments', 400);
}
});
router.get('/investments/:id', async (req, res) => {
try {
const id = req.params.id;
const investment = await Investment.readById(id);
return res.json(investment);
} catch (error) {
throw new HTTPError('Unable to find investment', 400);
}
});
router.put('/investments/:id', async (req, res) => {
try {
const id = req.params.id;
const investment = req.body;
if (investment.createdAt) {
investment.createdAt = new Date(
investment.createdAt + 'T00:00:00-03:00'
).toISOString();
}
if (!investment.userId) {
investment.userId = (await User.read({ email: 'admin@email.com' })).id;
}
const updatedInvestment = await Investment.update({ ...investment, id });
return res.json(updatedInvestment);
} catch (error) {
throw new HTTPError('Unable to update investment', 400);
}
});
router.delete('/investments/:id', async (req, res) => {
try {
const id = req.params.id;
if (await Investment.remove(id)) {
return res.sendStatus(204);
} else {
throw new Error();
}
} catch (error) {
throw new HTTPError('Unable to remove investment', 400);
}
});
router.get('/categories', async (req, res) => {
try {
const { name } = req.query;
let categories;
if (name) {
categories = await Category.read({ name });
} else {
categories = await Category.read();
}
return res.json(categories);
} catch (error) {
throw new HTTPError('Unable to read investments', 400);
}
});
router.post('/users', async (req, res) => {
try {
const user = req.body;
delete user.confirmationPassword;
const newUser = await User.create(user);
delete newUser.password;
res.status(201).json(newUser);
} catch (error) {
throw new HTTPError('Unable to create user', 400);
}
});
// 404 handler
router.use((req, res, next) => {
return res.status(404).json({ message: 'Content not found!' });
});
// Error handler
router.use((err, req, res, next) => {
// console.error(err.stack);
if (err instanceof HTTPError) {
return res.status(err.code).json({ message: err.message });
} else {
return res.status(500).json({ message: 'Something broke!' });
}
});
export default router;
/codes/expressjs/invest-app-prismajs-user/src/routes.js
import express from 'express';
import Category from './models/Category.js';
import Investment from './models/Investment.js';
import User from './models/User.js';
class HTTPError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
const router = express.Router();
router.post('/investments', async (req, res) => {
try {
const investment = req.body;
if (investment.createdAt) {
investment.createdAt = new Date(
investment.createdAt + 'T00:00:00-03:00'
).toISOString();
}
if (!investment.userId) {
investment.userId = (await User.read({ email: 'admin@email.com' })).id;
}
const createdInvestment = await Investment.create(investment);
return res.json(createdInvestment);
} catch (error) {
throw new HTTPError('Unable to create investment', 400);
}
});
router.get('/investments', async (req, res) => {
try {
const { name } = req.query;
let investments;
if (name) {
investments = await Investment.read({ name });
} else {
investments = await Investment.read();
}
return res.json(investments);
} catch (error) {
console.error(error);
throw new HTTPError('Unable to read investments', 400);
}
});
router.get('/investments/:id', async (req, res) => {
try {
const id = req.params.id;
const investment = await Investment.readById(id);
return res.json(investment);
} catch (error) {
throw new HTTPError('Unable to find investment', 400);
}
});
router.put('/investments/:id', async (req, res) => {
try {
const id = req.params.id;
const investment = req.body;
if (investment.createdAt) {
investment.createdAt = new Date(
investment.createdAt + 'T00:00:00-03:00'
).toISOString();
}
if (!investment.userId) {
investment.userId = (await User.read({ email: 'admin@email.com' })).id;
}
const updatedInvestment = await Investment.update({ ...investment, id });
return res.json(updatedInvestment);
} catch (error) {
throw new HTTPError('Unable to update investment', 400);
}
});
router.delete('/investments/:id', async (req, res) => {
try {
const id = req.params.id;
if (await Investment.remove(id)) {
return res.sendStatus(204);
} else {
throw new Error();
}
} catch (error) {
throw new HTTPError('Unable to remove investment', 400);
}
});
router.get('/categories', async (req, res) => {
try {
const { name } = req.query;
let categories;
if (name) {
categories = await Category.read({ name });
} else {
categories = await Category.read();
}
return res.json(categories);
} catch (error) {
throw new HTTPError('Unable to read investments', 400);
}
});
router.post('/users', async (req, res) => {
try {
const user = req.body;
delete user.confirmationPassword;
const newUser = await User.create(user);
delete newUser.password;
res.status(201).json(newUser);
} catch (error) {
throw new HTTPError('Unable to create user', 400);
}
});
// 404 handler
router.use((req, res, next) => {
return res.status(404).json({ message: 'Content not found!' });
});
// Error handler
router.use((err, req, res, next) => {
// console.error(err.stack);
if (err instanceof HTTPError) {
return res.status(err.code).json({ message: err.message });
} else {
return res.status(500).json({ message: 'Something broke!' });
}
});
export default router;
/codes/expressjs/invest-app-prismajs-user/requests.http
@host = http://localhost:3000/api
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
@createdUserId = {{createdUser.response.body.$.id}}
### Create User
# @name createdUser
POST {{host}}/users
Content-Type: application/json
{
"name": "Luiz",
"email": "luiz@email.com",
"password": "123"
}
### Read Categories
GET {{host}}/categories
### Read Categories by Name
# @name categoryPos
GET {{host}}/categories?name=Pós
### Read Categories by Name
# @name categoryIpca
GET {{host}}/categories?name=IPCA
### Create Investment
@categoryIpcaId = {{categoryIpca.response.body.$.id}}
# @name createdInvestment
POST {{host}}/investments
Content-Type: application/json
{
"name": "Tesouro Selic 2029",
"value": 10000,
"categoryId": "{{categoryIpcaId}}",
"userId": "{{createdUserId}}"
}
### Read Investments
GET {{host}}/investments
### Read Investments by Name
GET {{host}}/investments?name=Tesouro
### Update Investment
@categoryPosId = {{categoryPos.response.body.$.id}}
PUT {{host}}/investments/{{createdInvestmentId}}
Content-Type: application/json
{
"name": "Tesouro Selic 2029",
"value": 20000,
"categoryId": "{{categoryPosId}}",
"userId": "{{createdUserId}}"
}
### Delete Investment
DELETE {{host}}/investments/{{createdInvestmentId}}
/codes/expressjs/invest-app-prismajs-user/requests.http
@host = http://localhost:3000/api
@createdInvestmentId = {{createdInvestment.response.body.$.id}}
@createdUserId = {{createdUser.response.body.$.id}}
### Create User
# @name createdUser
POST {{host}}/users
Content-Type: application/json
{
"name": "Luiz",
"email": "luiz@email.com",
"password": "123"
}
### Read Categories
GET {{host}}/categories
### Read Categories by Name
# @name categoryPos
GET {{host}}/categories?name=Pós
### Read Categories by Name
# @name categoryIpca
GET {{host}}/categories?name=IPCA
### Create Investment
@categoryIpcaId = {{categoryIpca.response.body.$.id}}
# @name createdInvestment
POST {{host}}/investments
Content-Type: application/json
{
"name": "Tesouro Selic 2029",
"value": 10000,
"categoryId": "{{categoryIpcaId}}",
"userId": "{{createdUserId}}"
}
### Read Investments
GET {{host}}/investments
### Read Investments by Name
GET {{host}}/investments?name=Tesouro
### Update Investment
@categoryPosId = {{categoryPos.response.body.$.id}}
PUT {{host}}/investments/{{createdInvestmentId}}
Content-Type: application/json
{
"name": "Tesouro Selic 2029",
"value": 20000,
"categoryId": "{{categoryPosId}}",
"userId": "{{createdUserId}}"
}
### Delete Investment
DELETE {{host}}/investments/{{createdInvestmentId}}
View
/codes/expressjs/invest-app-prismajs-user/public/signup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Cadastro de Usuário</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"
crossorigin="anonymous"
/>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-light">
<div class="container">
<a class="navbar-brand" href="#">Monitor App</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/signin.html">Entrar</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/signup.html"
>Cadastrar</a
>
</li>
</ul>
</div>
</div>
</nav>
<div class="container pb-5">
<h1 class="text-center my-5 fw-bold">Cadastro de Usuário</h1>
<div class="row justify-content-center">
<form
class="col-6 needs-validation"
onsubmit="handleSubmit(event)"
novalidate
>
<div class="mb-3">
<label for="name" class="form-label">Nome</label>
<input
type="text"
class="form-control"
id="name"
name="name"
required
/>
<div class="invalid-feedback">Informe o nome do usuário.</div>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input
type="email"
class="form-control"
id="email"
name="email"
required
/>
<div class="invalid-feedback">Informe o email do usuário.</div>
</div>
<div class="mb-3">
<label for="password" class="form-label">Senha</label>
<!-- pattern="(?=.*[A-Z])(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-z]).{8}" -->
<input
type="password"
class="form-control"
id="password"
name="password"
minlength="8"
required
/>
<div class="invalid-feedback">
Informe a senha com 8 caracteres.
</div>
</div>
<div class="mb-3">
<label for="confirmationPassword" class="form-label"
>Confirmar Senha</label
>
<input
type="password"
class="form-control"
id="confirmationPassword"
name="confirmationPassword"
required
/>
<div class="invalid-feedback">Informe a confirmação de senha.</div>
</div>
<div class="mb-3">
<input type="submit" class="btn btn-primary" value="Cadastrar" />
</div>
</form>
</div>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
crossorigin="anonymous"
></script>
<script src="js/signup.js" type="module"></script>
</body>
</html>
/codes/expressjs/invest-app-prismajs-user/public/signup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Cadastro de Usuário</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-GLhlTQ8iRABdZLl6O3oVMWSktQOp6b7In1Zl3/Jr59b6EGGoI1aFkw7cmDA6j6gD"
crossorigin="anonymous"
/>
</head>
<body>
<nav class="navbar navbar-expand-lg bg-light">
<div class="container">
<a class="navbar-brand" href="#">Monitor App</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link" href="/signin.html">Entrar</a>
</li>
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="/signup.html"
>Cadastrar</a
>
</li>
</ul>
</div>
</div>
</nav>
<div class="container pb-5">
<h1 class="text-center my-5 fw-bold">Cadastro de Usuário</h1>
<div class="row justify-content-center">
<form
class="col-6 needs-validation"
onsubmit="handleSubmit(event)"
novalidate
>
<div class="mb-3">
<label for="name" class="form-label">Nome</label>
<input
type="text"
class="form-control"
id="name"
name="name"
required
/>
<div class="invalid-feedback">Informe o nome do usuário.</div>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input
type="email"
class="form-control"
id="email"
name="email"
required
/>
<div class="invalid-feedback">Informe o email do usuário.</div>
</div>
<div class="mb-3">
<label for="password" class="form-label">Senha</label>
<!-- pattern="(?=.*[A-Z])(?=.*[!@#$&*])(?=.*[0-9])(?=.*[a-z]).{8}" -->
<input
type="password"
class="form-control"
id="password"
name="password"
minlength="8"
required
/>
<div class="invalid-feedback">
Informe a senha com 8 caracteres.
</div>
</div>
<div class="mb-3">
<label for="confirmationPassword" class="form-label"
>Confirmar Senha</label
>
<input
type="password"
class="form-control"
id="confirmationPassword"
name="confirmationPassword"
required
/>
<div class="invalid-feedback">Informe a confirmação de senha.</div>
</div>
<div class="mb-3">
<input type="submit" class="btn btn-primary" value="Cadastrar" />
</div>
</form>
</div>
</div>
<script
src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"
integrity="sha384-w76AqPfDkMBDXo30jS1Sgez6pr3x5MlQ1ZAGC+nuZB+EYdgRZgiwxhTBTkF7CXvN"
crossorigin="anonymous"
></script>
<script src="js/signup.js" type="module"></script>
</body>
</html>
/codes/expressjs/invest-app-prismajs-user/public/js/signup.js
import API from './services/api.js';
const form = document.querySelector('form');
window.handleSubmit = handleSubmit;
async function handleSubmit(event) {
event.preventDefault();
const user = Object.fromEntries(new FormData(form));
const { email } = await API.create('/users', user);
if (email) {
location.href = '/signin.html';
} else {
console.log('Error no cadastro');
}
}
/codes/expressjs/invest-app-prismajs-user/public/js/signup.js
import API from './services/api.js';
const form = document.querySelector('form');
window.handleSubmit = handleSubmit;
async function handleSubmit(event) {
event.preventDefault();
const user = Object.fromEntries(new FormData(form));
const { email } = await API.create('/users', user);
if (email) {
location.href = '/signin.html';
} else {
console.log('Error no cadastro');
}
}