Skip to content

Commit 89b4866

Browse files
committed
Required fields, return handler
1 parent 6cf09f8 commit 89b4866

6 files changed

Lines changed: 183 additions & 41 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ commtrackr.init({ // Initialize CommTracker with configurations
8888
],
8989
},
9090
],
91+
handler: (data) => {
92+
// Custom handler function for processing commission data
93+
// This function is called when a commission is created or updated
94+
// You can implement your own logic here, such as saving to a database
95+
}
9196
});
9297

9398
app.listen(3000, () => {

frontend/pages/create.ejs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<%- include('head.ejs') %>
2+
<img src="<%= tenant.logo %>" alt="<%= tenant.name %>">
3+
<h1>New commission</h1>
4+
<p>Estimated time to complete: 2 minutes</p>
5+
<% var step = 1; fields.forEach(field => { %>
6+
<div class="inputField <%= field.required ? 'required' : '' %>" id="<%= field.id %>" step="<%= step %>">
7+
<h3><%= field.label %><%= field.required ? '*' : '' %></h3>
8+
<p><%= field.required ? 'Required' : 'Optional' %><%= field.description ? ': ' + field.description : '' %></p>
9+
<% if (field.type === 'textarea') { %>
10+
<textarea placeholder="<%= field.placeholder || '' %>"></textarea>
11+
<% } else if (field.type === 'checkbox') { %>
12+
<input type="checkbox" class="hidden">
13+
<div class="checkbox" change="cms">|||</div>
14+
<% } else if (field.type === 'radio') { %>
15+
<div class="radioOptions">
16+
<% (field.options || []).forEach(option => { %>
17+
<div class="radioOption">
18+
<input type="radio" id="<%= option.value %>" name="<%= option.value %>" value="<%= option.label %>">
19+
<label for="<%= option.value %>"><%= option.label %></label>
20+
</div>
21+
<% }) %>
22+
</div>
23+
<% } else if (field.type === 'select') { %>
24+
<select>
25+
<% (field.options || []).forEach(option => { %>
26+
<option value="<%= option.value %>"><%= option.label %></option>
27+
<% }) %>
28+
</select>
29+
<% } else { %>
30+
<input type="<%= field.type %>" placeholder="<%= field.placeholder || '' %>">
31+
<% } %>
32+
</div>
33+
<% step++; }) %>
34+
<div class="buttons">
35+
<div id="back" class="button hidden" onclick="back();">Back</div>
36+
<div id="next" class="button active hidden" onclick="next();">Next</div>
37+
<div id="start" class="button active" onclick="start();">Start</div>
38+
<div id="create" class="button active hidden" onclick="create();">Create</div>
39+
<a id="success" class="button active hidden" href="<%= tenant.domain %><%= tenant.path %>">Return</a>
40+
<a id="error" class="button active hidden" href="<%= tenant.domain %><%= tenant.path %>/create">Restart</a>
41+
</div>
42+
<%- include('foot.ejs') %>

frontend/pages/user.ejs

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,14 @@
11
<%- include('head.ejs') %>
22
<img src="<%= tenant.logo %>" alt="<%= tenant.name %>">
3-
<h1>New Commission</h1>
4-
<p>Estimated time to complete: 2 minutes</p>
5-
<% var step = 1; fields.forEach(field => { %>
6-
<div class="inputField" id="<%= field.id %>" step="<%= step %>">
7-
<h3><%= field.label %><%= field.required ? '*' : '' %></h3>
8-
<p><%= field.required ? 'Required' : 'Optional' %><%= field.description ? ': ' + field.description : '' %></p>
9-
<% if (field.type === 'textarea') { %>
10-
<textarea placeholder="<%= field.placeholder || '' %>"></textarea>
11-
<% } else if (field.type === 'checkbox') { %>
12-
<input type="checkbox" class="hidden">
13-
<div class="checkbox" change="cms">|||</div>
14-
<% } else if (field.type === 'radio') { %>
15-
<div class="radioOptions">
16-
<% (field.options || []).forEach(option => { %>
17-
<div class="radioOption">
18-
<input type="radio" id="<%= option.value %>" name="<%= option.value %>" value="<%= option.label %>">
19-
<label for="<%= option.value %>"><%= option.label %></label>
20-
</div>
21-
<% }) %>
22-
</div>
23-
<% } else if (field.type === 'select') { %>
24-
<select>
25-
<% (field.options || []).forEach(option => { %>
26-
<option value="<%= option.value %>"><%= option.label %></option>
27-
<% }) %>
28-
</select>
3+
<h1>
4+
<% if (tenant.auth && tenant.auth.enabled) { %>
5+
Hey, <%= session[vars.name] || session[vars.userId] %>!
296
<% } else { %>
30-
<input type="<%= field.type %>" placeholder="<%= field.placeholder || '' %>">
7+
<%= tenant.name %> commissions
318
<% } %>
32-
</div>
33-
<% step++; }) %>
9+
</h1>
10+
<p>View and manage your past commissions.</p>
3411
<div class="buttons">
35-
<div id="back" class="button hidden" onclick="back();">Back</div>
36-
<div id="next" class="button active hidden" onclick="next();">Next</div>
37-
<div id="start" class="button active" onclick="start();">Start</div>
38-
<div id="create" class="button active hidden" onclick="create();">Create</div>
12+
<a class="button" href="<%= tenant.domain %><%= tenant.path %>/create">New Commission</a>
3913
</div>
4014
<%- include('foot.ejs') %>

frontend/public/scripts.js

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,27 @@ function start() {
5656
};
5757

5858
function next() {
59+
if (step > 0) {
60+
const currentField = document.querySelector(`.inputField[step="${step}"]`);
61+
if (currentField && currentField.classList.contains('required')) {
62+
const input = currentField.querySelector('input, textarea, select');
63+
if (input) {
64+
if (input.type === 'checkbox') {
65+
if (!input.checked) {
66+
input.focus();
67+
shake(currentField);
68+
return;
69+
};
70+
} else {
71+
if (!input.value.trim()) {
72+
input.focus();
73+
shake(currentField);
74+
return;
75+
};
76+
};
77+
};
78+
};
79+
};
5980
if (step < document.querySelectorAll('.inputField').length) {
6081
document.querySelector(`.inputField[step="${step}"]`)?.classList.remove('active');
6182
step++;
@@ -144,11 +165,60 @@ document.addEventListener('keydown', function (event) {
144165
};
145166
});
146167

147-
function create() {
148-
localStorage.clear();
168+
async function create() {
169+
anim_out();
170+
var data = {};
171+
document.querySelectorAll('.inputField').forEach(field => {
172+
const input = field.querySelector('input, textarea, select');
173+
if (input) {
174+
if (input.type === 'checkbox') {
175+
data[field.id] = input.checked;
176+
} else {
177+
data[field.id] = input.value;
178+
};
179+
};
180+
});
181+
await fetch(window.location.href, {
182+
method: 'POST',
183+
headers: {
184+
'Content-Type': 'application/json'
185+
},
186+
body: JSON.stringify(data),
187+
})
188+
.then(response => response.json())
189+
.then(result => {
190+
document.getElementById('back').classList.add('hidden')
191+
document.getElementById('create').classList.add('hidden');
192+
if (result.status === 'success') {
193+
document.querySelectorAll('.inputField').forEach(field => {
194+
field.classList.remove('active');
195+
});;
196+
document.getElementById('success').classList.remove('hidden');
197+
localStorage.clear();
198+
document.querySelector('.inner h1').innerText = 'Creation successful';
199+
document.querySelector('.inner p').innerText = result.message || 'Your commission was created successfully.';
200+
} else {
201+
document.querySelectorAll('.inputField').forEach(field => {
202+
field.classList.remove('active');
203+
});
204+
document.getElementById('error').classList.remove('hidden');
205+
document.querySelector('.inner h1').innerText = 'Error';
206+
document.querySelector('.inner p').innerText = result.message || 'An unknown error occurred. Please try again later.';
207+
};
208+
setTimeout(() => {
209+
anim_in();
210+
}, 750)
211+
});
149212
};
150213

151214
function progress(percent) {
152215
const progressBar = document.querySelector('.progress');
153216
progressBar.style.width = percent + '%';
217+
};
218+
219+
function shake(element) {
220+
element.classList.add('shake');
221+
setTimeout(() => {
222+
element.classList.remove('shake');
223+
}, 500);
154224
};

frontend/public/styles.css

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,25 @@ main.in .inner {
289289
animation: in 0.5s forwards;
290290
}
291291

292+
@keyframes shake {
293+
0%,
294+
100% {
295+
transform: translateX(0);
296+
}
297+
20%,
298+
60% {
299+
transform: translateX(-10px);
300+
}
301+
40%,
302+
80% {
303+
transform: translateX(10px);
304+
}
305+
}
306+
307+
.shake {
308+
animation: shake 0.5s;
309+
}
310+
292311
@media screen and (max-width: 950px) {
293312
.buttons,
294313
.button {

index.js

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,26 +114,58 @@ function getUserRole(session) {
114114
// };
115115

116116
app.get('/', async (req, res) => {
117-
console.log('Session:', req.session);
118117
if (!on) return res.render('off', { tenant, title: 'Activation - ' });
119118
if (!req.session) return res.render('session', { tenant, title: 'Session - ' });
120119
if (!tenant.slug || !tenant.name || !tenant.domain) return res.render('tenant', { tenant, title: 'Configuration - ' });
121120
if (tenant.auth && tenant.auth.enabled && vars.userId && !req.session[vars.userId]) return res.render('auth', { tenant, title: 'Authenticate - ' });
122-
console.log('User ID:', req.session[vars.userId]);
123-
console.log('Role:', getUserRole(req.session));
124121
switch (getUserRole(req.session)) {
125122
case 'admin':
126-
res.render('admin', { tenant, title: 'Admin View - ' });
123+
res.render('admin', { tenant, title: 'Admin View - ', session: req.session, vars });
127124
break;
128125
case 'dev':
129-
res.render('dev', { tenant, title: 'Developer View - ' });
126+
res.render('dev', { tenant, title: 'Developer View - ', session: req.session, vars });
130127
break;
131128
default:
132-
res.render('user', { tenant, title: 'New Commission - ', fields });
129+
res.render('user', { tenant, title: '', session: req.session, vars, fields });
133130
break;
134131
};
135132
});
136133

134+
app.get('/create', async (req, res) => {
135+
if (!on) return res.render('off', { tenant, title: 'Activation - ' });
136+
if (!req.session) return res.render('session', { tenant, title: 'Session - ' });
137+
if (!tenant.slug || !tenant.name || !tenant.domain) return res.render('tenant', { tenant, title: 'Configuration - ' });
138+
if (tenant.auth && tenant.auth.enabled && vars.userId && !req.session[vars.userId]) return res.render('auth', { tenant, title: 'Authenticate - ' });
139+
res.render('create', { tenant, title: 'New Commission - ', session: req.session, vars, fields });
140+
});
141+
142+
app.post('/create', async (req, res) => {
143+
if (!on) return res.status(503).json({ status: 'error', message: 'Service is currently offline.' });
144+
if (!req.session) return res.status(401).json({ status: 'error', message: 'No session found. Please enable cookies and try again.' });
145+
if (tenant.auth && tenant.auth.enabled && vars.userId && !req.session[vars.userId]) return res.status(401).json({ status: 'error', message: 'User not authenticated. Please log in and try again.' });
146+
if (!tenant.slug || !tenant.name || !tenant.domain) return res.status(500).json({ status: 'error', message: 'Service is not properly configured. Please contact the administrator.' });
147+
if (!fields || !fields.length) return res.status(500).json({ status: 'error', message: 'No fields configured for commission creation. Please contact the administrator.' });
148+
const data = {};
149+
fields.forEach(field => {
150+
if (field.id) data[field.id] = req.body[field.id] || null;
151+
});
152+
data.createdAt = new Date();
153+
data.createdBy = (tenant.auth && tenant.auth.enabled) ? {
154+
id: req.session[vars.userId],
155+
name: req.session[vars.name] || req.session[vars.userId],
156+
role: getUserRole(req.session) || 'user'
157+
} : {};
158+
if (returnHandler && typeof returnHandler === 'function') {
159+
// try {
160+
// await returnHandler(data);
161+
// } catch (error) {
162+
// console.error('Error in handler function:', error);
163+
return res.status(500).json({ status: 'error', message: 'An error occurred while processing your request. Please try again later.' });
164+
// };
165+
};
166+
res.status(200).json({ status: 'success', message: 'Your commission was created successfully.' });
167+
});
168+
137169
module.exports = {
138170
routes: app,
139171
init,

0 commit comments

Comments
 (0)