Add every-N-day frequency toggle to new routine page

The schedule editor on /dashboard/routines/new was missing the
Weekly/Every N Days toggle that was added to the edit page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-19 19:26:44 -06:00
parent ecb79af44e
commit 33db2629e3

View File

@@ -50,6 +50,9 @@ export default function NewRoutinePage() {
const [scheduleDays, setScheduleDays] = useState<string[]>(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']);
const [scheduleTime, setScheduleTime] = useState('08:00');
const [scheduleRemind, setScheduleRemind] = useState(true);
const [scheduleFrequency, setScheduleFrequency] = useState<'weekly' | 'every_n_days'>('weekly');
const [scheduleIntervalDays, setScheduleIntervalDays] = useState(2);
const [scheduleStartDate, setScheduleStartDate] = useState(() => new Date().toISOString().split('T')[0]);
const toggleDay = (day: string) => {
setScheduleDays(prev =>
@@ -128,11 +131,16 @@ export default function NewRoutinePage() {
});
}
if (scheduleDays.length > 0) {
if (scheduleFrequency === 'every_n_days' || scheduleDays.length > 0) {
await api.routines.setSchedule(routine.id, {
days: scheduleDays,
time: scheduleTime,
remind: scheduleRemind,
frequency: scheduleFrequency,
...(scheduleFrequency === 'every_n_days' && {
interval_days: scheduleIntervalDays,
start_date: scheduleStartDate,
}),
});
}
@@ -226,58 +234,110 @@ export default function NewRoutinePage() {
{/* Schedule */}
<div className="bg-white dark:bg-gray-800 rounded-xl p-4 shadow-sm space-y-4">
<h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">Schedule <span className="text-sm font-normal text-gray-400">(optional)</span></h2>
{/* Quick select buttons */}
{/* Frequency selector */}
<div className="flex gap-2">
<button
type="button"
onClick={() => setScheduleDays(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'])}
className={`px-3 py-1.5 rounded-lg text-sm font-medium border transition-colors ${
scheduleDays.length === 7 ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
onClick={() => setScheduleFrequency('weekly')}
className={`flex-1 px-3 py-2 rounded-lg text-sm font-medium border transition-colors ${
scheduleFrequency === 'weekly' ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
}`}
>
Every day
Weekly
</button>
<button
type="button"
onClick={() => setScheduleDays(['mon', 'tue', 'wed', 'thu', 'fri'])}
className={`px-3 py-1.5 rounded-lg text-sm font-medium border transition-colors ${
scheduleDays.length === 5 && !scheduleDays.includes('sat') && !scheduleDays.includes('sun') ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
onClick={() => setScheduleFrequency('every_n_days')}
className={`flex-1 px-3 py-2 rounded-lg text-sm font-medium border transition-colors ${
scheduleFrequency === 'every_n_days' ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
}`}
>
Weekdays
</button>
<button
type="button"
onClick={() => setScheduleDays(['sat', 'sun'])}
className={`px-3 py-1.5 rounded-lg text-sm font-medium border transition-colors ${
scheduleDays.length === 2 && scheduleDays.includes('sat') && scheduleDays.includes('sun') ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
}`}
>
Weekends
Every N Days
</button>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Days</label>
<div className="flex gap-2 flex-wrap">
{DAY_OPTIONS.map((day) => (
{scheduleFrequency === 'every_n_days' ? (
<div className="space-y-3">
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Repeat every</label>
<div className="flex items-center gap-2">
<input
type="number"
min={2}
max={365}
value={scheduleIntervalDays}
onChange={(e) => setScheduleIntervalDays(Math.max(2, Number(e.target.value)))}
className="w-20 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-indigo-500 outline-none"
/>
<span className="text-sm text-gray-600 dark:text-gray-400">days</span>
</div>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Starting from</label>
<input
type="date"
value={scheduleStartDate}
onChange={(e) => setScheduleStartDate(e.target.value)}
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-indigo-500 outline-none"
/>
</div>
</div>
) : (
<>
{/* Quick select buttons */}
<div className="flex gap-2">
<button
key={day.value}
type="button"
onClick={() => toggleDay(day.value)}
className={`px-3 py-2 rounded-lg text-sm font-medium border transition-colors ${
scheduleDays.includes(day.value)
? 'bg-indigo-600 text-white border-indigo-600'
: 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
onClick={() => setScheduleDays(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'])}
className={`px-3 py-1.5 rounded-lg text-sm font-medium border transition-colors ${
scheduleDays.length === 7 ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
}`}
>
{day.label}
Every day
</button>
))}
</div>
</div>
<button
type="button"
onClick={() => setScheduleDays(['mon', 'tue', 'wed', 'thu', 'fri'])}
className={`px-3 py-1.5 rounded-lg text-sm font-medium border transition-colors ${
scheduleDays.length === 5 && !scheduleDays.includes('sat') && !scheduleDays.includes('sun') ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
}`}
>
Weekdays
</button>
<button
type="button"
onClick={() => setScheduleDays(['sat', 'sun'])}
className={`px-3 py-1.5 rounded-lg text-sm font-medium border transition-colors ${
scheduleDays.length === 2 && scheduleDays.includes('sat') && scheduleDays.includes('sun') ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
}`}
>
Weekends
</button>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">Days</label>
<div className="flex gap-2 flex-wrap">
{DAY_OPTIONS.map((day) => (
<button
key={day.value}
type="button"
onClick={() => toggleDay(day.value)}
className={`px-3 py-2 rounded-lg text-sm font-medium border transition-colors ${
scheduleDays.includes(day.value)
? 'bg-indigo-600 text-white border-indigo-600'
: 'bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 border-gray-300 dark:border-gray-600'
}`}
>
{day.label}
</button>
))}
</div>
</div>
</>
)}
<div>
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Time</label>
<input
@@ -287,7 +347,7 @@ export default function NewRoutinePage() {
className="w-full px-4 py-3 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:ring-2 focus:ring-indigo-500 outline-none"
/>
</div>
<div className="flex items-center justify-between">
<div>
<p className="font-medium text-gray-900 dark:text-gray-100">Send reminder</p>