Participants, context menus, budget rename, file types, UI polish

- Assignment participants: toggle who joins each activity
  - Chips with hover-to-remove (strikethrough effect)
  - Add button with dropdown for available members
  - Avatars in day plan sidebar
  - Side-by-side with reservation in place inspector
- Right-click context menus for places, notes in day plan + places list
- Budget categories can now be renamed (pencil icon inline edit)
- Admin: configurable allowed file types (stored in app_settings)
- File manager shows allowed types dynamically
- Hotel picker: select place + save button (no auto-close)
- Edit pencil opens full hotel popup with all options
- Place inspector: opening hours + files side by side on desktop
- Address clamped to 2 lines, coordinates hidden on mobile
- Category shows icon only on mobile
- Rating hidden on mobile in place inspector
- Time validation: "10" becomes "10:00"
- Climate weather: full hourly data from archive API
- CustomSelect: grouped headers support (isHeader)
- Various responsive fixes
This commit is contained in:
Maurice
2026-03-24 23:25:02 +01:00
parent e1cd9655fb
commit 785f0a7684
16 changed files with 480 additions and 102 deletions
+13
View File
@@ -117,6 +117,18 @@ router.get('/', authenticate, (req, res) => {
// Group assignments by day_id
const assignmentsByDayId = {};
// Load all participants for all assignments
const allAssignmentIds = allAssignments.map(a => a.id)
const allParticipants = allAssignmentIds.length > 0
? db.prepare(`SELECT ap.assignment_id, ap.user_id, u.username, u.avatar FROM assignment_participants ap JOIN users u ON ap.user_id = u.id WHERE ap.assignment_id IN (${allAssignmentIds.map(() => '?').join(',')})`)
.all(...allAssignmentIds)
: []
const participantsByAssignment = {}
for (const p of allParticipants) {
if (!participantsByAssignment[p.assignment_id]) participantsByAssignment[p.assignment_id] = []
participantsByAssignment[p.assignment_id].push({ user_id: p.user_id, username: p.username, avatar: p.avatar })
}
for (const a of allAssignments) {
if (!assignmentsByDayId[a.day_id]) assignmentsByDayId[a.day_id] = [];
assignmentsByDayId[a.day_id].push({
@@ -124,6 +136,7 @@ router.get('/', authenticate, (req, res) => {
day_id: a.day_id,
order_index: a.order_index,
notes: a.notes,
participants: participantsByAssignment[a.id] || [],
created_at: a.created_at,
place: {
id: a.place_id,