Skip to content

Commit d4de12b

Browse files
authored
Merge pull request #175 from BritishYouthBandAssociation/last-push
Big boi
2 parents d46cb08 + 288c8d9 commit d4de12b

File tree

11 files changed

+703
-94
lines changed

11 files changed

+703
-94
lines changed

public/js/component/Caption.js

+22-4
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,24 @@ Vue.component('caption-selector', {
1919
2020
<div class="form-group mb-3">
2121
<label :for="'multiplier-' + caption.id">Multiplier</label>
22-
<input type="number" class="form-control" :id="'multiplier-' + caption.id" v-model="caption.Multiplier" step="0.01"/>
22+
<input type="number" class="form-control" :id="'multiplier-' + caption.id" v-model="caption.Multiplier" step="0.01" @change="setMultiplier"/>
2323
</div>
2424
2525
<div class="form-group mb-3">
2626
<label :for="'optional-' + caption.id">Is Optional?</label>
2727
<div class="btn-group" role="group" aria-label="Is Optional?">
28-
<input type="radio" value="true" class="btn-check" :name="'optional-' + caption.id" :id="'optional-y-' + caption.id" autocomplete="off" v-model="caption.IsOptional">
28+
<input type="radio" value="true" class="btn-check" :name="'optional-' + caption.id" :id="'optional-y-' + caption.id" autocomplete="off" v-model="caption.IsOptional" @change="setOptional(true)">
2929
<label class="btn btn-outline-success" :for="'optional-y-' + caption.id">Yes</label>
3030
31-
<input type="radio" value="false" class="btn-check" :name="'optional-' + caption.id" :id="'optional-n-' + caption.id" autocomplete="off" v-model="caption.IsOptional">
31+
<input type="radio" value="false" class="btn-check" :name="'optional-' + caption.id" :id="'optional-n-' + caption.id" autocomplete="off" v-model="caption.IsOptional" @change="setOptional(false)">
3232
<label class="btn btn-outline-danger" :for="'optional-n-' + caption.id">No</label>
3333
</div>
3434
</div>
3535
3636
<button class="btn btn-default mb-3" type="button" v-on:click="addCaption">+ Add</button>
3737
3838
<div class="row row-cols-1 row-cols-lg-2">
39-
<caption-selector v-for="c in caption.Subcaptions" :key="c.id" :caption="c" />
39+
<caption-selector v-for="c in caption.Subcaptions" :key="c.id" :caption="c" ref="subcaption"/>
4040
</div>
4141
</div>
4242
</div>
@@ -55,6 +55,24 @@ Vue.component('caption-selector', {
5555
Vue.nextTick(() => {
5656
document.getElementById(`caption-${id}`).scrollIntoView(true);
5757
});
58+
},
59+
60+
setOptional(val){
61+
this.caption.IsOptional = val;
62+
63+
if (val && this.$refs.subcaption){
64+
this.$refs.subcaption.forEach(s => s.setOptional(val));
65+
}
66+
},
67+
68+
setMultiplier(val){
69+
if (!isNaN(val)){
70+
this.caption.Multiplier = val;
71+
}
72+
73+
if (this.$refs.subcaption){
74+
this.$refs.subcaption.forEach(s => s.setMultiplier(this.caption.Multiplier));
75+
}
5876
}
5977
},
6078
computed: {

public/js/component/SearchBox.js

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ Vue.component('search-box', {
3131
doSearch(e) {
3232
this.$data._text = e.target.value; //mobile workaround
3333

34+
//we've changed the text, so should clear any previously-selected value
35+
this.$data._value = null;
36+
3437
if (this.$data._text.length < 3) {
3538
this.results = [];
3639
this.noneFound = false;

routes/config.js

+85-31
Original file line numberDiff line numberDiff line change
@@ -147,45 +147,99 @@ router.post('/organisation-type', checkAdmin, validator.body(Joi.object({
147147
router.get('/event-type', checkAdmin, validator.query(Joi.object({
148148
saved: Joi.boolean()
149149
})), async (req, res, next) => {
150-
const types = await req.db.EventType.findAll();
150+
const [types, membershipTypes] = await Promise.all([req.db.EventType.findAll({
151+
include: [{
152+
model: req.db.EventTypeDiscount,
153+
include: [req.db.MembershipType]
154+
}],
155+
order: [
156+
['id'],
157+
[req.db.EventTypeDiscount, 'DiscountAfter']
158+
]
159+
}), req.db.MembershipType.findAll({
160+
where: {
161+
IsOrganisation: true,
162+
IsActive: true
163+
}
164+
})]);
151165

152166
return res.render('config/event-type.hbs', {
153167
title: 'Event Types',
154-
types: types,
168+
types,
169+
membershipTypes,
155170
saved: req.query.saved ?? false
156171
});
157172
});
158173

159-
router.post('/event-type', checkAdmin, validator.body(Joi.object({
160-
id: Joi.array()
161-
.items(Joi.number()),
162-
type: Joi.array()
163-
.items(Joi.string()),
164-
cost: Joi.array()
165-
.items(Joi.number()),
166-
isActive: Joi.array()
167-
.items(Joi.boolean().falsy('0').truthy('1')),
168-
})), async (req, res, next) => {
169-
await Promise.all(req.body.type.map((type, i) => {
170-
const details = {
171-
Name: req.body.type[i],
172-
EntryCost: req.body.cost[i],
173-
IsActive: req.body.isActive[i]
174-
};
174+
router.post('/event-type', checkAdmin,
175+
validator.body(Joi.object({
176+
id: Joi.array()
177+
.items(Joi.number()),
178+
type: Joi.array()
179+
.items(Joi.string()),
180+
cost: Joi.array()
181+
.items(Joi.number()),
182+
isActive: Joi.array()
183+
.items(Joi.boolean().falsy('0').truthy('1')),
184+
discountAfter: Joi.array().items(Joi.array().items(Joi.number())),
185+
multiplier: Joi.array().items(Joi.array().items(Joi.number())),
186+
membersOnly: Joi.array().items(Joi.array().items(Joi.boolean())),
187+
membershipType: Joi.array().items(Joi.array().items(Joi.array().items(Joi.number().allow(''))))
188+
})),
189+
async (req, res, next) => {
190+
await Promise.all(req.body.type.map((_, i) => {
191+
return (async function(){
192+
const details = {
193+
Name: req.body.type[i],
194+
EntryCost: req.body.cost[i],
195+
IsActive: req.body.isActive[i]
196+
};
175197

176-
if (req.body.id[i] < 0) {
177-
return req.db.EventType.create(details);
178-
}
198+
let type = null;
199+
if (req.body.id[i] < 0) {
200+
type = await req.db.EventType.create(details);
201+
} else {
202+
await req.db.EventType.update(details, {
203+
where: {
204+
id: req.body.id[i]
205+
}
206+
});
207+
type = await req.db.EventType.findByPk(req.body.id[i]);
208+
}
179209

180-
return req.db.EventType.update(details, {
181-
where: {
182-
id: req.body.id[i]
183-
}
184-
});
185-
}));
210+
//clear discounts and start fresh
211+
await req.db.EventTypeDiscount.destroy({
212+
where: {
213+
EventTypeId: type.id
214+
}
215+
});
186216

187-
return res.redirect('?saved=true');
188-
});
217+
await Promise.all(req.body.discountAfter[i].map((_, d) => {
218+
return (async function() {
219+
const allPos = (req.body.membershipType[i][d] ?? []).indexOf(-1);
220+
if (allPos > -1) {
221+
req.body.membershipType[i][d].splice(allPos, 1);
222+
}
223+
224+
const discountDetails = {
225+
DiscountAfter: req.body.discountAfter[i][d],
226+
DiscountMultiplier: req.body.multiplier[i][d],
227+
MembersOnly: req.body.membersOnly[i][d],
228+
AllMembers: allPos > -1
229+
};
230+
231+
const discount = await type.createEventTypeDiscount(discountDetails);
232+
233+
if (discount.MembersOnly) {
234+
await discount.addMembershipTypes(req.body.membershipType[i][d]);
235+
}
236+
})();
237+
}));
238+
})();
239+
}));
240+
241+
return res.redirect('?saved=true');
242+
});
189243

190244
router.get('/payment-type', checkAdmin, validator.query(Joi.object({
191245
saved: Joi.boolean()
@@ -275,7 +329,7 @@ router.post('/division', checkAdmin, validator.body(Joi.object({
275329
return res.redirect('?saved=true');
276330
});
277331

278-
async function loadCaption(db, parent){
332+
async function loadCaption(db, parent) {
279333
parent.Subcaptions = await db.findAll({
280334
where: {
281335
ParentID: parent.id
@@ -320,7 +374,7 @@ async function saveCaption(db, caption, parent) {
320374
ParentID: parent
321375
};
322376

323-
if (caption.id < 0){
377+
if (caption.id < 0) {
324378
const _new = await db.create(details);
325379

326380
caption.id = _new.id;

0 commit comments

Comments
 (0)