pointvirgule commited on
Commit
1553fbb
·
verified ·
1 Parent(s): 14f9a83

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +53 -167
index.html CHANGED
@@ -5,8 +5,6 @@
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>EasyLoc - Gestion des locations saisonnières</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
- <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
9
- <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
10
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
11
  <style>
12
  .tab-active {
@@ -14,9 +12,6 @@
14
  color: #f97316;
15
  font-weight: 600;
16
  }
17
- .datepicker {
18
- z-index: 1000;
19
- }
20
  .contract-section {
21
  margin-bottom: 1.5rem;
22
  }
@@ -28,27 +23,6 @@
28
  .bold-text {
29
  font-weight: bold;
30
  }
31
- .account-modal {
32
- display: none;
33
- position: fixed;
34
- top: 0;
35
- left: 0;
36
- width: 100%;
37
- height: 100%;
38
- background-color: rgba(0,0,0,0.5);
39
- z-index: 1000;
40
- justify-content: center;
41
- align-items: center;
42
- }
43
- .account-modal-content {
44
- background-color: white;
45
- padding: 2rem;
46
- border-radius: 0.5rem;
47
- width: 90%;
48
- max-width: 600px;
49
- max-height: 90vh;
50
- overflow-y: auto;
51
- }
52
  </style>
53
  </head>
54
  <body class="bg-gray-50">
@@ -59,104 +33,14 @@
59
  <i class="fas fa-home text-orange-500 text-4xl mr-3"></i>
60
  <h1 class="text-3xl font-bold text-gray-800">Easy<span class="text-orange-500">Loc</span></h1>
61
  </div>
62
- <div id="account-btn" class="bg-orange-100 text-orange-800 px-4 py-2 rounded-full text-sm font-medium cursor-pointer hover:bg-orange-200 transition">
63
  <i class="fas fa-user-circle mr-2"></i>
64
- <span id="user-name">Mon compte</span>
65
  </div>
66
  </div>
67
  <p class="text-gray-600 mt-2">Gérez vos contrats de location saisonnière en toute simplicité</p>
68
  </header>
69
 
70
- <!-- Account Modal -->
71
- <div id="account-modal" class="account-modal">
72
- <div class="account-modal-content">
73
- <div class="flex justify-between items-center mb-6">
74
- <h2 class="text-2xl font-bold text-gray-800">Mon compte</h2>
75
- <button id="close-modal" class="text-gray-500 hover:text-gray-700">
76
- <i class="fas fa-times"></i>
77
- </button>
78
- </div>
79
-
80
- <div class="mb-8">
81
- <h3 class="text-lg font-semibold text-gray-800 mb-4">Informations de connexion</h3>
82
- <div class="space-y-4">
83
- <div>
84
- <label class="block text-sm font-medium text-gray-700 mb-1">Email*</label>
85
- <input type="email" id="account-email" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
86
- </div>
87
- <div>
88
- <label class="block text-sm font-medium text-gray-700 mb-1">Mot de passe*</label>
89
- <input type="password" id="account-password" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
90
- </div>
91
- </div>
92
- </div>
93
-
94
- <div class="mb-8">
95
- <h3 class="text-lg font-semibold text-gray-800 mb-4">Informations du propriétaire</h3>
96
- <div class="space-y-4">
97
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
98
- <div>
99
- <label class="block text-sm font-medium text-gray-700 mb-1">Nom*</label>
100
- <input type="text" id="account-owner-lastname" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
101
- </div>
102
- <div>
103
- <label class="block text-sm font-medium text-gray-700 mb-1">Prénom*</label>
104
- <input type="text" id="account-owner-firstname" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
105
- </div>
106
- </div>
107
- <div>
108
- <label class="block text-sm font-medium text-gray-700 mb-1">Adresse*</label>
109
- <input type="text" id="account-owner-address" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
110
- </div>
111
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
112
- <div>
113
- <label class="block text-sm font-medium text-gray-700 mb-1">Téléphone*</label>
114
- <input type="tel" id="account-owner-phone" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
115
- </div>
116
- <div>
117
- <label class="block text-sm font-medium text-gray-700 mb-1">Email*</label>
118
- <input type="email" id="account-owner-email" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
119
- </div>
120
- </div>
121
- </div>
122
- </div>
123
-
124
- <div class="mb-8">
125
- <h3 class="text-lg font-semibold text-gray-800 mb-4">Informations sur le logement</h3>
126
- <div class="space-y-4">
127
- <div>
128
- <label class="block text-sm font-medium text-gray-700 mb-1">Adresse du logement*</label>
129
- <input type="text" id="account-property-address" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
130
- </div>
131
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
132
- <div>
133
- <label class="block text-sm font-medium text-gray-700 mb-1">Tarif journalier (€)*</label>
134
- <input type="number" id="account-daily-rate" min="0" step="0.01" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
135
- </div>
136
- <div>
137
- <label class="block text-sm font-medium text-gray-700 mb-1">Frais de ménage (€)*</label>
138
- <input type="number" id="account-cleaning-fee" min="0" step="0.01" class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-orange-500 focus:border-orange-500" required>
139
- </div>
140
- </div>
141
- </div>
142
- </div>
143
-
144
- <div class="flex justify-between pt-4">
145
- <button id="logout-btn" class="px-4 py-2 text-gray-700 font-medium rounded-md hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500 hidden">
146
- <i class="fas fa-sign-out-alt mr-2"></i> Déconnexion
147
- </button>
148
- <div>
149
- <button id="cancel-account" class="px-4 py-2 border border-gray-300 text-gray-700 font-medium rounded-md hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500 mr-2">
150
- Annuler
151
- </button>
152
- <button id="save-account" class="px-6 py-2 bg-orange-600 text-white font-medium rounded-md hover:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-orange-500">
153
- Enregistrer
154
- </button>
155
- </div>
156
- </div>
157
- </div>
158
- </div>
159
-
160
  <div class="bg-white rounded-xl shadow-md overflow-hidden">
161
  <!-- Navigation tabs -->
162
  <div class="border-b border-gray-200">
@@ -441,7 +325,7 @@
441
 
442
  <div class="contract-section">
443
  <h3 class="font-bold">8. DÉCLARATION DU BAILLEUR</h3>
444
- <p>Le Bailleur déclare être propriétaire du logement et en avoir la libre disposition et la pleine jouissance durant la période définie au paragraphe 3.</p>
445
  </div>
446
 
447
  <div class="contract-section">
@@ -515,7 +399,7 @@
515
  });
516
 
517
  document.getElementById('next-to-tenant').addEventListener('click', () => {
518
- if (document.getElementById('owner-form').checkValidity()) {
519
  calculatePrices();
520
  showTab('tab2');
521
  } else {
@@ -528,8 +412,7 @@
528
  });
529
 
530
  document.getElementById('next-to-contract').addEventListener('click', () => {
531
- if (document.getElementById('tenant-form').checkValidity()) {
532
- calculateBalance();
533
  generateContract();
534
  showTab('tab3');
535
  } else {
@@ -560,6 +443,39 @@
560
  document.getElementById(`${tabName}-btn`).classList.remove('text-gray-500');
561
  }
562
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563
  // Calculate rental prices when dates or rates change
564
  document.getElementById('rental-start').addEventListener('change', calculatePrices);
565
  document.getElementById('rental-end').addEventListener('change', calculatePrices);
@@ -603,16 +519,6 @@
603
  document.getElementById('balance-due').textContent = `${(totalPrice - depositAmount).toFixed(2)} €`;
604
  }
605
 
606
- // Calculate balance due
607
- function calculateBalance() {
608
- const totalPrice = parseFloat(document.getElementById('total-price').textContent) || 0;
609
- const depositAmount = parseFloat(document.getElementById('deposit-amount').value) || 0;
610
- const balanceDue = totalPrice - depositAmount;
611
-
612
- document.getElementById('deposit-display').textContent = `${depositAmount.toFixed(2)} €`;
613
- document.getElementById('balance-due').textContent = `${balanceDue.toFixed(2)} €`;
614
- }
615
-
616
  // Generate contract content
617
  function generateContract() {
618
  // Owner info
@@ -648,48 +554,28 @@
648
  document.getElementById('total-price-contract').textContent = document.getElementById('total-price').textContent;
649
  document.getElementById('deposit-amount-display').textContent = document.getElementById('deposit-amount').value;
650
 
651
- document.getElementById('balance-due-display').textContent = document.getElementById('balance-due').textContent.split(' ')[0];
 
652
 
653
  // Contract date
654
  const today = new Date();
655
  document.getElementById('contract-date').textContent = today.toLocaleDateString('fr-FR', options);
656
  }
657
 
658
- // Export to PDF
659
  document.getElementById('export-pdf').addEventListener('click', () => {
660
- const { jsPDF } = window.jspdf;
661
- const element = document.getElementById('contract-content');
662
-
663
- html2canvas(element, {
664
- scale: 2,
665
- logging: false,
666
- useCORS: true
667
- }).then(canvas => {
668
- const imgData = canvas.toDataURL('image/png');
669
- const pdf = new jsPDF('p', 'mm', 'a4');
670
- const imgWidth = 210; // A4 width in mm
671
- const pageHeight = 295; // A4 height in mm
672
- const imgHeight = canvas.height * imgWidth / canvas.width;
673
- let heightLeft = imgHeight;
674
- let position = 0;
675
-
676
- pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
677
- heightLeft -= pageHeight;
678
-
679
- while (heightLeft >= 0) {
680
- position = heightLeft - imgHeight;
681
- pdf.addPage();
682
- pdf.addImage(imgData, 'PNG', 0, position, imgWidth, imgHeight);
683
- heightLeft -= pageHeight;
684
- }
685
-
686
- const fileName = `contrat_location_${document.getElementById('tenant-lastname').value}_${document.getElementById('rental-start').value}.pdf`;
687
- pdf.save(fileName);
688
- });
689
  });
690
 
691
- // Export to Word
692
  document.getElementById('export-word').addEventListener('click', () => {
693
- const contractContent = document.getElementById('contract-content').innerHTML;
694
- const preHtml = `<html xmlns:o='urn:schemas-microsoft-com:office:office' xmlns:w='urn:schemas-microsoft-com:office:word' xmlns='http://www.w3.org/TR/REC-html40'><head><meta charset='utf-8'><title>Contrat de location</title></head><body>`;
695
- const postHtml = `<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=pointvirgule/easyloc" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body></html>
 
 
 
 
 
 
 
 
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
  <title>EasyLoc - Gestion des locations saisonnières</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
 
 
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
  <style>
10
  .tab-active {
 
12
  color: #f97316;
13
  font-weight: 600;
14
  }
 
 
 
15
  .contract-section {
16
  margin-bottom: 1.5rem;
17
  }
 
23
  .bold-text {
24
  font-weight: bold;
25
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  </style>
27
  </head>
28
  <body class="bg-gray-50">
 
33
  <i class="fas fa-home text-orange-500 text-4xl mr-3"></i>
34
  <h1 class="text-3xl font-bold text-gray-800">Easy<span class="text-orange-500">Loc</span></h1>
35
  </div>
36
+ <div class="bg-orange-100 text-orange-800 px-4 py-2 rounded-full text-sm font-medium">
37
  <i class="fas fa-user-circle mr-2"></i>
38
+ <span>Mon compte</span>
39
  </div>
40
  </div>
41
  <p class="text-gray-600 mt-2">Gérez vos contrats de location saisonnière en toute simplicité</p>
42
  </header>
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  <div class="bg-white rounded-xl shadow-md overflow-hidden">
45
  <!-- Navigation tabs -->
46
  <div class="border-b border-gray-200">
 
325
 
326
  <div class="contract-section">
327
  <h3 class="font-bold">8. DÉCLARATION DU BAILLEUR</h3>
328
+ <p>Le Bailleur déclare être propriétaire du logement et en avoir la libre disposition et la pleine jouissance durant la période définite au paragraphe 3.</p>
329
  </div>
330
 
331
  <div class="contract-section">
 
399
  });
400
 
401
  document.getElementById('next-to-tenant').addEventListener('click', () => {
402
+ if (validateOwnerForm()) {
403
  calculatePrices();
404
  showTab('tab2');
405
  } else {
 
412
  });
413
 
414
  document.getElementById('next-to-contract').addEventListener('click', () => {
415
+ if (validateTenantForm()) {
 
416
  generateContract();
417
  showTab('tab3');
418
  } else {
 
443
  document.getElementById(`${tabName}-btn`).classList.remove('text-gray-500');
444
  }
445
 
446
+ // Form validation
447
+ function validateOwnerForm() {
448
+ const requiredFields = [
449
+ 'owner-lastname', 'owner-firstname', 'owner-address',
450
+ 'owner-phone', 'owner-email', 'property-address',
451
+ 'rental-start', 'rental-end', 'daily-rate', 'cleaning-fee'
452
+ ];
453
+
454
+ for (const fieldId of requiredFields) {
455
+ const field = document.getElementById(fieldId);
456
+ if (!field.value.trim()) {
457
+ field.focus();
458
+ return false;
459
+ }
460
+ }
461
+ return true;
462
+ }
463
+
464
+ function validateTenantForm() {
465
+ const requiredFields = [
466
+ 'tenant-lastname', 'tenant-firstname', 'tenant-phone', 'tenant-email'
467
+ ];
468
+
469
+ for (const fieldId of requiredFields) {
470
+ const field = document.getElementById(fieldId);
471
+ if (!field.value.trim()) {
472
+ field.focus();
473
+ return false;
474
+ }
475
+ }
476
+ return true;
477
+ }
478
+
479
  // Calculate rental prices when dates or rates change
480
  document.getElementById('rental-start').addEventListener('change', calculatePrices);
481
  document.getElementById('rental-end').addEventListener('change', calculatePrices);
 
519
  document.getElementById('balance-due').textContent = `${(totalPrice - depositAmount).toFixed(2)} €`;
520
  }
521
 
 
 
 
 
 
 
 
 
 
 
522
  // Generate contract content
523
  function generateContract() {
524
  // Owner info
 
554
  document.getElementById('total-price-contract').textContent = document.getElementById('total-price').textContent;
555
  document.getElementById('deposit-amount-display').textContent = document.getElementById('deposit-amount').value;
556
 
557
+ const balanceDue = parseFloat(document.getElementById('balance-due').textContent);
558
+ document.getElementById('balance-due-display').textContent = balanceDue.toFixed(2);
559
 
560
  // Contract date
561
  const today = new Date();
562
  document.getElementById('contract-date').textContent = today.toLocaleDateString('fr-FR', options);
563
  }
564
 
565
+ // Export to PDF (placeholder)
566
  document.getElementById('export-pdf').addEventListener('click', () => {
567
+ alert('Fonctionnalité PDF à implémenter');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  });
569
 
570
+ // Export to Word (placeholder)
571
  document.getElementById('export-word').addEventListener('click', () => {
572
+ alert('Fonctionnalité Word à implémenter');
573
+ });
574
+
575
+ // Save contract (placeholder)
576
+ document.getElementById('save-contract').addEventListener('click', () => {
577
+ alert('Contrat enregistré avec succès !');
578
+ });
579
+ </script>
580
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=pointvirgule/easyloc" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
581
+ </html>