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(contract): add javascript validation #148

Merged
merged 21 commits into from
Dec 10, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
8871f90
feat (contract): Validation Contracts
Chuck-D-Norris Nov 28, 2024
8fc2b54
Merge branch 'main' into feat/contract
0x1026 Nov 28, 2024
c6e4e74
fix: .env won't be uploaded
0x1026 Nov 28, 2024
97d9930
Merge branch 'main' into feat/contract
0x1026 Dec 2, 2024
7ffbd0a
Jacascript
Chuck-D-Norris Dec 3, 2024
0e6ceae
Merge branch 'main' into feat/contract
Chuck-D-Norris Dec 3, 2024
d7f4c58
Merge branch 'main' into feat/contract
0x1026 Dec 3, 2024
e8b039c
Merge branch 'feat/contract' of https://github.com/Projecte-UrbanTree…
Chuck-D-Norris Dec 3, 2024
723b94f
Solution conflicts
Chuck-D-Norris Dec 3, 2024
bfbd965
Merge branch 'main' into feat/contract
0x1026 Dec 3, 2024
becf1cb
Merge remote-tracking branch 'origin/main' into feat/contract
0x1026 Dec 3, 2024
31093b9
Merge branch 'main' into feat/contract
0x1026 Dec 4, 2024
7a6d833
Merge branch 'main' into feat/contract
0x1026 Dec 4, 2024
b628285
Merge branch 'main' into feat/contract
projecte-urbantree-bot Dec 4, 2024
2de3850
Merge branch 'main' into feat/contract
0x1026 Dec 9, 2024
54219be
fix(database): change contract date fields from timestamp to date
0x1026 Dec 10, 2024
c007953
refactor(contract): update form structure and validation, remove obso…
0x1026 Dec 10, 2024
ca66f9f
refactor(tree-type): rename form IDs for consistency
0x1026 Dec 10, 2024
ee04f10
fix(contract): add max attribute to invoice fields for validation
0x1026 Dec 10, 2024
14d83e2
refactor(validations): improve validations for both contract and tree…
0x1026 Dec 10, 2024
b06d149
Merge branch 'main' into feat/contract
0x1026 Dec 10, 2024
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
47 changes: 27 additions & 20 deletions src/app/Views/Contract/Create.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<div class="mb-4 flex justify-end">
<a href="/contracts"
class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg shadow focus:outline-none focus:ring focus:ring-green-500 flex items-center space-x-2">
<!-- Heroicon for return/back (chevron-left) -->
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
Expand All @@ -11,61 +10,69 @@ class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg

<div class="bg-white p-8 border border-gray-300 rounded-lg shadow-md">
<h2 class="text-2xl font-semibold text-gray-800 mb-6">Create Contract</h2>
<form action="/contract/store" method="POST" class="space-y-6">
<!-- Name -->

<div id="errorMessages" class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-6 hidden"></div>

<form id="contractForm" action="/contracts/store" method="POST" class="space-y-6">
<div>
<label for="name" class="block text-sm font-medium text-gray-700 mb-1">Name</label>
<input type="text" id="name" name="name"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500"
required>
</div>

<!-- Start Date -->
<div>
<label for="start_date" class="block text-sm font-medium text-gray-700 mb-1">Start Date</label>
<input type="date" id="start_date" name="start_date"
<input type="text" id="start_date" name="start_date"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500"
required>
</div>

<!-- End Date -->
<div>
<label for="end_date" class="block text-sm font-medium text-gray-700 mb-1">End Date</label>
<input type="date" id="end_date" name="end_date"
<input type="text" id="end_date" name="end_date"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500"
required>
</div>

<!-- Invoice Proposed -->
<div>
<label for="invoice_proposed" class="block text-sm font-medium text-gray-700 mb-1">Invoice Proposed</label>
<input type="number" step="0.01" id="invoice_proposed" name="invoice_proposed"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500"
required>
</div>

<!-- Invoice Agreed -->
<div>
<label for="invoice_agreed" class="block text-sm font-medium text-gray-700 mb-1">Invoice agreed</label>
<label for="invoice_agreed" class="block text-sm font-medium text-gray-700 mb-1">Invoice Agreed</label>
<input type="number" id="invoice_agreed" name="invoice_agreed"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500"
required>
</div>

<!-- Invoice Paid -->
<div>
<label for="invoice_paid" class="block text-sm font-medium text-gray-700 mb-1">Invoice paid</label>
<label for="invoice_paid" class="block text-sm font-medium text-gray-700 mb-1">Invoice Paid</label>
<input type="number" id="invoice_paid" name="invoice_paid"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500"
required>
</div>

<!-- Submit Button -->
<div class="flex items-center">
<button type="submit"
class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg focus:outline-none focus:ring focus:ring-blue-500">
Create Contract
</button>
</div>
<button type="button" id="submitBtn"
class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg focus:outline-none focus:ring focus:ring-blue-500">
Create Contract
</button>
</form>
</div>
</div>

<script src="/assets/js/app.js"></script>
<script>
document.getElementById('submitBtn').addEventListener('click', function(event) {
const errorMessagesDiv = document.getElementById('errorMessages');
validateForm(event);

if (errorMessagesDiv.innerHTML.trim() !== '') {
errorMessagesDiv.classList.remove('hidden');
} else {
errorMessagesDiv.classList.add('hidden');
}
});
</script>
59 changes: 31 additions & 28 deletions src/app/Views/Contract/Edit.php
Original file line number Diff line number Diff line change
@@ -1,70 +1,73 @@
<div class="mb-4 flex justify-end">
<a href="/contracts"
class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg shadow focus:outline-none focus:ring focus:ring-green-500 flex items-center space-x-2">
<!-- Heroicon for return/back (chevron-left) -->
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
</svg>
<span>Return to Contracts</span>
</a>
</div>

<div class="bg-white p-8 border border-gray-300 rounded-lg shadow-md">
<h2 class="text-2xl font-semibold text-gray-800 mb-6">Edit Contract</h2>
<form action="/contract/<?php echo htmlspecialchars($contract->getId()); ?>/update" method="POST" class="space-y-6">
<!-- Name -->


<div id="errorMessages"
class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative mb-6 hidden"></div>

<form id="contractForm" action="/contracts/<?php echo htmlspecialchars($contract->getId()); ?>/update" method="POST"
class="space-y-6">

<div>
<label for="name" class="block text-sm font-medium text-gray-700 mb-1">Name</label>
<input type="text" id="name" name="name" value="<?php echo htmlspecialchars($contract->name); ?>"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500">
</div>

<!-- Start Date -->

<div>
<label for="start_date" class="block text-sm font-medium text-gray-700 mb-1">Start Date</label>
<input type="date" id="start_date" name="start_date"
<input type="datetime-local" id="start_date" name="start_date"
value="<?php echo htmlspecialchars($contract->start_date); ?>"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500">
</div>

<!-- End Date -->

<div>
<label for="end_date" class="block text-sm font-medium text-gray-700 mb-1">End Date</label>
<input type="date" id="end_date" name="end_date"
<input type="datetime-local" id="end_date" name="end_date"
value="<?php echo htmlspecialchars($contract->end_date); ?>"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500">
</div>

<!-- Invoice Proposed -->
<div>
<label for="invoice_proposed" class="block text-sm font-medium text-gray-700 mb-1">Invoice Proposed</label>
<input type="number" step="0.01" id="invoice_proposed" name="invoice_proposed"
value="<?php echo htmlspecialchars($contract->invoice_proposed); ?>"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500">
</div>

<!-- Invoice Agreed -->
<div>
<label for="invoice_agreed" class="block text-sm font-medium text-gray-700 mb-1">Invoice Agreed</label>
<input type="number" step="0.01" id="invoice_agreed" name="invoice_agreed"
value="<?php echo htmlspecialchars($contract->invoice_agreed); ?>"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500">
</div>

<!-- Invoice Paid -->
<div>
<label for="invoice_paid" class="block text-sm font-medium text-gray-700 mb-1">Invoice Paid</label>
<input type="number" step="0.01" id="invoice_paid" name="invoice_paid"
value="<?php echo htmlspecialchars($contract->invoice_paid); ?>"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500">
</div>

<!-- Submit Button -->
<div class="flex items-center">
<button type="submit"
class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg focus:outline-none focus:ring focus:ring-blue-500">
Update Contract
</button>
</div>
<button type="button" id="submitBtn"
class="bg-blue-500 hover:bg-blue-600 text-white font-medium py-2 px-4 rounded-lg focus:outline-none focus:ring focus:ring-blue-500">
Update Contract
</button>
</form>
</div>
</div>

<script src="/assets/js/app.js"></script>
<script>
document.getElementById('submitBtn').addEventListener('click', function (event) {
const errorMessagesDiv = document.getElementById('errorMessages');
validateForm(event);

if (errorMessagesDiv.innerHTML.trim() !== '') {
errorMessagesDiv.classList.remove('hidden');
} else {
errorMessagesDiv.classList.add('hidden');
}
});
</script>
62 changes: 62 additions & 0 deletions src/app/Views/Contract/validacions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
document.getElementById("form").addEventListener("submit", function (e) {
event.preventDefault();


const name = document.getElementById("name").value.trim();
const startDate = document.getElementById("start_date").value.trim();
const endDate = document.getElementById("end_date").value.trim();
const invoiceProposed = document.getElementById("invoice_proposed").value.trim();
const invoiceAgreed = document.getElementById("invoice_agreed").value.trim();
const invoicePaid = document.getElementById("invoice_paid").value.trim();


let errorMessage = '';

const namePattern = /^[a-zA-Z\s]+$/;
if (!name) {
errorMessage += 'Name is required.<br>';
} else if (!namePattern.test(name)) {
errorMessage += 'Name must only contain letters and spaces.<br>';
}

const startDatePattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/;
if (!startDate) {
errorMessage += 'Start Date is required.<br>';
} else if (!startDatePattern.test(startDate)) {
errorMessage += 'Start Date must be in the format YYYY-MM-DDTHH:MM.<br>';
}

const endDatePattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/;
if (!endDate) {
errorMessage += 'End Date is required.<br>';
} else if (!endDatePattern.test(endDate)) {
errorMessage += 'End Date must be in the format YYYY-MM-DDTHH:MM.<br>';
}

const invoiceProposedPattern = /^\d+(\.\d{1,2})?$/;
if (!invoiceProposed) {
errorMessage += 'Invoice Proposed is required.<br>';
} else if (!invoiceProposedPattern.test(invoiceProposed)) {
errorMessage += 'Invoice Proposed must be a number.<br>';
}

const invoiceAgreedPattern = /^\d+(\.\d{1,2})?$/;
if (!invoiceAgreed) {
errorMessage += 'Invoice Agreed is required.<br>';
} else if (!invoiceAgreedPattern.test(invoiceAgreed)) {
errorMessage += 'Invoice Agreed must be a number.<br>';
}

const invoicePaidPattern = /^\d+(\.\d{1,2})?$/;
if (!invoicePaid) {
errorMessage += 'Invoice Paid is required.<br>';
} else if (!invoicePaidPattern.test(invoicePaid)) {
errorMessage += 'Invoice Paid must be a number.<br>';
}

if (errorMessage) {
alert(errorMessage);
return false;
}
}
)
65 changes: 65 additions & 0 deletions src/public/assets/js/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

//Validacio de contractes

function validateForm(event) {
const errorMessagesDiv = document.getElementById('errorMessages');
errorMessagesDiv.innerHTML = '';

let isValid = true;


var name = document.getElementById('name').value;
var nameRegex = /^[A-Za-z\s]+$/;
if (!nameRegex.test(name)) {
isValid = false;
const errorMsg = document.createElement('p');
errorMsg.textContent = '- El nom només pot contenir lletres i espais.';
errorMsg.classList.add('text-red-600', 'font-medium', 'bg-red-100', 'p-2', 'rounded-md');
errorMessagesDiv.appendChild(errorMsg);
}

var startDate = document.getElementById('start_date').value;
var endDate = document.getElementById('end_date').value;
if (new Date(startDate) > new Date(endDate)) {
isValid = false;
const errorMsg = document.createElement('p');
errorMsg.textContent = '- La data d\'inici no pot ser posterior a la data de finalització.';
errorMsg.classList.add('text-red-600', 'font-medium', 'bg-red-100', 'p-2', 'rounded-md');
errorMessagesDiv.appendChild(errorMsg);
}


var invoiceProposed = parseFloat(document.getElementById('invoice_proposed').value);
var invoiceAgreed = parseFloat(document.getElementById('invoice_agreed').value);
var invoicePaid = parseFloat(document.getElementById('invoice_paid').value);

if (invoiceProposed < 0) {
isValid = false;
const errorMsg = document.createElement('p');
errorMsg.textContent = '- El preu proposat no pot ser negatiu.';
errorMsg.classList.add('text-red-600', 'font-medium', 'bg-red-100', 'p-2', 'rounded-md');
errorMessagesDiv.appendChild(errorMsg);
}
if (invoiceAgreed < 0) {
isValid = false;
const errorMsg = document.createElement('p');
errorMsg.textContent = '- El preu acordat no pot ser negatiu.';
errorMsg.classList.add('text-red-600', 'font-medium', 'bg-red-100', 'p-2', 'rounded-md');
errorMessagesDiv.appendChild(errorMsg);
}
if (invoicePaid < 0) {
isValid = false;
const errorMsg = document.createElement('p');
errorMsg.textContent = '- El preu pagat no pot ser negatiu.';
errorMsg.classList.add('text-red-600', 'font-medium', 'bg-red-100', 'p-2', 'rounded-md');
errorMessagesDiv.appendChild(errorMsg);
}


if (!isValid) {
event.preventDefault();
} else {

document.getElementById('contractForm').submit();
}
}