feat: 세션 중, 끝났을 때 목표 표시
This commit is contained in:
@@ -54,7 +54,7 @@
|
||||
--card-foreground: oklch(0.129 0.042 264.695);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(15.152% 0.01301 277.362);
|
||||
--primary: oklch(0.208 0.042 265.755);
|
||||
--primary: oklch(0.574 0.202 262);
|
||||
--primary-foreground: oklch(0.984 0.003 247.858);
|
||||
--secondary: oklch(0.968 0.007 247.896);
|
||||
--secondary-foreground: oklch(0.208 0.042 265.755);
|
||||
@@ -65,7 +65,7 @@
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.929 0.013 255.508);
|
||||
--input: oklch(0.929 0.013 255.508);
|
||||
--ring: oklch(0.704 0.04 256.788);
|
||||
--ring: oklch(0.62 0.202 262);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
|
||||
@@ -49,7 +49,7 @@ export default function HomePage() {
|
||||
params.set("mode", mode);
|
||||
|
||||
if (goal && goal.trim().length > 0) {
|
||||
localStorage.setItem("goal", goal.trim());
|
||||
localStorage.setItem("hushroom:session-goal", goal.trim());
|
||||
}
|
||||
|
||||
router.push(`/session?${params.toString()}`);
|
||||
@@ -197,7 +197,7 @@ function SessionGoalDialog({
|
||||
value={goal}
|
||||
onChange={(e) => setGoal(e.target.value)}
|
||||
placeholder="목표를 입력하세요"
|
||||
className="text-lg border-[#2F6FED] focus-visible:ring-[#2F6FED] focus-visible:ring-1"
|
||||
className="text-lg"
|
||||
autoFocus
|
||||
/>
|
||||
<div className="text-xs text-slate-500">
|
||||
@@ -209,11 +209,7 @@ function SessionGoalDialog({
|
||||
<Button variant="ghost" onClick={() => onOpenChange(false)}>
|
||||
취소
|
||||
</Button>
|
||||
<Button
|
||||
onClick={onStart}
|
||||
className="rounded-xl bg-[#2F6FED]"
|
||||
disabled={!mode}
|
||||
>
|
||||
<Button onClick={onStart} className="rounded-xl" disabled={!mode}>
|
||||
시작하기
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"use client";
|
||||
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
import { useMemo } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
|
||||
type Mode = "freeflow" | "sprint" | "deepwork";
|
||||
|
||||
@@ -34,11 +34,17 @@ export default function SessionEndPage() {
|
||||
const router = useRouter();
|
||||
const params = useSearchParams();
|
||||
|
||||
const mode = useMemo(() => clampMode(params.get("mode")), [params]);
|
||||
const elapsed = useMemo(() => {
|
||||
const v = Number(params.get("elapsed") ?? "0");
|
||||
const [elapsed, setElapsed] = useState(() => {
|
||||
const v = Number(localStorage.getItem("hushroom:session-elapsed") ?? "0");
|
||||
return Number.isFinite(v) ? v : 0;
|
||||
}, [params]);
|
||||
});
|
||||
|
||||
const [goal, setGoal] = useState(() => {
|
||||
const goal = localStorage.getItem("hushroom:session-goal");
|
||||
return goal;
|
||||
});
|
||||
|
||||
const mode = useMemo(() => clampMode(params.get("mode")), [params]);
|
||||
|
||||
return (
|
||||
<main className="min-h-screen w-full" style={{ backgroundColor: BG }}>
|
||||
@@ -59,6 +65,22 @@ export default function SessionEndPage() {
|
||||
<div className="mt-3 text-[44px] font-semibold leading-none text-slate-900 tabular-nums">
|
||||
{hhmmss(elapsed)}
|
||||
</div>
|
||||
|
||||
{/* Goal */}
|
||||
{goal && (
|
||||
<div
|
||||
className="mt-4 rounded-2xl border bg-[#F1F5FF] px-4 py-3"
|
||||
style={{ borderColor: BORDER }}
|
||||
>
|
||||
<div className="text-xs font-semibold text-slate-600">
|
||||
이번 목표
|
||||
</div>
|
||||
<div className="mt-1 text-xl font-semibold text-slate-900 line-clamp-2">
|
||||
{goal}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-3 text-base text-slate-700">세션이 종료됐어요</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -293,13 +293,20 @@ export default function SessionPage() {
|
||||
}
|
||||
}, [elapsed, mode]);
|
||||
|
||||
useEffect(() => {
|
||||
const goal = localStorage.getItem("hushroom:session-goal") ?? "";
|
||||
setGoal(goal);
|
||||
}, []);
|
||||
|
||||
const timeMain = useMemo(() => {
|
||||
if (mode === "freeflow") return formatHHMMSS(elapsed);
|
||||
return formatHHMMSS(remaining);
|
||||
}, [elapsed, remaining, mode]);
|
||||
|
||||
const onEnd = () =>
|
||||
router.push(`/session/end?mode=${mode}&elapsed=${elapsed}`);
|
||||
const onEnd = () => {
|
||||
localStorage.setItem("hushroom:session-elapsed", elapsed.toString());
|
||||
router.push(`/session/end?mode=${mode}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<main className="min-h-screen w-full" style={{ backgroundColor: BG }}>
|
||||
@@ -330,6 +337,21 @@ export default function SessionPage() {
|
||||
? "원할 때 종료"
|
||||
: "한 번 실행되고 끝나면 요약으로 이동"}
|
||||
</div>
|
||||
|
||||
{/* Goal */}
|
||||
{goal && (
|
||||
<div
|
||||
className="mt-4 rounded-2xl border bg-[#F1F5FF] px-4 py-3"
|
||||
style={{ borderColor: BORDER }}
|
||||
>
|
||||
<div className="text-xs font-semibold text-slate-600">
|
||||
이번 목표
|
||||
</div>
|
||||
<div className="mt-1 text-xl font-semibold text-slate-900 line-clamp-2">
|
||||
{goal}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-[44px] font-semibold leading-none text-slate-900 tabular-nums">
|
||||
{timeMain}
|
||||
|
||||
18
src/components/Modal.tsx
Normal file
18
src/components/Modal.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
// import { ReactNode } from "react";
|
||||
|
||||
// interface ModalProps {
|
||||
// open: boolean;
|
||||
// onClose: () => void;
|
||||
// children: ReactNode;
|
||||
// }
|
||||
|
||||
// export default function Modal({ open, onClose, children }: ModalProps) {
|
||||
// return (
|
||||
// <div
|
||||
// onClick={onClose}
|
||||
// className={`flex fixed inset-0 justify-center items-center transition-colors ${open ? "visible bg-black/20" : "invisible"}`}
|
||||
// >
|
||||
// {children}
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
Reference in New Issue
Block a user