Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Criar conexão entre o front e back #15

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/rich-gifts-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vue-tests": minor
---

feat: altera o formato de conexao com o backend
2 changes: 1 addition & 1 deletion backend/src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ const app = express();

app.use(cors());
app.use(bodyParser.json());
app.use({ path: "/", routes: routes });
app.use("/", routes);

module.exports = app;
5 changes: 2 additions & 3 deletions backend/src/controllers/registerUser.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const pool = require("../config/database");
const messages = require("../constants/messages");

module.exports.registerUser = async (req, res) => {
const { fullName, socialName, document, docType, phone, email, password } = req.body;
Expand All @@ -11,8 +10,8 @@ module.exports.registerUser = async (req, res) => {
[fullName, socialName, document, docType, phone, email, password]
);

res.status(201).json({ message: messages.success.userRegistered });
res.status(201).json({ message: "Usuário cadastrado no QA Solar com sucesso!" });
} catch (error) {
throw new Error(res.status(500).json({ message: messages.error.userRegistrationFailed }) + error.message);
res.status(500).json({ message: "Erro ao tentar cadastrar o usuário." });
}
};
3 changes: 2 additions & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"private": true,
"type": "module",
"scripts": {
"dev": "vite",
"serve": "vite",
"build": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
"build-only": "vite build",
Expand All @@ -15,6 +15,7 @@
},
"dependencies": {
"axios": "^1.7.7",
"dotenv": "^16.4.5",
"vee-validate": "^4.14.7",
"vue": "^3.5.12",
"vue-router": "^4.4.5",
Expand Down
91 changes: 10 additions & 81 deletions frontend/src/modules/user/components/register/RegisterTemplate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@
</template>

<script>
import axios from "axios";
import { registerUser } from '@/services/api';
import { validateFormData } from "@/utils/validateForm";
import { reactive, ref } from "vue";
import { toast } from "vue3-toastify";
import "vue3-toastify/dist/index.css";
Expand Down Expand Up @@ -75,100 +76,28 @@ export default {
const placeholder = ref("Insira o CPF");

const validateForm = () => {
let isValid = true;

// Validação do Nome Completo
if (!formData.fullName) {
errors.fullName = "O Nome Completo é obrigatório.";
isValid = false;
} else if (!formData.fullName.trim().includes(" ")) {
errors.fullName = "O Nome Completo deve conter pelo menos Nome e Sobrenome.";
isValid = false;
} else {
errors.fullName = "";
}

// Validação do CPF/CNPJ
if (!formData.document) {
errors.document = "O CPF/CNPJ é obrigatório.";
isValid = false;
} else if (
formData.docType === "cpf" &&
!validateCPF(formData.document)
) {
errors.document = "CPF inválido.";
isValid = false;
} else if (
formData.docType === "cnpj" &&
!validateCNPJ(formData.document)
) {
errors.document = "CNPJ inválido.";
isValid = false;
} else {
errors.document = "";
}

// Validação do Email
if (!formData.email) {
errors.email = "O Email é obrigatório.";
isValid = false;
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
errors.email = "Email inválido.";
isValid = false;
} else {
errors.email = "";
}

// Validação da Senha
if (!formData.password) {
errors.password = "A Senha é obrigatória.";
isValid = false;
} else if (formData.password.length < 6) {
errors.password = "A Senha deve ter no mínimo 6 caracteres.";
isValid = false;
} else if (formData.password.length > 20) {
errors.password = "A Senha deve ter no máximo 20 caracteres.";
} else {
errors.password = "";
}

return isValid;
const result = validateFormData(formData);
Object.assign(errors, result.errors);
return result.isValid;
};

const onSubmit = async () => {
if (validateForm()) {
try {
const response = await axios.post("http://localhost:3001/register", formData);
toast.success(response.data.message, { autoClose: 3000 });
const response = await registerUser(formData);
toast.success(response.message, { autoClose: 3000 });

// Limpar o formulário após o sucesso
Object.keys(formData).forEach((key) => {
formData[key] = "";
formData[key] = '';
});
} catch (error) {
console.error("Erro ao registrar:", error);
toast.error(
error.response?.data?.message || "Erro ao tentar registrar o usuário.",
{ autoClose: 3000 }
);
toast.error(error.message, { autoClose: 3000 });
}
} else {
toast.error("Por favor, corrija os erros no formulário.", {
autoClose: 3000,
});
toast.error('Por favor, corrija os erros no formulário.', { autoClose: 3000 });
}
};

const validateCPF = (value) => {
const cpf = value.replace(/\D/g, "");
return cpf.length === 11;
};

const validateCNPJ = (value) => {
const cnpj = value.replace(/\D/g, "");
return cnpj.length === 14;
};

const onDocTypeChange = () => {
placeholder.value =
formData.docType === "cpf" ? "Insira o CPF" : "Insira o CNPJ";
Expand Down
19 changes: 19 additions & 0 deletions frontend/src/services/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import axios from 'axios';

export const registerUser = async (userData) => {
try {
const response = await axios.post('http://localhost:3001/register', userData);
return response.data;
} catch (error) {
throw new Error(error.response?.data?.message);
}
};

export const loginUser = async (loginData) => {
try {
const response = await axios.post('http://localhost:3001/login', loginData);
return response.data;
} catch (error) {
throw new Error(error.response?.data?.message);
}
};
43 changes: 43 additions & 0 deletions frontend/src/utils/validateCpfCnpj.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
export function validateCPF(cpf: string): boolean {
const cleanCpf = cpf.replace(/\D/g, "");

if (cleanCpf.length !== 11 || /^(\d)\1+$/.test(cleanCpf)) {
return false;
}

const calculateDigit = (cpf: string, factor: number): number => {
let total = 0;
for (let i = 0; i < factor - 1; i++) {
total += parseInt(cpf[i]) * (factor - i);
}
const remainder = total % 11;
return remainder < 2 ? 0 : 11 - remainder;
};

const firstDigit = calculateDigit(cleanCpf, 10);
const secondDigit = calculateDigit(cleanCpf, 11);

return firstDigit === parseInt(cleanCpf[9]) && secondDigit === parseInt(cleanCpf[10]);
};

export function validateCNPJ(cnpj: string): boolean {
const cleanCnpj = cnpj.replace(/\D/g, "");

if (cleanCnpj.length !== 14 || /^(\d)\1+$/.test(cleanCnpj)) {
return false;
}

const calculateDigit = (cnpj: string, positions: number[]): number => {
let total = 0;
for (let i = 0; i < positions.length; i++) {
total += parseInt(cnpj[i]) * positions[i];
}
const remainder = total % 11;
return remainder < 2 ? 0 : 11 - remainder;
};

const firstDigit = calculateDigit(cleanCnpj, [5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]);
const secondDigit = calculateDigit(cleanCnpj, [6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2]);

return firstDigit === parseInt(cleanCnpj[12]) && secondDigit === parseInt(cleanCnpj[13]);
};
82 changes: 82 additions & 0 deletions frontend/src/utils/validateForm.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { validateCNPJ, validateCPF } from "./validateCpfCnpj";

export interface FormData {
fullName: string;
socialName?: string;
document: string;
docType: "cpf" | "cnpj";
phone?: string;
email: string;
password: string;
}

export interface FormErrors {
fullName: string;
document: string;
email: string;
password: string;
}

export const validateFormData = (formData: FormData): { isValid: boolean; errors: FormErrors } => {
const errors: FormErrors = {
fullName: "",
document: "",
email: "",
password: "",
};

let isValid = true;

// Limpar espaços em branco
formData.document = formData.document.trim();
formData.fullName = formData.fullName.trim();
formData.email = formData.email.trim();

// Validação do Nome Completo
if (!formData.fullName) {
errors.fullName = "O Nome Completo é obrigatório.";
isValid = false;
} else if (!formData.fullName.includes(" ")) {
errors.fullName = "O Nome Completo deve conter pelo menos Nome e Sobrenome.";
isValid = false;
}

// Validação do CPF/CNPJ
if (!formData.document) {
errors.document = "O CPF/CNPJ é obrigatório.";
isValid = false;
} else if (formData.docType === "cpf") {
if (!validateCPF(formData.document)) {
errors.document = "CPF inválido.";
isValid = false;
}
} else if (formData.docType === "cnpj") {
if (!validateCNPJ(formData.document)) {
errors.document = "CNPJ inválido.";
isValid = false;
}
}

// Validação do Email
if (!formData.email) {
errors.email = "O Email é obrigatório.";
isValid = false;
} else if (!/\S+@\S+\.\S+/.test(formData.email)) {
errors.email = "Email inválido.";
isValid = false;
}

// Validação da Senha
if (!formData.password) {
errors.password = "A Senha é obrigatória.";
isValid = false;
} else if (formData.password.length < 6) {
errors.password = "A Senha deve ter no mínimo 6 caracteres.";
isValid = false;
} else if (formData.password.length > 20) {
errors.password = "A Senha deve ter no máximo 20 caracteres.";
isValid = false;
}

return { isValid, errors };
};
5 changes: 5 additions & 0 deletions frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1177,6 +1177,11 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==

dotenv@^16.4.5:
version "16.4.5"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==

electron-to-chromium@^1.5.41:
version "1.5.63"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.63.tgz#69444d592fbbe628d129866c2355691ea93eda3e"
Expand Down