Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions src/app/handoff-journal/_components/action-bullet-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { ActionBullet } from "../_data/handoff-journal-data";
import styles from "../handoff-journal.module.css";

type ActionBulletListProps = {
entryTitle: string;
actions: ActionBullet[];
};

const toneLabelMap = {
now: "Immediate",
next: "Queued next",
watch: "Watch closely",
} as const;

export function ActionBulletList({
entryTitle,
actions,
}: ActionBulletListProps) {
console.log(`Rendering ${actions.length} action bullets for ${entryTitle}`);

return (
<section className={styles.actionSection}>
<div className={styles.sectionHeader}>
<p className={styles.sectionEyebrow}>Action bullets</p>
<p className={styles.sectionCaption}>
Compact, owner-tagged follow-through for the incoming shift.
</p>
</div>

Comment thread
iamasx marked this conversation as resolved.
<ul
aria-label={`${entryTitle} action bullets`}
className={styles.actionList}
role="list"
>
{actions.map((action) => (
<li key={action.id} className={styles.actionItem}>
<span
aria-hidden
className={`${styles.actionDot} ${
action.tone === "now"
? styles.actionDotNow
: action.tone === "watch"
? styles.actionDotWatch
: styles.actionDotNext
}`}
/>
<div className={styles.actionBody}>
<p className={styles.actionLabel}>{action.label}</p>
<div className={styles.actionMeta}>
<span className={styles.actionMetaPill}>{toneLabelMap[action.tone]}</span>
<span className={styles.actionMetaText}>{action.owner}</span>
<span className={styles.actionMetaText}>{action.timing}</span>
</div>
</div>
</li>
))}
</ul>
</section>
);
}
54 changes: 54 additions & 0 deletions src/app/handoff-journal/_components/carry-forward-panel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import type { CarryForwardNote } from "../_data/handoff-journal-data";
import styles from "../handoff-journal.module.css";

type CarryForwardPanelProps = {
notes: CarryForwardNote[];
};

export function CarryForwardPanel({ notes }: CarryForwardPanelProps) {
return (
<aside
aria-labelledby="carry-forward-title"
className={`${styles.surfacePanel} ${styles.carryForwardPanel}`}
id="carry-forward"
>
<div className={styles.panelHeading}>
<p className={styles.panelEyebrow}>Carry-forward</p>
<h2 id="carry-forward-title" className={styles.panelTitle}>
Compact notes for the incoming crew
</h2>
<p className={styles.panelDescription}>
Only unresolved items stay here, so the next shift can scan the
essentials without rereading every handoff card.
</p>
</div>

<div
aria-label="Carry-forward notes"
className={styles.carryForwardList}
role="list"
>
{notes.map((note) => (
<article
key={note.id}
className={`${styles.carryForwardCard} ${
note.tone === "open"
? styles.carryForwardOpen
: note.tone === "monitor"
? styles.carryForwardMonitor
: styles.carryForwardScheduled
}`}
role="listitem"
>
<div className={styles.carryForwardTop}>
<p className={styles.carryForwardLane}>{note.lane}</p>
<span className={styles.carryForwardCheck}>{note.nextCheck}</span>
</div>
<p className={styles.carryForwardNote}>{note.note}</p>
<p className={styles.carryForwardOwner}>{note.owner}</p>
</article>
))}
</div>
</aside>
);
}
50 changes: 50 additions & 0 deletions src/app/handoff-journal/_components/handoff-entry-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ActionBulletList } from "./action-bullet-list";
import type { HandoffEntry } from "../_data/handoff-journal-data";
import styles from "../handoff-journal.module.css";

type HandoffEntryCardProps = {
entry: HandoffEntry;
};

export function HandoffEntryCard({ entry }: HandoffEntryCardProps) {
return (
<article
className={`${styles.entryCard} ${
entry.tone === "steady"
? styles.entrySteady
: entry.tone === "watch"
? styles.entryWatch
: styles.entryUrgent
}`}
role="listitem"
>
<div className={styles.entryHeader}>
<div className={styles.entryHeaderCopy}>
<span className={styles.entryShiftBadge}>{entry.shiftLabel}</span>
<h3 className={styles.entryTitle}>{entry.title}</h3>
</div>
<div className={styles.entryMeta}>
<span className={styles.entryMetaPill}>{entry.window}</span>
<span className={styles.entryMetaText}>{entry.operator}</span>
<span className={styles.entryMetaText}>{entry.channel}</span>
</div>
</div>

<p className={styles.entrySummary}>{entry.summary}</p>

<ul
aria-label={`${entry.title} highlights`}
className={styles.highlightList}
role="list"
>
{entry.highlights.map((highlight) => (
<li key={highlight} className={styles.highlightItem}>
{highlight}
</li>
))}
</ul>

<ActionBulletList actions={entry.actions} entryTitle={entry.title} />
</article>
);
}
Loading
Loading