You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.6 KiB
TypeScript

// frontend/components/journey/FlowCard.tsx — 흐름 카드 (routine/task/meet, 원본 fcard)
import { forwardRef } from "react";
import { Icon } from "@/components/Icon";
import type { IconName } from "@/components/icons/paths";
import type { RoutineCard, TaskCard, MeetCard, JourneyPerson } from "@/lib/types";
type Hover = {
className: string;
onMouseEnter: () => void;
onMouseLeave: () => void;
};
const FALLBACK_PERSON: Pick<JourneyPerson, "name" | "initial" | "color"> = {
name: "",
initial: "?",
color: "var(--card-2)",
};
// 1 — 아침 준비 (routine)
export const RoutineFlowCard = forwardRef<HTMLDivElement, { card: RoutineCard; hover: Hover }>(
function RoutineFlowCard({ card, hover }, ref) {
return (
<div
className={hover.className}
ref={ref}
onMouseEnter={hover.onMouseEnter}
onMouseLeave={hover.onMouseLeave}
>
<div className="fcard-row">
<div className="fc-ic">
<Icon name={card.icon as IconName} />
</div>
<div className="fc-main">
<div className="fc-title">{card.title}</div>
<div className="fc-meta">{card.meta}</div>
</div>
<div className={"mini " + (card.toolTone || "")}>
<Icon name={card.tool as IconName} w={2.4} />
</div>
</div>
<div className="fcard-foot">
<span className="tag">{card.tag}</span>
</div>
</div>
);
},
);
// 2 — 오전 집중 (task, 체크 토글)
export const TaskFlowCard = forwardRef<
HTMLDivElement,
{
card: TaskCard;
person?: JourneyPerson;
done: boolean;
onToggle: () => void;
hover: Hover;
}
>(function TaskFlowCard({ card, person, done, onToggle, hover }, ref) {
const pe = person ?? FALLBACK_PERSON;
return (
<div
className={hover.className}
ref={ref}
onMouseEnter={hover.onMouseEnter}
onMouseLeave={hover.onMouseLeave}
>
<div className="fcard-row">
<div
className="fcheck"
onClick={(e) => {
e.stopPropagation();
onToggle();
}}
role="button"
tabIndex={0}
aria-pressed={done}
aria-label={card.title}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
e.stopPropagation();
onToggle();
}
}}
>
<Icon name="tick" w={3} />
</div>
<div className="fc-main">
<div className="fc-title">{card.title}</div>
<div className="fc-meta">{card.meta}</div>
</div>
<div className="fc-who" style={{ background: pe.color }} title={pe.name}>
{pe.initial}
</div>
</div>
</div>
);
});
// 3 — 오후 협업 (meet)
export const MeetFlowCard = forwardRef<
HTMLDivElement,
{ card: MeetCard; person?: JourneyPerson; hover: Hover }
>(function MeetFlowCard({ card, person, hover }, ref) {
const pe = person ?? FALLBACK_PERSON;
return (
<div
className={hover.className}
ref={ref}
onMouseEnter={hover.onMouseEnter}
onMouseLeave={hover.onMouseLeave}
>
<div className="fcard-row">
<div className="fc-av" style={{ background: pe.color }}>
{pe.initial}
</div>
<div className="fc-main">
<div className="fc-title">{card.title}</div>
<div className="fc-meta">{card.meta}</div>
</div>
{card.soon ? (
<span className="mini soon"></span>
) : (
<div className="fc-time">{card.time}</div>
)}
</div>
</div>
);
});