Build and Push Docker Image / build-and-push (push) Failing after 20s
App bar: brand, Studies / Read Bible / Reading Plans, and one account menu (theme, Settings, Admin, Log out). Study stage: notes get their own box above the resources in the right column. Settings, Admin and the login page use the reader themes; add a theme-aware danger colour. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
54 lines
3.1 KiB
React
54 lines
3.1 KiB
React
// Cross-references for the chunk: typed, suggested from the Open Cross Ref
|
||
// dataset, and a preview of each reference's verse text.
|
||
import { useState } from 'react';
|
||
|
||
function RefChip({ label, onRemove, loadVerseText }) {
|
||
const [text, setText] = useState(null);
|
||
const [open, setOpen] = useState(false);
|
||
const toggle = () => {
|
||
setOpen((o) => !o);
|
||
if (text == null) loadVerseText(label).then((t) => setText(t || 'Verse text unavailable.')).catch(() => setText('Verse text unavailable.'));
|
||
};
|
||
return (
|
||
<div className="rounded-xl border border-[var(--r-line)]">
|
||
<div className="flex items-center justify-between gap-2 px-3 py-1.5">
|
||
<button type="button" onClick={toggle} aria-expanded={open} className="flex-1 text-left text-sm">{label}</button>
|
||
<button type="button" onClick={onRemove} aria-label={`Remove ${label}`} className="text-[var(--r-sub)] hover:text-[var(--r-danger,#b42318)]">×</button>
|
||
</div>
|
||
{open && <p className="border-t border-[var(--r-line)] px-3 py-2 font-serif text-[13px] leading-relaxed text-[var(--r-sub)]">{text ?? 'Loading…'}</p>}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
export default function CrossRefsTab({ crossRefs, chunk }) {
|
||
const { crossRefInput, setCrossRefInput, suggestingCrossRefs, crossRefSuggestions, addCrossRef, removeCrossRef,
|
||
suggestCrossRefsForChunk, addSuggestedCrossRef, loadVerseText } = crossRefs;
|
||
const refs = chunk.crossReferences ?? [];
|
||
return (
|
||
<div>
|
||
<div className="flex gap-2">
|
||
<input value={crossRefInput} onChange={(e) => setCrossRefInput(e.target.value)} placeholder="e.g. John 1:1 or Rom 3:23"
|
||
onKeyDown={(e) => { if (e.key === 'Enter') { e.preventDefault(); addCrossRef(chunk.id); } }}
|
||
className="min-w-0 flex-1 rounded-lg border border-[var(--r-line)] bg-[var(--r-bg)] px-3 py-1.5 text-sm text-[var(--r-text)] focus:outline-none focus:ring-2 focus:ring-[var(--r-line)]" />
|
||
<button type="button" onClick={() => addCrossRef(chunk.id)} className="rounded-lg bg-[var(--r-text)] px-3 py-1.5 text-sm text-[var(--r-bg)]">Add</button>
|
||
</div>
|
||
<button type="button" onClick={() => suggestCrossRefsForChunk(chunk.id)} disabled={suggestingCrossRefs}
|
||
className="mt-2 rounded-lg border border-[var(--r-line)] px-3 py-1.5 text-sm hover:bg-black/5 disabled:opacity-50">
|
||
{suggestingCrossRefs ? 'Suggesting…' : 'Suggest from passage'}
|
||
</button>
|
||
{crossRefSuggestions.length > 0 && (
|
||
<div className="mt-3 flex flex-wrap gap-1.5">
|
||
{crossRefSuggestions.map((ref) => (
|
||
<button key={ref} type="button" onClick={() => addSuggestedCrossRef(chunk.id, ref)}
|
||
className="rounded-full border border-[var(--r-accent)] px-2.5 py-0.5 text-xs text-[var(--r-accent)] hover:bg-black/5">+ {ref}</button>
|
||
))}
|
||
</div>
|
||
)}
|
||
<div className="mt-3 space-y-1.5">
|
||
{refs.map((ref) => <RefChip key={ref} label={ref} onRemove={() => removeCrossRef(chunk.id, ref)} loadVerseText={loadVerseText} />)}
|
||
{refs.length === 0 && <p className="text-sm text-[var(--r-sub)]">No cross-references yet.</p>}
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|