It now holds files, sharing, handouts, slides, importing notes, schedule, co-teachers and earlier versions, not just exports. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
65 lines
3.7 KiB
React
65 lines
3.7 KiB
React
// Finish → Schedule: the study's sessions (one per chunk) as a calendar file, starting on a date you pick.
|
||
import { useState } from 'react';
|
||
import { formatChunkReference } from '../utils/bibleUtils.jsx';
|
||
import { buildIcs, downloadIcs, sessionDates } from '../utils/icsFile.js';
|
||
|
||
const field = 'rounded-lg border border-[var(--r-line)] bg-[var(--r-bg)] px-2.5 py-1.5 text-sm text-[var(--r-text)] focus:outline-none focus:ring-2 focus:ring-[var(--r-line)]';
|
||
const isoDay = (d) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
||
|
||
// The study's sessions in order: { title, description } for each chunk.
|
||
export function sessionsOf(project) {
|
||
const list = [];
|
||
(project?.chapters ?? []).forEach((chapter, chapterIndex) => {
|
||
for (const chunk of chapter.chunks ?? []) {
|
||
const ref = formatChunkReference(project, chapterIndex, chunk, '–');
|
||
const n = list.length + 1;
|
||
const label = `Session ${(chunk.episodeNumber ?? '').toString().trim() || n}`;
|
||
const name = (project.series ?? '').trim() || project.title;
|
||
list.push({ title: `${name} — ${label}: ${(chunk.episodeTitle ?? '').trim() || ref}`, description: `${project.title}\n${ref}` });
|
||
}
|
||
});
|
||
return list;
|
||
}
|
||
|
||
export default function SessionSchedule({ project }) {
|
||
const sessions = sessionsOf(project);
|
||
const [start, setStart] = useState(() => isoDay(new Date()));
|
||
const [every, setEvery] = useState('7');
|
||
const [time, setTime] = useState('');
|
||
const [minutes, setMinutes] = useState('60');
|
||
if (sessions.length === 0) return null;
|
||
|
||
const download = () => {
|
||
const [y, m, d] = start.split('-').map(Number);
|
||
const dates = sessionDates(new Date(y, m - 1, d), sessions.length, Number(every));
|
||
const events = sessions.map((s, i) => ({ ...s, date: dates[i], time: time || undefined, minutes: Number(minutes) || 60 }));
|
||
downloadIcs(buildIcs(events, { name: (project.series ?? '').trim() || project.title }), `${(project.title || 'study').replace(/[^\w]+/g, '-').toLowerCase()}-schedule.ics`);
|
||
};
|
||
|
||
return (
|
||
<section className="rounded-2xl border border-[var(--r-line)] bg-[var(--r-bar)] p-5" aria-label="Schedule">
|
||
<h2 className="text-sm font-medium">Schedule</h2>
|
||
<p className="mb-3 mt-1 text-xs text-[var(--r-sub)]">Put the {sessions.length} session{sessions.length === 1 ? '' : 's'} on your calendar: one per chunk, in order, using each chunk’s session number and title.</p>
|
||
<div className="flex flex-wrap items-end gap-3">
|
||
<label className="text-xs text-[var(--r-sub)]">First session
|
||
<input type="date" value={start} onChange={(e) => setStart(e.target.value)} className={`${field} mt-1 block`} />
|
||
</label>
|
||
<label className="text-xs text-[var(--r-sub)]">Then every
|
||
<select value={every} onChange={(e) => setEvery(e.target.value)} className={`${field} mt-1 block`}>
|
||
<option value="1">day</option><option value="7">week</option><option value="14">2 weeks</option><option value="30">30 days</option>
|
||
</select>
|
||
</label>
|
||
<label className="text-xs text-[var(--r-sub)]">At (optional)
|
||
<input type="time" value={time} onChange={(e) => setTime(e.target.value)} className={`${field} mt-1 block`} />
|
||
</label>
|
||
{time && (
|
||
<label className="text-xs text-[var(--r-sub)]">Minutes
|
||
<input type="number" min="5" max="480" value={minutes} onChange={(e) => setMinutes(e.target.value)} className={`${field} mt-1 block w-20`} />
|
||
</label>
|
||
)}
|
||
<button type="button" onClick={download} disabled={!start} className="rounded-xl border border-[var(--r-line)] px-4 py-2 text-sm hover:bg-black/5 disabled:opacity-50">Download calendar file (.ics)</button>
|
||
</div>
|
||
</section>
|
||
);
|
||
}
|