froiln1565 commited on
Commit
75c33fc
·
verified ·
1 Parent(s): 784aed3

Make me an automatic calculator Titled: "Safety Officers Specialized Training Calculator and Tracker" that needed an input for Days Participants with Title and Description/ Details/ close/open/ongoing/pending. it should auto calculate also also add an upload photo functionality so that I can upload a photo in landscape rectangular orientation that fits the whole photo when uploaded. also put other details and other inputs needed for it go freestyle. just make the Format Dark Green. also make sure that the Data is auto stored when the browser or application is closed. also add a filter functionality, Edit and Delete Functionality, Export and Import Data Functionality and other stuff. also make sure that there's no existing input data yet so that It is clean when I use it. Add beside the title an upload photo functionality so that I can add my Company logo, also on the Training Programs section make the space for pictures a bit larger, and also make the list be minimized so that I can save space. also make the list of training programs be in scroll tab form. to save space Make the photo larger and appear below all the details inputted. on the Additional Cost add there Multiple Additional cost and put an input detail for what kind of additional cost that is. make the cost into Philippine Peso Currency. - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1282 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Training
3
- emoji: 🐢
4
- colorFrom: gray
5
- colorTo: red
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: training
3
+ emoji: 🐳
4
+ colorFrom: purple
5
+ colorTo: green
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1282 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Safety Officers Training Calculator</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
+ .photo-preview {
11
+ width: 100%;
12
+ height: 300px;
13
+ object-fit: cover;
14
+ border-radius: 0.5rem;
15
+ margin-top: 1rem;
16
+ display: none;
17
+ }
18
+ .training-item {
19
+ transition: all 0.3s ease;
20
+ }
21
+ .training-item.collapsed {
22
+ max-height: 60px;
23
+ overflow: hidden;
24
+ }
25
+ .scrollable-list {
26
+ max-height: 400px;
27
+ overflow-y: auto;
28
+ }
29
+ .scrollable-list::-webkit-scrollbar {
30
+ width: 8px;
31
+ }
32
+ .scrollable-list::-webkit-scrollbar-track {
33
+ background: #f1f1f1;
34
+ border-radius: 10px;
35
+ }
36
+ .scrollable-list::-webkit-scrollbar-thumb {
37
+ background: #2d7d46;
38
+ border-radius: 10px;
39
+ }
40
+ .scrollable-list::-webkit-scrollbar-thumb:hover {
41
+ background: #1e5631;
42
+ }
43
+ </style>
44
+ </head>
45
+ <body class="bg-gray-100">
46
+ <div class="container mx-auto p-4 max-w-6xl">
47
+ <!-- Header with Logo Upload -->
48
+ <div class="bg-green-800 text-white p-6 rounded-lg shadow-lg mb-6 flex justify-between items-center">
49
+ <div class="flex items-center">
50
+ <div class="mr-4">
51
+ <img id="company-logo" src="" alt="Company Logo" class="h-16 w-16 object-contain hidden">
52
+ <label for="logo-upload" class="cursor-pointer bg-green-700 hover:bg-green-600 p-2 rounded-lg">
53
+ <i class="fas fa-upload mr-2"></i>Upload Logo
54
+ </label>
55
+ <input type="file" id="logo-upload" accept="image/*" class="hidden">
56
+ </div>
57
+ <div>
58
+ <h1 class="text-3xl font-bold">Safety Officers Specialized Training Calculator and Tracker</h1>
59
+ <p class="text-green-200">Track and manage all your safety training programs efficiently</p>
60
+ </div>
61
+ </div>
62
+ </div>
63
+
64
+ <!-- Main Content -->
65
+ <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
66
+ <!-- Input Form -->
67
+ <div class="lg:col-span-2 bg-white p-6 rounded-lg shadow-lg">
68
+ <h2 class="text-2xl font-semibold text-green-800 mb-4">Add New Training Program</h2>
69
+
70
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
71
+ <!-- Basic Information -->
72
+ <div class="md:col-span-2 bg-green-50 p-4 rounded-lg">
73
+ <h3 class="text-lg font-medium text-green-800 mb-3">Basic Information</h3>
74
+ <div class="space-y-3">
75
+ <div>
76
+ <label for="training-title" class="block text-sm font-medium text-green-700">Training Title*</label>
77
+ <input type="text" id="training-title" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
78
+ </div>
79
+ <div>
80
+ <label for="training-description" class="block text-sm font-medium text-green-700">Description*</label>
81
+ <textarea id="training-description" rows="3" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border"></textarea>
82
+ </div>
83
+ </div>
84
+ </div>
85
+
86
+ <!-- Training Details -->
87
+ <div class="bg-green-50 p-4 rounded-lg">
88
+ <h3 class="text-lg font-medium text-green-800 mb-3">Training Details</h3>
89
+ <div class="space-y-3">
90
+ <div>
91
+ <label for="start-date" class="block text-sm font-medium text-green-700">Start Date*</label>
92
+ <input type="date" id="start-date" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
93
+ </div>
94
+ <div>
95
+ <label for="end-date" class="block text-sm font-medium text-green-700">End Date*</label>
96
+ <input type="date" id="end-date" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
97
+ </div>
98
+ <div>
99
+ <label for="participants" class="block text-sm font-medium text-green-700">Number of Participants*</label>
100
+ <input type="number" id="participants" min="1" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
101
+ </div>
102
+ <div>
103
+ <label for="days" class="block text-sm font-medium text-green-700">Training Days*</label>
104
+ <input type="number" id="days" min="1" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
105
+ </div>
106
+ </div>
107
+ </div>
108
+
109
+ <!-- Cost Information -->
110
+ <div class="bg-green-50 p-4 rounded-lg">
111
+ <h3 class="text-lg font-medium text-green-800 mb-3">Cost Information</h3>
112
+ <div class="space-y-3">
113
+ <div>
114
+ <label for="base-cost" class="block text-sm font-medium text-green-700">Base Cost (₱)*</label>
115
+ <input type="number" id="base-cost" min="0" step="0.01" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
116
+ </div>
117
+ <div>
118
+ <label for="cost-per-participant" class="block text-sm font-medium text-green-700">Cost per Participant (₱)*</label>
119
+ <input type="number" id="cost-per-participant" min="0" step="0.01" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
120
+ </div>
121
+ <div>
122
+ <label for="cost-per-day" class="block text-sm font-medium text-green-700">Cost per Day (₱)*</label>
123
+ <input type="number" id="cost-per-day" min="0" step="0.01" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
124
+ </div>
125
+ </div>
126
+ </div>
127
+
128
+ <!-- Additional Costs -->
129
+ <div class="md:col-span-2 bg-green-50 p-4 rounded-lg">
130
+ <h3 class="text-lg font-medium text-green-800 mb-3">Additional Costs</h3>
131
+ <div id="additional-costs-container">
132
+ <div class="additional-cost-item grid grid-cols-1 md:grid-cols-3 gap-3 mb-3">
133
+ <div>
134
+ <label class="block text-sm font-medium text-green-700">Cost Type</label>
135
+ <input type="text" class="cost-type mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" placeholder="e.g., Materials, Venue">
136
+ </div>
137
+ <div>
138
+ <label class="block text-sm font-medium text-green-700">Amount (₱)</label>
139
+ <input type="number" min="0" step="0.01" class="cost-amount mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
140
+ </div>
141
+ <div class="flex items-end">
142
+ <button type="button" class="remove-cost bg-red-500 hover:bg-red-600 text-white py-2 px-3 rounded-md text-sm">
143
+ <i class="fas fa-trash mr-1"></i> Remove
144
+ </button>
145
+ </div>
146
+ </div>
147
+ </div>
148
+ <button type="button" id="add-cost" class="mt-2 bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded-md text-sm">
149
+ <i class="fas fa-plus mr-1"></i> Add Another Cost
150
+ </button>
151
+ </div>
152
+
153
+ <!-- Status and Photo -->
154
+ <div class="md:col-span-2 bg-green-50 p-4 rounded-lg">
155
+ <h3 class="text-lg font-medium text-green-800 mb-3">Status & Documentation</h3>
156
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
157
+ <div>
158
+ <label for="status" class="block text-sm font-medium text-green-700">Status*</label>
159
+ <select id="status" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
160
+ <option value="pending">Pending</option>
161
+ <option value="ongoing">Ongoing</option>
162
+ <option value="completed">Completed</option>
163
+ <option value="cancelled">Cancelled</option>
164
+ </select>
165
+ </div>
166
+ <div>
167
+ <label for="training-photo" class="block text-sm font-medium text-green-700">Training Photo</label>
168
+ <input type="file" id="training-photo" accept="image/*" class="mt-1 block w-full text-sm text-green-700 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-green-500 file:text-white hover:file:bg-green-600">
169
+ <img id="photo-preview" class="photo-preview mt-2" alt="Training photo preview">
170
+ </div>
171
+ </div>
172
+ </div>
173
+ </div>
174
+
175
+ <!-- Submit Button -->
176
+ <div class="mt-6 flex justify-end">
177
+ <button type="button" id="save-training" class="bg-green-700 hover:bg-green-800 text-white font-bold py-2 px-6 rounded-lg shadow">
178
+ <i class="fas fa-save mr-2"></i> Save Training
179
+ </button>
180
+ </div>
181
+ </div>
182
+
183
+ <!-- Summary and Calculations -->
184
+ <div class="bg-white p-6 rounded-lg shadow-lg">
185
+ <h2 class="text-2xl font-semibold text-green-800 mb-4">Training Summary</h2>
186
+
187
+ <div class="bg-green-50 p-4 rounded-lg mb-4">
188
+ <h3 class="text-lg font-medium text-green-800 mb-3">Calculated Costs</h3>
189
+ <div class="space-y-2">
190
+ <div class="flex justify-between">
191
+ <span class="text-green-700">Base Cost:</span>
192
+ <span id="summary-base-cost" class="font-medium">₱0.00</span>
193
+ </div>
194
+ <div class="flex justify-between">
195
+ <span class="text-green-700">Participants Cost:</span>
196
+ <span id="summary-participants-cost" class="font-medium">₱0.00</span>
197
+ </div>
198
+ <div class="flex justify-between">
199
+ <span class="text-green-700">Days Cost:</span>
200
+ <span id="summary-days-cost" class="font-medium">₱0.00</span>
201
+ </div>
202
+ <div class="flex justify-between">
203
+ <span class="text-green-700">Additional Costs:</span>
204
+ <span id="summary-additional-costs" class="font-medium">₱0.00</span>
205
+ </div>
206
+ <div class="border-t border-green-300 my-2 pt-2 flex justify-between font-bold text-green-800">
207
+ <span>Total Cost:</span>
208
+ <span id="summary-total-cost">₱0.00</span>
209
+ </div>
210
+ <div class="border-t border-green-300 my-2 pt-2 flex justify-between">
211
+ <span class="text-green-700">Cost per Participant:</span>
212
+ <span id="summary-cost-per-participant" class="font-medium">₱0.00</span>
213
+ </div>
214
+ </div>
215
+ </div>
216
+
217
+ <!-- Filters -->
218
+ <div class="bg-green-50 p-4 rounded-lg mb-4">
219
+ <h3 class="text-lg font-medium text-green-800 mb-3">Filter Trainings</h3>
220
+ <div class="space-y-3">
221
+ <div>
222
+ <label for="filter-status" class="block text-sm font-medium text-green-700">Status</label>
223
+ <select id="filter-status" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
224
+ <option value="all">All Statuses</option>
225
+ <option value="pending">Pending</option>
226
+ <option value="ongoing">Ongoing</option>
227
+ <option value="completed">Completed</option>
228
+ <option value="cancelled">Cancelled</option>
229
+ </select>
230
+ </div>
231
+ <div>
232
+ <label for="filter-date" class="block text-sm font-medium text-green-700">Date Range</label>
233
+ <select id="filter-date" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
234
+ <option value="all">All Dates</option>
235
+ <option value="this-month">This Month</option>
236
+ <option value="last-month">Last Month</option>
237
+ <option value="this-year">This Year</option>
238
+ <option value="last-year">Last Year</option>
239
+ </select>
240
+ </div>
241
+ <div>
242
+ <label for="search-title" class="block text-sm font-medium text-green-700">Search Title</label>
243
+ <input type="text" id="search-title" placeholder="Search training title..." class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
244
+ </div>
245
+ </div>
246
+ </div>
247
+
248
+ <!-- Data Management -->
249
+ <div class="bg-green-50 p-4 rounded-lg">
250
+ <h3 class="text-lg font-medium text-green-800 mb-3">Data Management</h3>
251
+ <div class="grid grid-cols-1 gap-2">
252
+ <button id="export-data" class="bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded-md text-sm w-full text-left">
253
+ <i class="fas fa-file-export mr-2"></i> Export Data
254
+ </button>
255
+ <label for="import-data" class="bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded-md text-sm w-full text-left cursor-pointer">
256
+ <i class="fas fa-file-import mr-2"></i> Import Data
257
+ <input type="file" id="import-data" accept=".json" class="hidden">
258
+ </label>
259
+ <button id="clear-data" class="bg-red-500 hover:bg-red-600 text-white py-2 px-4 rounded-md text-sm w-full text-left">
260
+ <i class="fas fa-trash-alt mr-2"></i> Clear All Data
261
+ </button>
262
+ </div>
263
+ </div>
264
+ </div>
265
+ </div>
266
+
267
+ <!-- Training Programs List -->
268
+ <div class="mt-8 bg-white p-6 rounded-lg shadow-lg">
269
+ <div class="flex justify-between items-center mb-4">
270
+ <h2 class="text-2xl font-semibold text-green-800">Training Programs</h2>
271
+ <div class="flex items-center">
272
+ <span class="text-sm text-green-700 mr-2">Collapse All</span>
273
+ <label class="relative inline-flex items-center cursor-pointer">
274
+ <input type="checkbox" id="toggle-collapse" class="sr-only peer">
275
+ <div class="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-green-300 rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-green-600"></div>
276
+ </label>
277
+ </div>
278
+ </div>
279
+
280
+ <div id="training-list" class="scrollable-list space-y-3">
281
+ <!-- Training items will be added here dynamically -->
282
+ <div class="text-center py-8 text-gray-500" id="empty-message">
283
+ <i class="fas fa-clipboard-list text-4xl mb-2"></i>
284
+ <p>No training programs added yet.</p>
285
+ <p class="text-sm">Add your first training program using the form above.</p>
286
+ </div>
287
+ </div>
288
+ </div>
289
+ </div>
290
+
291
+ <!-- Edit Modal -->
292
+ <div id="edit-modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
293
+ <div class="bg-white rounded-lg shadow-xl p-6 w-full max-w-2xl max-h-[90vh] overflow-y-auto">
294
+ <div class="flex justify-between items-center mb-4">
295
+ <h3 class="text-xl font-semibold text-green-800">Edit Training Program</h3>
296
+ <button id="close-edit-modal" class="text-gray-500 hover:text-gray-700">
297
+ <i class="fas fa-times"></i>
298
+ </button>
299
+ </div>
300
+ <div id="edit-form-content" class="space-y-4">
301
+ <!-- Edit form content will be inserted here -->
302
+ </div>
303
+ <div class="mt-6 flex justify-end space-x-3">
304
+ <button id="cancel-edit" class="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-2 px-4 rounded">
305
+ Cancel
306
+ </button>
307
+ <button id="save-edit" class="bg-green-700 hover:bg-green-800 text-white font-bold py-2 px-4 rounded">
308
+ Save Changes
309
+ </button>
310
+ </div>
311
+ </div>
312
+ </div>
313
+
314
+ <script>
315
+ document.addEventListener('DOMContentLoaded', function() {
316
+ // Initialize variables
317
+ let trainings = [];
318
+ let currentEditId = null;
319
+
320
+ // Load data from localStorage
321
+ loadData();
322
+
323
+ // Calculate costs when inputs change
324
+ const calculateInputs = ['participants', 'days', 'base-cost', 'cost-per-participant', 'cost-per-day'];
325
+ calculateInputs.forEach(inputId => {
326
+ document.getElementById(inputId).addEventListener('input', calculateCosts);
327
+ });
328
+
329
+ // Add additional cost row
330
+ document.getElementById('add-cost').addEventListener('click', function() {
331
+ addAdditionalCostRow();
332
+ });
333
+
334
+ // Remove additional cost row (delegated event)
335
+ document.getElementById('additional-costs-container').addEventListener('click', function(e) {
336
+ if (e.target.classList.contains('remove-cost') || e.target.closest('.remove-cost')) {
337
+ const costItem = e.target.closest('.additional-cost-item');
338
+ if (costItem && document.querySelectorAll('.additional-cost-item').length > 1) {
339
+ costItem.remove();
340
+ calculateCosts();
341
+ }
342
+ }
343
+ });
344
+
345
+ // Save training program
346
+ document.getElementById('save-training').addEventListener('click', saveTraining);
347
+
348
+ // Handle photo preview
349
+ document.getElementById('training-photo').addEventListener('change', function(e) {
350
+ const file = e.target.files[0];
351
+ if (file) {
352
+ const reader = new FileReader();
353
+ reader.onload = function(event) {
354
+ const preview = document.getElementById('photo-preview');
355
+ preview.src = event.target.result;
356
+ preview.style.display = 'block';
357
+ };
358
+ reader.readAsDataURL(file);
359
+ }
360
+ });
361
+
362
+ // Handle company logo upload
363
+ document.getElementById('logo-upload').addEventListener('change', function(e) {
364
+ const file = e.target.files[0];
365
+ if (file) {
366
+ const reader = new FileReader();
367
+ reader.onload = function(event) {
368
+ const logo = document.getElementById('company-logo');
369
+ logo.src = event.target.result;
370
+ logo.classList.remove('hidden');
371
+ };
372
+ reader.readAsDataURL(file);
373
+ }
374
+ });
375
+
376
+ // Filter trainings
377
+ document.getElementById('filter-status').addEventListener('change', filterTrainings);
378
+ document.getElementById('filter-date').addEventListener('change', filterTrainings);
379
+ document.getElementById('search-title').addEventListener('input', filterTrainings);
380
+
381
+ // Toggle collapse all
382
+ document.getElementById('toggle-collapse').addEventListener('change', function(e) {
383
+ const items = document.querySelectorAll('.training-item');
384
+ items.forEach(item => {
385
+ if (item.id !== 'empty-message') {
386
+ item.classList.toggle('collapsed', e.target.checked);
387
+ }
388
+ });
389
+ });
390
+
391
+ // Data management
392
+ document.getElementById('export-data').addEventListener('click', exportData);
393
+ document.getElementById('import-data').addEventListener('change', importData);
394
+ document.getElementById('clear-data').addEventListener('click', clearData);
395
+
396
+ // Edit modal
397
+ document.getElementById('close-edit-modal').addEventListener('click', closeEditModal);
398
+ document.getElementById('cancel-edit').addEventListener('click', closeEditModal);
399
+ document.getElementById('save-edit').addEventListener('click', saveEditedTraining);
400
+
401
+ // Functions
402
+ function calculateCosts() {
403
+ const participants = parseInt(document.getElementById('participants').value) || 0;
404
+ const days = parseInt(document.getElementById('days').value) || 0;
405
+ const baseCost = parseFloat(document.getElementById('base-cost').value) || 0;
406
+ const costPerParticipant = parseFloat(document.getElementById('cost-per-participant').value) || 0;
407
+ const costPerDay = parseFloat(document.getElementById('cost-per-day').value) || 0;
408
+
409
+ // Calculate additional costs
410
+ let additionalCosts = 0;
411
+ document.querySelectorAll('.additional-cost-item').forEach(item => {
412
+ const amount = parseFloat(item.querySelector('.cost-amount').value) || 0;
413
+ additionalCosts += amount;
414
+ });
415
+
416
+ // Calculate totals
417
+ const participantsCost = participants * costPerParticipant;
418
+ const daysCost = days * costPerDay;
419
+ const totalCost = baseCost + participantsCost + daysCost + additionalCosts;
420
+ const costPerParticipantTotal = participants > 0 ? totalCost / participants : 0;
421
+
422
+ // Update summary
423
+ document.getElementById('summary-base-cost').textContent = formatCurrency(baseCost);
424
+ document.getElementById('summary-participants-cost').textContent = formatCurrency(participantsCost);
425
+ document.getElementById('summary-days-cost').textContent = formatCurrency(daysCost);
426
+ document.getElementById('summary-additional-costs').textContent = formatCurrency(additionalCosts);
427
+ document.getElementById('summary-total-cost').textContent = formatCurrency(totalCost);
428
+ document.getElementById('summary-cost-per-participant').textContent = formatCurrency(costPerParticipantTotal);
429
+ }
430
+
431
+ function formatCurrency(amount) {
432
+ return '₱' + amount.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
433
+ }
434
+
435
+ function addAdditionalCostRow(type = '', amount = '') {
436
+ const container = document.getElementById('additional-costs-container');
437
+ const div = document.createElement('div');
438
+ div.className = 'additional-cost-item grid grid-cols-1 md:grid-cols-3 gap-3 mb-3';
439
+ div.innerHTML = `
440
+ <div>
441
+ <label class="block text-sm font-medium text-green-700">Cost Type</label>
442
+ <input type="text" class="cost-type mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" placeholder="e.g., Materials, Venue" value="${type}">
443
+ </div>
444
+ <div>
445
+ <label class="block text-sm font-medium text-green-700">Amount (₱)</label>
446
+ <input type="number" min="0" step="0.01" class="cost-amount mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${amount}">
447
+ </div>
448
+ <div class="flex items-end">
449
+ <button type="button" class="remove-cost bg-red-500 hover:bg-red-600 text-white py-2 px-3 rounded-md text-sm">
450
+ <i class="fas fa-trash mr-1"></i> Remove
451
+ </button>
452
+ </div>
453
+ `;
454
+ container.appendChild(div);
455
+ }
456
+
457
+ function saveTraining() {
458
+ // Validate required fields
459
+ const title = document.getElementById('training-title').value.trim();
460
+ const description = document.getElementById('training-description').value.trim();
461
+ const startDate = document.getElementById('start-date').value;
462
+ const endDate = document.getElementById('end-date').value;
463
+ const participants = parseInt(document.getElementById('participants').value) || 0;
464
+ const days = parseInt(document.getElementById('days').value) || 0;
465
+ const baseCost = parseFloat(document.getElementById('base-cost').value) || 0;
466
+ const costPerParticipant = parseFloat(document.getElementById('cost-per-participant').value) || 0;
467
+ const costPerDay = parseFloat(document.getElementById('cost-per-day').value) || 0;
468
+ const status = document.getElementById('status').value;
469
+
470
+ if (!title || !description || !startDate || !endDate || participants <= 0 || days <= 0) {
471
+ alert('Please fill in all required fields with valid values.');
472
+ return;
473
+ }
474
+
475
+ // Get additional costs
476
+ const additionalCosts = [];
477
+ document.querySelectorAll('.additional-cost-item').forEach(item => {
478
+ const type = item.querySelector('.cost-type').value.trim();
479
+ const amount = parseFloat(item.querySelector('.cost-amount').value) || 0;
480
+ if (type || amount > 0) {
481
+ additionalCosts.push({ type, amount });
482
+ }
483
+ });
484
+
485
+ // Get photo if available
486
+ const photoInput = document.getElementById('training-photo');
487
+ let photoBase64 = '';
488
+ if (photoInput.files.length > 0) {
489
+ const file = photoInput.files[0];
490
+ const reader = new FileReader();
491
+ reader.onload = function(event) {
492
+ photoBase64 = event.target.result;
493
+ completeSave(title, description, startDate, endDate, participants, days, baseCost,
494
+ costPerParticipant, costPerDay, additionalCosts, status, photoBase64);
495
+ };
496
+ reader.readAsDataURL(file);
497
+ } else {
498
+ completeSave(title, description, startDate, endDate, participants, days, baseCost,
499
+ costPerParticipant, costPerDay, additionalCosts, status, photoBase64);
500
+ }
501
+ }
502
+
503
+ function completeSave(title, description, startDate, endDate, participants, days, baseCost,
504
+ costPerParticipant, costPerDay, additionalCosts, status, photoBase64) {
505
+ // Calculate totals
506
+ const participantsCost = participants * costPerParticipant;
507
+ const daysCost = days * costPerDay;
508
+ const additionalCostsTotal = additionalCosts.reduce((sum, cost) => sum + cost.amount, 0);
509
+ const totalCost = baseCost + participantsCost + daysCost + additionalCostsTotal;
510
+ const costPerParticipantTotal = participants > 0 ? totalCost / participants : 0;
511
+
512
+ // Create training object
513
+ const training = {
514
+ id: Date.now().toString(),
515
+ title,
516
+ description,
517
+ startDate,
518
+ endDate,
519
+ participants,
520
+ days,
521
+ baseCost,
522
+ costPerParticipant,
523
+ costPerDay,
524
+ additionalCosts,
525
+ status,
526
+ photo: photoBase64,
527
+ participantsCost,
528
+ daysCost,
529
+ additionalCostsTotal,
530
+ totalCost,
531
+ costPerParticipantTotal,
532
+ createdAt: new Date().toISOString()
533
+ };
534
+
535
+ // Add to array and save
536
+ trainings.push(training);
537
+ saveData();
538
+ renderTrainings();
539
+ resetForm();
540
+ }
541
+
542
+ function resetForm() {
543
+ document.getElementById('training-title').value = '';
544
+ document.getElementById('training-description').value = '';
545
+ document.getElementById('start-date').value = '';
546
+ document.getElementById('end-date').value = '';
547
+ document.getElementById('participants').value = '';
548
+ document.getElementById('days').value = '';
549
+ document.getElementById('base-cost').value = '';
550
+ document.getElementById('cost-per-participant').value = '';
551
+ document.getElementById('cost-per-day').value = '';
552
+ document.getElementById('status').value = 'pending';
553
+ document.getElementById('training-photo').value = '';
554
+ document.getElementById('photo-preview').style.display = 'none';
555
+
556
+ // Reset additional costs (keep one empty row)
557
+ const container = document.getElementById('additional-costs-container');
558
+ container.innerHTML = '';
559
+ addAdditionalCostRow();
560
+
561
+ // Reset calculations
562
+ document.getElementById('summary-base-cost').textContent = formatCurrency(0);
563
+ document.getElementById('summary-participants-cost').textContent = formatCurrency(0);
564
+ document.getElementById('summary-days-cost').textContent = formatCurrency(0);
565
+ document.getElementById('summary-additional-costs').textContent = formatCurrency(0);
566
+ document.getElementById('summary-total-cost').textContent = formatCurrency(0);
567
+ document.getElementById('summary-cost-per-participant').textContent = formatCurrency(0);
568
+ }
569
+
570
+ function renderTrainings(filteredTrainings = null) {
571
+ const container = document.getElementById('training-list');
572
+ const trainingsToRender = filteredTrainings || trainings;
573
+
574
+ if (trainingsToRender.length === 0) {
575
+ container.innerHTML = `
576
+ <div class="text-center py-8 text-gray-500" id="empty-message">
577
+ <i class="fas fa-clipboard-list text-4xl mb-2"></i>
578
+ <p>No training programs found.</p>
579
+ <p class="text-sm">Add your first training program using the form above.</p>
580
+ </div>
581
+ `;
582
+ return;
583
+ }
584
+
585
+ container.innerHTML = '';
586
+
587
+ trainingsToRender.forEach(training => {
588
+ const startDate = new Date(training.startDate);
589
+ const endDate = new Date(training.endDate);
590
+ const dateOptions = { year: 'numeric', month: 'short', day: 'numeric' };
591
+
592
+ const item = document.createElement('div');
593
+ item.className = 'training-item collapsed bg-green-50 rounded-lg overflow-hidden shadow';
594
+ item.id = training.id;
595
+ item.innerHTML = `
596
+ <div class="p-4 cursor-pointer" onclick="toggleTrainingDetails('${training.id}')">
597
+ <div class="flex justify-between items-center">
598
+ <div>
599
+ <h3 class="font-semibold text-green-800">${training.title}</h3>
600
+ <p class="text-sm text-green-600">${startDate.toLocaleDateString(undefined, dateOptions)} - ${endDate.toLocaleDateString(undefined, dateOptions)}</p>
601
+ </div>
602
+ <div class="flex items-center space-x-2">
603
+ <span class="px-2 py-1 text-xs rounded-full ${getStatusClass(training.status)}">
604
+ ${training.status.charAt(0).toUpperCase() + training.status.slice(1)}
605
+ </span>
606
+ <span class="font-bold text-green-800">${formatCurrency(training.totalCost)}</span>
607
+ <i class="fas fa-chevron-down text-green-600 transition-transform"></i>
608
+ </div>
609
+ </div>
610
+ </div>
611
+ <div class="px-4 pb-4 hidden">
612
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
613
+ <div>
614
+ <h4 class="font-medium text-green-700 mb-2">Details</h4>
615
+ <p class="text-sm text-gray-700 mb-3">${training.description}</p>
616
+ <div class="grid grid-cols-2 gap-2 text-sm">
617
+ <div>
618
+ <span class="text-green-700">Participants:</span> ${training.participants}
619
+ </div>
620
+ <div>
621
+ <span class="text-green-700">Days:</span> ${training.days}
622
+ </div>
623
+ <div>
624
+ <span class="text-green-700">Base Cost:</span> ${formatCurrency(training.baseCost)}
625
+ </div>
626
+ <div>
627
+ <span class="text-green-700">Per Participant:</span> ${formatCurrency(training.costPerParticipant)}
628
+ </div>
629
+ <div>
630
+ <span class="text-green-700">Per Day:</span> ${formatCurrency(training.costPerDay)}
631
+ </div>
632
+ <div>
633
+ <span class="text-green-700">Cost/Participant:</span> ${formatCurrency(training.costPerParticipantTotal)}
634
+ </div>
635
+ </div>
636
+ </div>
637
+ <div>
638
+ <h4 class="font-medium text-green-700 mb-2">Additional Costs</h4>
639
+ ${training.additionalCosts.length > 0 ?
640
+ training.additionalCosts.map(cost => `
641
+ <div class="flex justify-between text-sm mb-1">
642
+ <span>${cost.type || 'Unspecified'}:</span>
643
+ <span>${formatCurrency(cost.amount)}</span>
644
+ </div>
645
+ `).join('') :
646
+ '<p class="text-sm text-gray-500">No additional costs</p>'}
647
+
648
+ <div class="mt-4 border-t pt-2">
649
+ <div class="flex justify-between font-semibold">
650
+ <span>Total Cost:</span>
651
+ <span>${formatCurrency(training.totalCost)}</span>
652
+ </div>
653
+ </div>
654
+ </div>
655
+ </div>
656
+
657
+ ${training.photo ? `
658
+ <div class="mt-4">
659
+ <h4 class="font-medium text-green-700 mb-2">Training Photo</h4>
660
+ <img src="${training.photo}" alt="Training photo" class="w-full h-auto rounded-lg">
661
+ </div>
662
+ ` : ''}
663
+
664
+ <div class="mt-4 flex justify-end space-x-2">
665
+ <button onclick="editTraining('${training.id}')" class="bg-blue-500 hover:bg-blue-600 text-white py-1 px-3 rounded text-sm">
666
+ <i class="fas fa-edit mr-1"></i> Edit
667
+ </button>
668
+ <button onclick="deleteTraining('${training.id}')" class="bg-red-500 hover:bg-red-600 text-white py-1 px-3 rounded text-sm">
669
+ <i class="fas fa-trash mr-1"></i> Delete
670
+ </button>
671
+ </div>
672
+ </div>
673
+ `;
674
+ container.appendChild(item);
675
+ });
676
+ }
677
+
678
+ function getStatusClass(status) {
679
+ switch(status) {
680
+ case 'pending': return 'bg-yellow-100 text-yellow-800';
681
+ case 'ongoing': return 'bg-blue-100 text-blue-800';
682
+ case 'completed': return 'bg-green-100 text-green-800';
683
+ case 'cancelled': return 'bg-red-100 text-red-800';
684
+ default: return 'bg-gray-100 text-gray-800';
685
+ }
686
+ }
687
+
688
+ function toggleTrainingDetails(id) {
689
+ const item = document.getElementById(id);
690
+ if (item) {
691
+ const details = item.querySelector('.hidden');
692
+ const icon = item.querySelector('.fa-chevron-down');
693
+
694
+ details.classList.toggle('hidden');
695
+ icon.classList.toggle('rotate-180');
696
+ }
697
+ }
698
+
699
+ function editTraining(id) {
700
+ const training = trainings.find(t => t.id === id);
701
+ if (!training) return;
702
+
703
+ currentEditId = id;
704
+
705
+ // Create edit form
706
+ let additionalCostsHTML = '';
707
+ if (training.additionalCosts.length > 0) {
708
+ additionalCostsHTML = training.additionalCosts.map(cost => `
709
+ <div class="additional-cost-item grid grid-cols-1 md:grid-cols-3 gap-3 mb-3">
710
+ <div>
711
+ <label class="block text-sm font-medium text-green-700">Cost Type</label>
712
+ <input type="text" class="cost-type mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${cost.type || ''}">
713
+ </div>
714
+ <div>
715
+ <label class="block text-sm font-medium text-green-700">Amount (₱)</label>
716
+ <input type="number" min="0" step="0.01" class="cost-amount mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${cost.amount || ''}">
717
+ </div>
718
+ <div class="flex items-end">
719
+ <button type="button" class="remove-cost bg-red-500 hover:bg-red-600 text-white py-2 px-3 rounded-md text-sm">
720
+ <i class="fas fa-trash mr-1"></i> Remove
721
+ </button>
722
+ </div>
723
+ </div>
724
+ `).join('');
725
+ } else {
726
+ additionalCostsHTML = `
727
+ <div class="additional-cost-item grid grid-cols-1 md:grid-cols-3 gap-3 mb-3">
728
+ <div>
729
+ <label class="block text-sm font-medium text-green-700">Cost Type</label>
730
+ <input type="text" class="cost-type mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
731
+ </div>
732
+ <div>
733
+ <label class="block text-sm font-medium text-green-700">Amount (₱)</label>
734
+ <input type="number" min="0" step="0.01" class="cost-amount mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
735
+ </div>
736
+ <div class="flex items-end">
737
+ <button type="button" class="remove-cost bg-red-500 hover:bg-red-600 text-white py-2 px-3 rounded-md text-sm">
738
+ <i class="fas fa-trash mr-1"></i> Remove
739
+ </button>
740
+ </div>
741
+ </div>
742
+ `;
743
+ }
744
+
745
+ const editForm = `
746
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
747
+ <div>
748
+ <label class="block text-sm font-medium text-green-700">Training Title*</label>
749
+ <input type="text" id="edit-title" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.title}">
750
+ </div>
751
+ <div>
752
+ <label class="block text-sm font-medium text-green-700">Status*</label>
753
+ <select id="edit-status" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
754
+ <option value="pending" ${training.status === 'pending' ? 'selected' : ''}>Pending</option>
755
+ <option value="ongoing" ${training.status === 'ongoing' ? 'selected' : ''}>Ongoing</option>
756
+ <option value="completed" ${training.status === 'completed' ? 'selected' : ''}>Completed</option>
757
+ <option value="cancelled" ${training.status === 'cancelled' ? 'selected' : ''}>Cancelled</option>
758
+ </select>
759
+ </div>
760
+ <div>
761
+ <label class="block text-sm font-medium text-green-700">Start Date*</label>
762
+ <input type="date" id="edit-start-date" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.startDate}">
763
+ </div>
764
+ <div>
765
+ <label class="block text-sm font-medium text-green-700">End Date*</label>
766
+ <input type="date" id="edit-end-date" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.endDate}">
767
+ </div>
768
+ <div>
769
+ <label class="block text-sm font-medium text-green-700">Participants*</label>
770
+ <input type="number" id="edit-participants" min="1" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.participants}">
771
+ </div>
772
+ <div>
773
+ <label class="block text-sm font-medium text-green-700">Days*</label>
774
+ <input type="number" id="edit-days" min="1" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.days}">
775
+ </div>
776
+ <div>
777
+ <label class="block text-sm font-medium text-green-700">Base Cost (₱)*</label>
778
+ <input type="number" id="edit-base-cost" min="0" step="0.01" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.baseCost}">
779
+ </div>
780
+ <div>
781
+ <label class="block text-sm font-medium text-green-700">Cost per Participant (₱)*</label>
782
+ <input type="number" id="edit-cost-per-participant" min="0" step="0.01" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.costPerParticipant}">
783
+ </div>
784
+ <div>
785
+ <label class="block text-sm font-medium text-green-700">Cost per Day (₱)*</label>
786
+ <input type="number" id="edit-cost-per-day" min="0" step="0.01" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.costPerDay}">
787
+ </div>
788
+ <div class="md:col-span-2">
789
+ <label class="block text-sm font-medium text-green-700">Description*</label>
790
+ <textarea id="edit-description" rows="3" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">${training.description}</textarea>
791
+ </div>
792
+ <div class="md:col-span-2">
793
+ <label class="block text-sm font-medium text-green-700">Training Photo</label>
794
+ <input type="file" id="edit-photo" accept="image/*" class="mt-1 block w-full text-sm text-green-700 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-green-500 file:text-white hover:file:bg-green-600">
795
+ ${training.photo ? `<img src="${training.photo}" alt="Current photo" class="mt-2 h-32 object-contain rounded-lg border">` : ''}
796
+ </div>
797
+ </div>
798
+
799
+ <div class="mt-4">
800
+ <h4 class="text-lg font-medium text-green-800 mb-3">Additional Costs</h4>
801
+ <div id="edit-additional-costs">
802
+ ${additionalCostsHTML}
803
+ </div>
804
+ <button type="button" id="edit-add-cost" class="mt-2 bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded-md text-sm">
805
+ <i class="fas fa-plus mr-1"></i> Add Another Cost
806
+ </button>
807
+ </div>
808
+ `;
809
+
810
+ document.getElementById('edit-form-content').innerHTML = editForm;
811
+
812
+ // Add event for new cost button in edit form
813
+ document.getElementById('edit-add-cost').addEventListener('click', function() {
814
+ const container = document.getElementById('edit-additional-costs');
815
+ const div = document.createElement('div');
816
+ div.className = 'additional-cost-item grid grid-cols-1 md:grid-cols-3 gap-3 mb-3';
817
+ div.innerHTML = `
818
+ <div>
819
+ <label class="block text-sm font-medium text-green-700">Cost Type</label>
820
+ <input type="text" class="cost-type mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" placeholder="e.g., Materials, Venue">
821
+ </div>
822
+ <div>
823
+ <label class="block text-sm font-medium text-green-700">Amount (₱)</label>
824
+ <input type="number" min="0" step="0.01" class="cost-amount mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
825
+ </div>
826
+ <div class="flex items-end">
827
+ <button type="button" class="remove-cost bg-red-500 hover:bg-red-600 text-white py-2 px-3 rounded-md text-sm">
828
+ <i class="fas fa-trash mr-1"></i> Remove
829
+ </button>
830
+ </div>
831
+ `;
832
+ container.appendChild(div);
833
+ });
834
+
835
+ // Remove additional cost row in edit form
836
+ document.getElementById('edit-additional-costs').addEventListener('click', function(e) {
837
+ if (e.target.classList.contains('remove-cost') || e.target.closest('.remove-cost')) {
838
+ const costItem = e.target.closest('.additional-cost-item');
839
+ if (costItem) {
840
+ costItem.remove();
841
+ }
842
+ }
843
+ });
844
+
845
+ // Show modal
846
+ document.getElementById('edit-modal').classList.remove('hidden');
847
+ }
848
+
849
+ function saveEditedTraining() {
850
+ if (!currentEditId) return;
851
+
852
+ const trainingIndex = trainings.findIndex(t => t.id === currentEditId);
853
+ if (trainingIndex === -1) return;
854
+
855
+ // Validate required fields
856
+ const title = document.getElementById('edit-title').value.trim();
857
+ const description = document.getElementById('edit-description').value.trim();
858
+ const startDate = document.getElementById('edit-start-date').value;
859
+ const endDate = document.getElementById('edit-end-date').value;
860
+ const participants = parseInt(document.getElementById('edit-participants').value) || 0;
861
+ const days = parseInt(document.getElementById('edit-days').value) || 0;
862
+ const baseCost = parseFloat(document.getElementById('edit-base-cost').value) || 0;
863
+ const costPerParticipant = parseFloat(document.getElementById('edit-cost-per-participant').value) || 0;
864
+ const costPerDay = parseFloat(document.getElementById('edit-cost-per-day').value) || 0;
865
+ const status = document.getElementById('edit-status').value;
866
+
867
+ if (!title || !description || !startDate || !endDate || participants <= 0 || days <= 0) {
868
+ alert('Please fill in all required fields with valid values.');
869
+ return;
870
+ }
871
+
872
+ // Get additional costs
873
+ const additionalCosts = [];
874
+ document.querySelectorAll('#edit-additional-costs .additional-cost-item').forEach(item => {
875
+ const type = item.querySelector('.cost-type').value.trim();
876
+ const amount = parseFloat(item.querySelector('.cost-amount').value) || 0;
877
+ if (type || amount > 0) {
878
+ additionalCosts.push({ type, amount });
879
+ }
880
+ });
881
+
882
+ // Get photo if available
883
+ const photoInput = document.getElementById('edit-photo');
884
+ let photoBase64 = trainings[trainingIndex].photo;
885
+ if (photoInput.files.length > 0) {
886
+ const file = photoInput.files[0];
887
+ const reader = new FileReader();
888
+ reader.onload = function(event) {
889
+ photoBase64 = event.target.result;
890
+ completeEdit(title, description, startDate, endDate, participants, days, baseCost,
891
+ costPerParticipant, costPerDay, additionalCosts, status, photoBase64, trainingIndex);
892
+ };
893
+ reader.readAsDataURL(file);
894
+ } else {
895
+ completeEdit(title, description, startDate, endDate, participants, days, baseCost,
896
+ costPerParticipant, costPerDay, additionalCosts, status, photoBase64, trainingIndex);
897
+ }
898
+ }
899
+
900
+ function completeEdit(title, description, startDate, endDate, participants, days, baseCost,
901
+ costPerParticipant, costPerDay, additionalCosts, status, photoBase64, trainingIndex) {
902
+ // Calculate totals
903
+ const participantsCost = participants * costPerParticipant;
904
+ const daysCost = days * costPerDay;
905
+ const additionalCostsTotal = additionalCosts.reduce((sum, cost) => sum + cost.amount, 0);
906
+ const totalCost = baseCost + participantsCost + daysCost + additionalCostsTotal;
907
+ const costPerParticipantTotal = participants > 0 ? totalCost / participants : 0;
908
+
909
+ // Update training object
910
+ trainings[trainingIndex] = {
911
+ ...trainings[trainingIndex],
912
+ title,
913
+ description,
914
+ startDate,
915
+ endDate,
916
+ participants,
917
+ days,
918
+ baseCost,
919
+ costPerParticipant,
920
+ costPerDay,
921
+ additionalCosts,
922
+ status,
923
+ photo: photoBase64,
924
+ participantsCost,
925
+ daysCost,
926
+ additionalCostsTotal,
927
+ totalCost,
928
+ costPerParticipantTotal
929
+ };
930
+
931
+ saveData();
932
+ renderTrainings();
933
+ closeEditModal();
934
+ }
935
+
936
+ function closeEditModal() {
937
+ document.getElementById('edit-modal').classList.add('hidden');
938
+ currentEditId = null;
939
+ }
940
+
941
+ function deleteTraining(id) {
942
+ if (confirm('Are you sure you want to delete this training program?')) {
943
+ trainings = trainings.filter(t => t.id !== id);
944
+ saveData();
945
+ renderTrainings();
946
+ }
947
+ }
948
+
949
+ function filterTrainings() {
950
+ const statusFilter = document.getElementById('filter-status').value;
951
+ const dateFilter = document.getElementById('filter-date').value;
952
+ const searchTerm = document.getElementById('search-title').value.toLowerCase();
953
+
954
+ let filtered = [...trainings];
955
+
956
+ // Apply status filter
957
+ if (statusFilter !== 'all') {
958
+ filtered = filtered.filter(t => t.status === statusFilter);
959
+ }
960
+
961
+ // Apply date filter
962
+ if (dateFilter !== 'all') {
963
+ const now = new Date();
964
+ const currentMonth = now.getMonth();
965
+ const currentYear = now.getFullYear();
966
+
967
+ filtered = filtered.filter(t => {
968
+ const startDate = new Date(t.startDate);
969
+ const startMonth = startDate.getMonth();
970
+ const startYear = startDate.getFullYear();
971
+
972
+ switch(dateFilter) {
973
+ case 'this-month':
974
+ return startMonth === currentMonth && startYear === currentYear;
975
+ case 'last-month':
976
+ const lastMonth = currentMonth === 0 ? 11 : currentMonth - 1;
977
+ const lastMonthYear = currentMonth === 0 ? currentYear - 1 : currentYear;
978
+ return startMonth === lastMonth && startYear === lastMonthYear;
979
+ case 'this-year':
980
+ return startYear === currentYear;
981
+ case 'last-year':
982
+ return startYear === currentYear - 1;
983
+ default:
984
+ return true;
985
+ }
986
+ });
987
+ }
988
+
989
+ // Apply search filter
990
+ if (searchTerm) {
991
+ filtered = filtered.filter(t => t.title.toLowerCase().includes(searchTerm));
992
+ }
993
+
994
+ renderTrainings(filtered);
995
+ }
996
+
997
+ function saveData() {
998
+ localStorage.setItem('safetyTrainingData', JSON.stringify({
999
+ trainings,
1000
+ logo: document.getElementById('company-logo').src || ''
1001
+ }));
1002
+ }
1003
+
1004
+ function loadData() {
1005
+ const savedData = localStorage.getItem('safetyTrainingData');
1006
+ if (savedData) {
1007
+ try {
1008
+ const data = JSON.parse(savedData);
1009
+ trainings = data.trainings || [];
1010
+
1011
+ if (data.logo) {
1012
+ const logo = document.getElementById('company-logo');
1013
+ logo.src = data.logo;
1014
+ logo.classList.remove('hidden');
1015
+ }
1016
+
1017
+ renderTrainings();
1018
+ } catch (e) {
1019
+ console.error('Error loading saved data:', e);
1020
+ }
1021
+ }
1022
+ }
1023
+
1024
+ function exportData() {
1025
+ const data = {
1026
+ trainings,
1027
+ logo: document.getElementById('company-logo').src || '',
1028
+ exportedAt: new Date().toISOString()
1029
+ };
1030
+
1031
+ const dataStr = JSON.stringify(data, null, 2);
1032
+ const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
1033
+
1034
+ const exportName = 'safety-training-data_' + new Date().toISOString().slice(0, 10) + '.json';
1035
+
1036
+ const linkElement = document.createElement('a');
1037
+ linkElement.setAttribute('href', dataUri);
1038
+ linkElement.setAttribute('download', exportName);
1039
+ linkElement.click();
1040
+ }
1041
+
1042
+ function importData(e) {
1043
+ const file = e.target.files[0];
1044
+ if (!file) return;
1045
+
1046
+ if (confirm('Importing data will replace all current data. Continue?')) {
1047
+ const reader = new FileReader();
1048
+ reader.onload = function(event) {
1049
+ try {
1050
+ const data = JSON.parse(event.target.result);
1051
+
1052
+ if (data.trainings) {
1053
+ trainings = data.trainings;
1054
+
1055
+ if (data.logo) {
1056
+ const logo = document.getElementById('company-logo');
1057
+ logo.src = data.logo;
1058
+ logo.classList.remove('hidden');
1059
+ }
1060
+
1061
+ saveData();
1062
+ renderTrainings();
1063
+ alert('Data imported successfully!');
1064
+ } else {
1065
+ alert('Invalid data format: missing trainings array');
1066
+ }
1067
+ } catch (e) {
1068
+ alert('Error parsing file: ' + e.message);
1069
+ }
1070
+ };
1071
+ reader.readAsText(file);
1072
+ }
1073
+
1074
+ // Reset input to allow importing the same file again
1075
+ e.target.value = '';
1076
+ }
1077
+
1078
+ function clearData() {
1079
+ if (confirm('Are you sure you want to clear all data? This cannot be undone.')) {
1080
+ trainings = [];
1081
+ localStorage.removeItem('safetyTrainingData');
1082
+ document.getElementById('company-logo').src = '';
1083
+ document.getElementById('company-logo').classList.add('hidden');
1084
+ renderTrainings();
1085
+ resetForm();
1086
+ }
1087
+ }
1088
+ });
1089
+
1090
+ // Global functions needed for event handlers in dynamically created elements
1091
+ window.toggleTrainingDetails = function(id) {
1092
+ const item = document.getElementById(id);
1093
+ if (item) {
1094
+ const details = item.querySelector('.hidden');
1095
+ const icon = item.querySelector('.fa-chevron-down');
1096
+
1097
+ details.classList.toggle('hidden');
1098
+ icon.classList.toggle('rotate-180');
1099
+ }
1100
+ };
1101
+
1102
+ window.editTraining = function(id) {
1103
+ const event = new Event('DOMContentLoaded');
1104
+ document.dispatchEvent(event);
1105
+
1106
+ // Wait for the DOM to be ready
1107
+ setTimeout(() => {
1108
+ document.querySelector(`#training-list #${id} .fa-chevron-down`).classList.remove('rotate-180');
1109
+ document.querySelector(`#training-list #${id} .hidden`).classList.add('hidden');
1110
+
1111
+ const training = JSON.parse(localStorage.getItem('safetyTrainingData')).trainings.find(t => t.id === id);
1112
+ if (!training) return;
1113
+
1114
+ currentEditId = id;
1115
+
1116
+ // Create edit form
1117
+ let additionalCostsHTML = '';
1118
+ if (training.additionalCosts.length > 0) {
1119
+ additionalCostsHTML = training.additionalCosts.map(cost => `
1120
+ <div class="additional-cost-item grid grid-cols-1 md:grid-cols-3 gap-3 mb-3">
1121
+ <div>
1122
+ <label class="block text-sm font-medium text-green-700">Cost Type</label>
1123
+ <input type="text" class="cost-type mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${cost.type || ''}">
1124
+ </div>
1125
+ <div>
1126
+ <label class="block text-sm font-medium text-green-700">Amount (₱)</label>
1127
+ <input type="number" min="0" step="0.01" class="cost-amount mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${cost.amount || ''}">
1128
+ </div>
1129
+ <div class="flex items-end">
1130
+ <button type="button" class="remove-cost bg-red-500 hover:bg-red-600 text-white py-2 px-3 rounded-md text-sm">
1131
+ <i class="fas fa-trash mr-1"></i> Remove
1132
+ </button>
1133
+ </div>
1134
+ </div>
1135
+ `).join('');
1136
+ } else {
1137
+ additionalCostsHTML = `
1138
+ <div class="additional-cost-item grid grid-cols-1 md:grid-cols-3 gap-3 mb-3">
1139
+ <div>
1140
+ <label class="block text-sm font-medium text-green-700">Cost Type</label>
1141
+ <input type="text" class="cost-type mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
1142
+ </div>
1143
+ <div>
1144
+ <label class="block text-sm font-medium text-green-700">Amount (₱)</label>
1145
+ <input type="number" min="0" step="0.01" class="cost-amount mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
1146
+ </div>
1147
+ <div class="flex items-end">
1148
+ <button type="button" class="remove-cost bg-red-500 hover:bg-red-600 text-white py-2 px-3 rounded-md text-sm">
1149
+ <i class="fas fa-trash mr-1"></i> Remove
1150
+ </button>
1151
+ </div>
1152
+ </div>
1153
+ `;
1154
+ }
1155
+
1156
+ const editForm = `
1157
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
1158
+ <div>
1159
+ <label class="block text-sm font-medium text-green-700">Training Title*</label>
1160
+ <input type="text" id="edit-title" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.title}">
1161
+ </div>
1162
+ <div>
1163
+ <label class="block text-sm font-medium text-green-700">Status*</label>
1164
+ <select id="edit-status" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
1165
+ <option value="pending" ${training.status === 'pending' ? 'selected' : ''}>Pending</option>
1166
+ <option value="ongoing" ${training.status === 'ongoing' ? 'selected' : ''}>Ongoing</option>
1167
+ <option value="completed" ${training.status === 'completed' ? 'selected' : ''}>Completed</option>
1168
+ <option value="cancelled" ${training.status === 'cancelled' ? 'selected' : ''}>Cancelled</option>
1169
+ </select>
1170
+ </div>
1171
+ <div>
1172
+ <label class="block text-sm font-medium text-green-700">Start Date*</label>
1173
+ <input type="date" id="edit-start-date" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.startDate}">
1174
+ </div>
1175
+ <div>
1176
+ <label class="block text-sm font-medium text-green-700">End Date*</label>
1177
+ <input type="date" id="edit-end-date" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.endDate}">
1178
+ </div>
1179
+ <div>
1180
+ <label class="block text-sm font-medium text-green-700">Participants*</label>
1181
+ <input type="number" id="edit-participants" min="1" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.participants}">
1182
+ </div>
1183
+ <div>
1184
+ <label class="block text-sm font-medium text-green-700">Days*</label>
1185
+ <input type="number" id="edit-days" min="1" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.days}">
1186
+ </div>
1187
+ <div>
1188
+ <label class="block text-sm font-medium text-green-700">Base Cost (₱)*</label>
1189
+ <input type="number" id="edit-base-cost" min="0" step="0.01" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.baseCost}">
1190
+ </div>
1191
+ <div>
1192
+ <label class="block text-sm font-medium text-green-700">Cost per Participant (₱)*</label>
1193
+ <input type="number" id="edit-cost-per-participant" min="0" step="0.01" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.costPerParticipant}">
1194
+ </div>
1195
+ <div>
1196
+ <label class="block text-sm font-medium text-green-700">Cost per Day (₱)*</label>
1197
+ <input type="number" id="edit-cost-per-day" min="0" step="0.01" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" value="${training.costPerDay}">
1198
+ </div>
1199
+ <div class="md:col-span-2">
1200
+ <label class="block text-sm font-medium text-green-700">Description*</label>
1201
+ <textarea id="edit-description" rows="3" class="mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">${training.description}</textarea>
1202
+ </div>
1203
+ <div class="md:col-span-2">
1204
+ <label class="block text-sm font-medium text-green-700">Training Photo</label>
1205
+ <input type="file" id="edit-photo" accept="image/*" class="mt-1 block w-full text-sm text-green-700 file:mr-4 file:py-2 file:px-4 file:rounded-md file:border-0 file:text-sm file:font-semibold file:bg-green-500 file:text-white hover:file:bg-green-600">
1206
+ ${training.photo ? `<img src="${training.photo}" alt="Current photo" class="mt-2 h-32 object-contain rounded-lg border">` : ''}
1207
+ </div>
1208
+ </div>
1209
+
1210
+ <div class="mt-4">
1211
+ <h4 class="text-lg font-medium text-green-800 mb-3">Additional Costs</h4>
1212
+ <div id="edit-additional-costs">
1213
+ ${additionalCostsHTML}
1214
+ </div>
1215
+ <button type="button" id="edit-add-cost" class="mt-2 bg-green-600 hover:bg-green-700 text-white py-2 px-4 rounded-md text-sm">
1216
+ <i class="fas fa-plus mr-1"></i> Add Another Cost
1217
+ </button>
1218
+ </div>
1219
+ `;
1220
+
1221
+ document.getElementById('edit-form-content').innerHTML = editForm;
1222
+
1223
+ // Add event for new cost button in edit form
1224
+ document.getElementById('edit-add-cost').addEventListener('click', function() {
1225
+ const container = document.getElementById('edit-additional-costs');
1226
+ const div = document.createElement('div');
1227
+ div.className = 'additional-cost-item grid grid-cols-1 md:grid-cols-3 gap-3 mb-3';
1228
+ div.innerHTML = `
1229
+ <div>
1230
+ <label class="block text-sm font-medium text-green-700">Cost Type</label>
1231
+ <input type="text" class="cost-type mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border" placeholder="e.g., Materials, Venue">
1232
+ </div>
1233
+ <div>
1234
+ <label class="block text-sm font-medium text-green-700">Amount (₱)</label>
1235
+ <input type="number" min="0" step="0.01" class="cost-amount mt-1 block w-full rounded-md border-green-300 shadow-sm focus:border-green-500 focus:ring-green-500 p-2 border">
1236
+ </div>
1237
+ <div class="flex items-end">
1238
+ <button type="button" class="remove-cost bg-red-500 hover:bg-red-600 text-white py-2 px-3 rounded-md text-sm">
1239
+ <i class="fas fa-trash mr-1"></i> Remove
1240
+ </button>
1241
+ </div>
1242
+ `;
1243
+ container.appendChild(div);
1244
+ });
1245
+
1246
+ // Remove additional cost row in edit form
1247
+ document.getElementById('edit-additional-costs').addEventListener('click', function(e) {
1248
+ if (e.target.classList.contains('remove-cost') || e.target.closest('.remove-cost')) {
1249
+ const costItem = e.target.closest('.additional-cost-item');
1250
+ if (costItem) {
1251
+ costItem.remove();
1252
+ }
1253
+ }
1254
+ });
1255
+
1256
+ // Show modal
1257
+ document.getElementById('edit-modal').classList.remove('hidden');
1258
+ }, 100);
1259
+ };
1260
+
1261
+ window.deleteTraining = function(id) {
1262
+ if (confirm('Are you sure you want to delete this training program?')) {
1263
+ const event = new Event('DOMContentLoaded');
1264
+ document.dispatchEvent(event);
1265
+
1266
+ // Wait for the DOM to be ready
1267
+ setTimeout(() => {
1268
+ let trainings = JSON.parse(localStorage.getItem('safetyTrainingData')).trainings;
1269
+ trainings = trainings.filter(t => t.id !== id);
1270
+
1271
+ localStorage.setItem('safetyTrainingData', JSON.stringify({
1272
+ ...JSON.parse(localStorage.getItem('safetyTrainingData')),
1273
+ trainings
1274
+ }));
1275
+
1276
+ document.dispatchEvent(event);
1277
+ }, 100);
1278
+ }
1279
+ };
1280
+ </script>
1281
+ <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=froiln1565/training" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1282
+ </html>