Commit 5a05be2b authored by Alexander Dietmüller's avatar Alexander Dietmüller

Frontend: Selection of single courses

parent 330d3af0
const m = require('mithril');
const { courses, userCourses } = require('./backend.js');
function isSelected(course) {
return userCourses.selected.some(sel => sel === course._id);
function isSelectedOrReserved(course) {
return userCourses.selected.some(sel => sel.course === course._id) ||
userCourses.signups.some(signup => signup.course === course._id);
}
function isBusy() { return userCourses.resources.selections.isBusy(); }
module.exports = {
oninit() { courses.get(); },
oninit() { courses.get().then((d) => { console.log(d); }); },
view() {
return m('table', [
......@@ -17,6 +16,9 @@ module.exports = {
m('th', 'Course'),
m('th', 'Department'),
m('th', 'Name'),
m('th', 'Spots'),
m('th', 'Signup Start'),
m('th', 'Signup End'),
m('th', 'Starting time'),
m('th', 'Ending time'),
]),
......@@ -26,6 +28,9 @@ module.exports = {
m('td', course.lecture.title),
m('td', course.lecture.department),
m('td', course.assistant),
m('td', course.spots),
m('td', course.signup.start),
m('td', course.signup.end),
course.datetimes.map(timeslot => [
m('td', timeslot.start),
m('td', timeslot.end),
......@@ -35,8 +40,8 @@ module.exports = {
m(
'button',
{
onclick() { userCourses.selectCourse(course._id); },
disabled: isSelected(course) || isBusy(),
onclick() { userCourses.select(course._id); },
disabled: isSelectedOrReserved(course),
// ?
// true : false,
// return false;
......
// User Sidebar
const m = require('mithril');
const { userCourses } = require('./backend.js');
const { userCourses, courses } = require('./backend.js');
function courseView(course) {
return m('li', course);
}
const courseView = {
view({ attrs: { _id, courseId, remove } }) {
// Get Lecture of Course
const course = courses.list.find(item => item._id === courseId);
// Otherwise display loading
return m('li', [
m('span', course ? course.lecture.title : 'Loading...'),
// If there is no id, the element is not yet created,
// so a delete button does not make any sense
m('button', { onclick: remove, disabled: !_id }, 'X'),
]);
},
};
function asList(courses) { return courses.map(courseView); }
module.exports = {
oninit() { userCourses.get(); },
......@@ -15,31 +24,33 @@ module.exports = {
return [
m('h1', 'Selected Courses'),
userCourses.selected.length ? [
userCourses.selected.map(selId =>
m('li', [
m('span', selId),
m(
'button',
{
onclick() { userCourses.deselectCourse(selId); },
disabled: userCourses.resources.selections.isBusy(),
},
'X',
),
])),
userCourses.selected.map(({ _id, course: courseId }) =>
m(
courseView,
{ _id, courseId, remove() { userCourses.deselect(_id); } },
)),
m('button', { onclick() { userCourses.reserve(); } }, 'reserve'),
] : m('p', 'No courses selected.'),
m('h1', 'Reserved Courses'),
userCourses.reserved.length ? [
asList(userCourses.reserved),
m('button', { onclick() { userCourses.pay(); } }, 'Pay'),
userCourses.reserved.map(({ _id, course: courseId }) =>
m(
courseView,
{ _id, courseId, remove() { userCourses.free(_id); } },
)),
// m('button', { onclick() { userCourses.pay(); } }, 'Pay'),
] : m('p', 'No courses reserved.'),
userCourses.waiting.length ? [
m('h4', 'Waiting'),
userCourses.waiting.map(({ _id, course: courseId }) =>
m(
courseView,
{ _id, courseId, remove() { userCourses.free(_id); } },
)),
] : [],
m('h1', 'Accepted Courses'),
userCourses.accepted.length ? [
asList(userCourses.accepted),
] : m('p', 'No courses accepted.'),
m('p', 'No courses accepted.'), // TODO: Implement
];
},
};
......@@ -194,59 +194,66 @@ const userCourses = {
},
get selected() {
// We are only interested in the first (only) item
const sel = this.resources.selections.list[0];
return sel ? sel.courses : [];
return this.resources.selections.list;
},
get signups() { return this.resources.signups.list; },
get reserved() {
return this.resources.signups.list.filter(({ status }) =>
status === 'reserved');
},
get waiting() {
return this.resources.signups.list.filter(({ status }) =>
status !== 'reserved' && status !== 'accepted');
},
get accepted() {
return this.resources.signups.list.filter(({ status }) =>
status === 'accepted');
},
selectCourse(courseId) {
// If user already has a selection and update it
const currentSelection = this.resources.selections.list[0] || [];
if (this.selected.length > 0) {
const selectionId = currentSelection._id;
const newSelection = [
...currentSelection.courses,
courseId,
];
return this.resources.selections.patchItem(
selectionId,
{ courses: newSelection },
);
// TODO: Provide error feedback to user in .catch
}
// Otherwise create a new selection
// Select a course
select(courseId) {
return this.resources.selections.post({
nethz: session.user.nethz,
courses: [courseId],
course: courseId,
});
// TODO: Provide error feedback to user in .catch
},
deselectCourse(courseId) {
const selection = this.resources.selections.list[0] || [];
const newSelection = selection.courses.filter(item => item !== courseId);
const selectionId = selection._id;
if (newSelection.length === 0) {
this.resources.selections.deleteItem(selectionId);
} else {
this.resources.selections.patchItem(
selectionId,
{ courses: newSelection },
);
}
// Remove a selection
deselect(selectionId) {
return this.resources.selections.deleteItem(selectionId);
// TODO: Provide error feedback to user in .catch
},
reserve() {},
// Reserve all selected course
reserve() {
// Apply only to selections that actually have been created
const selections = Object.values(this.resources.selections._items);
selections.forEach(({ _id, course }) => {
// Delete selection
this.deselect(_id);
// Create signup
return this.resources.signups.post({
nethz: session.user.nethz,
course,
}).catch((err) => {
// Restore selection
this.select(course);
throw err;
// Todo: Provide feedback to user
});
});
},
// Give up a reserved signup
free(signupId) {
return this.resources.signups.deleteItem(signupId);
// TODO: Provide error feedback to user
},
// TODO: Implement
pay() {},
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment