+
}
+ title={t('trip.form.whenTitle')}
+ hint={t('trip.form.whenHint')}
+ />
+
+ {/* min-w-0 on both cells: a grid item defaults to min-width:auto, so a
+ long date ("12. Sept. 2026" and the keyboard button beside it) pushed
+ the cell past its track and the two columns overlapped (#2267). */}
+
+
+
+ update('start_date', v)}
+ placeholder={t('dashboard.startDate')}
+ />
+
+
+
+ update('end_date', v)}
+ placeholder={t('dashboard.endDate')}
+ />
+
+
+
+ {!formData.start_date && !formData.end_date && (
+
+
+
{
+ if (raw === '') {
+ update('day_count', '');
+ return;
+ }
+ const n = Math.floor(Number(raw));
+ if (Number.isFinite(n)) update('day_count', Math.min(MAX_TRIP_DAYS, Math.max(1, n)));
+ }}
+ className={inputCls}
+ />
+ {t('dashboard.dayCountHint')}
+
+ )}
+
+
+
+ canEditTrip && update('currency', v)}
+ disabled={!canEditTrip}
+ options={currenciesWith(formData.currency).map((c) => ({
+ value: c,
+ label: `${c} (${SYMBOLS[c] || c})`,
+ }))}
+ searchable
+ />
+
+
+ {/* Reminder — only visible to owner (or when creating) */}
+ {(!isEditing || trip?.user_id === currentUser?.id || currentUser?.role === 'admin') && (
+
+
+ {!tripRemindersEnabled ? (
+
+ {t('trips.reminderDisabledHint')}
+
+ ) : (
+ <>
+
+ {[
+ { value: 0, label: t('trips.reminderNone') },
+ { value: 1, label: `1 ${t('trips.reminderDay')}` },
+ { value: 3, label: `3 ${t('trips.reminderDays')}` },
+ { value: 9, label: `9 ${t('trips.reminderDays')}` },
+ ].map((opt) => (
+
+ ))}
+
+
+ {customReminder && (
+
+
+ update('reminder_days', Math.max(1, Math.min(30, Number(raw) || 1)))
+ }
+ className="focus:ring-accent/40 w-20 rounded-xl border border-edge bg-surface-input px-3 py-1.5 text-body text-content focus:outline-none focus:ring-2"
+ />
+ {t('trips.reminderDaysBefore')}
+
+ )}
+ >
+ )}
+
+ )}
+
+ {/* Members. Not inside the trip settings, whose People area is where they are managed. */}
+ {!embedded && allUsers.filter((u) => u.id !== currentUser?.id).length > 0 && (
+
+
+ {/* Existing members (editing mode) */}
+ {isEditing && existingMembers.length > 0 && (
+
+ {existingMembers.map((m) => (
+
+ ))}
+
+ )}
+ {/* Newly selected members (both modes) */}
+ {selectedMembers.length > 0 && (
+
+ {selectedMembers.map((uid) => {
+ const user = allUsers.find((u) => u.id === uid)!;
+ return (
+
+ );
+ })}
+
+ )}
+
+ {
+ if (isEditing && trip?.id) {
+ const user = allUsers.find((u) => u.id === Number(value));
+ if (user && isEffectivelyOffline()) {
+ toast.error(t('common.needsConnection'));
+ } else if (user) {
+ try {
+ await tripsApi.addMember(trip.id, user.username);
+ setExistingMembers((prev) => [...prev, { id: user.id, username: user.username }]);
+ toast.success(t('trips.memberAdded', { username: user.username }));
+ } catch {
+ toast.error(t('trips.memberAddError'));
+ }
+ }
+ } else {
+ setSelectedMembers((prev) =>
+ prev.includes(Number(value)) ? prev : [...prev, Number(value)]
+ );
+ }
+ setMemberSelectValue('');
+ }}
+ placeholder={t('dashboard.addMember')}
+ options={allUsers
+ .filter(
+ (u) =>
+ u.id !== currentUser?.id &&
+ !selectedMembers.includes(u.id) &&
+ !existingMembers.some((m) => m.id === u.id)
+ )
+ .map((u) => ({ value: u.id, label: u.username }))}
+ searchable
+ size="sm"
+ />
+
+
+ )}
+