diff --git a/.env.example b/.env.example index 2746189..82902b4 100644 --- a/.env.example +++ b/.env.example @@ -10,7 +10,7 @@ PROJECT_NAME=jama # Image version to run (set by build.sh, or use 'latest') -JAMA_VERSION=0.9.65 +JAMA_VERSION=0.9.66 # App port — the host port Docker maps to the container PORT=3000 diff --git a/backend/package.json b/backend/package.json index edafddf..c07ec8d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "jama-backend", - "version": "0.9.65", + "version": "0.9.66", "description": "TeamChat backend server", "main": "src/index.js", "scripts": { diff --git a/backend/src/routes/schedule.js b/backend/src/routes/schedule.js index 016e384..1c6580e 100644 --- a/backend/src/routes/schedule.js +++ b/backend/src/routes/schedule.js @@ -195,6 +195,29 @@ router.patch('/:id', authMiddleware, teamManagerMiddleware, (req, res) => { req.params.id ); if (Array.isArray(userGroupIds)) { + // Find which groups are being removed + const prevGroupIds = db.prepare('SELECT user_group_id FROM event_user_groups WHERE event_id = ?') + .all(req.params.id).map(r => r.user_group_id); + const newGroupSet = new Set(userGroupIds.map(Number)); + const removedGroupIds = prevGroupIds.filter(id => !newGroupSet.has(id)); + + // Remove availability responses for users who are only in removed groups + for (const removedGid of removedGroupIds) { + const removedUserIds = db.prepare('SELECT user_id FROM user_group_members WHERE user_group_id = ?') + .all(removedGid).map(r => r.user_id); + for (const uid of removedUserIds) { + // Check if user is still in ANY remaining group for this event + const stillAssigned = newGroupSet.size > 0 && db.prepare(` + SELECT 1 FROM user_group_members + WHERE user_id = ? AND user_group_id IN (${[...newGroupSet].map(()=>'?').join(',')}) + `).get(uid, ...[...newGroupSet]); + if (!stillAssigned) { + db.prepare('DELETE FROM event_availability WHERE event_id = ? AND user_id = ?') + .run(req.params.id, uid); + } + } + } + db.prepare('DELETE FROM event_user_groups WHERE event_id = ?').run(req.params.id); for (const ugId of userGroupIds) db.prepare('INSERT OR IGNORE INTO event_user_groups (event_id, user_group_id) VALUES (?, ?)').run(req.params.id, ugId); diff --git a/build.sh b/build.sh index ad8d95a..5fedb73 100644 --- a/build.sh +++ b/build.sh @@ -13,7 +13,7 @@ # ───────────────────────────────────────────────────────────── set -euo pipefail -VERSION="${1:-0.9.65}" +VERSION="${1:-0.9.66}" ACTION="${2:-}" REGISTRY="${REGISTRY:-}" IMAGE_NAME="jama" diff --git a/frontend/package.json b/frontend/package.json index 8a3c719..28c13b3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "jama-frontend", - "version": "0.9.65", + "version": "0.9.66", "private": true, "scripts": { "dev": "vite", diff --git a/frontend/src/components/MobileEventForm.jsx b/frontend/src/components/MobileEventForm.jsx index 59931bb..6bfcb2e 100644 --- a/frontend/src/components/MobileEventForm.jsx +++ b/frontend/src/components/MobileEventForm.jsx @@ -170,6 +170,19 @@ function RecurrenceSheet({ value, onChange, onClose }) { ); } +// ── Row — must be defined OUTSIDE the component to avoid focus loss ───────────── +function MobileRow({ icon, label, children, onPress, border=true }) { + return ( +