Skip to content
Merged
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
8 changes: 4 additions & 4 deletions src/features/notification/ui/notification-sse-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ function getPayloadId(payload: NotificationPayload | null): string | null {
return null;
}

function getPayloadTitle(payload: NotificationPayload | null): string | null {
function getPayloadMessage(payload: NotificationPayload | null): string | null {
if (!payload) return null;
const candidate = payload.title;
const candidate = payload.message;
return typeof candidate === "string" && candidate.length > 0 ? candidate : null;
}

Expand Down Expand Up @@ -117,8 +117,8 @@ export function NotificationSseProvider() {
if (payload) {
const didPrepend = prependNotification(queryClient, payload);

const title = getPayloadTitle(payload);
showToast.info(title ?? "새 알림이 도착했어요.");
const message = getPayloadMessage(payload);
showToast.info(message ?? "새 알림이 도착했어요.");

if (!didPrepend) {
queryClient.invalidateQueries({ queryKey: notificationKeys.all });
Expand Down
28 changes: 15 additions & 13 deletions src/screens/guide/ui/pages/guidebook-page1.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,38 @@ import { KEYWORDS } from "../../model/guide-data";

export function GuidebookPage1() {
return (
<div className="flex h-full flex-col items-center justify-center text-center">
<div className="flex h-full w-full flex-col items-center justify-center px-4 text-center sm:px-0">
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.1, duration: 0.6 }}
className="mb-6 max-[1024px]:mb-4"
className="mb-4 sm:mb-6"
>
<motion.h1
className="mb-3 text-4xl font-bold max-[1024px]:text-3xl"
className="mb-2 text-3xl font-bold sm:mb-3 sm:text-4xl"
style={{ color: "oklch(0.4758 0.2241 288.5)" }}
>
네덜란드 경매
</motion.h1>
<motion.p
className="text-base text-gray-600 max-[1024px]:text-sm"
className="text-sm text-gray-600 sm:text-base"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.3, duration: 0.6 }}
>
시간이 지날수록 가격이 내려가는 독특한 경매 방식
시간이 지날수록 가격이 <span className="text-red-500">내려가는</span> 독특한 경매 방식
</motion.p>
</motion.div>

<motion.div
className="mb-8 h-1 w-20 rounded-full max-[1024px]:mb-6 max-[1024px]:w-16"
className="mb-6 h-1 w-16 rounded-full sm:mb-8 sm:w-20"
style={{ backgroundColor: "oklch(0.4758 0.2241 288.5 / 0.3)" }}
initial={{ width: 0 }}
animate={{ width: 96 }}
transition={{ delay: 0.5, duration: 0.6 }}
/>

<div className="grid w-full max-w-3xl grid-cols-1 gap-4 max-[1024px]:gap-3 sm:grid-cols-3">
<div className="grid w-full max-w-3xl grid-cols-3 gap-2 sm:gap-4">
{KEYWORDS.map((keyword, index) => (
<motion.div
key={keyword.label}
Expand All @@ -47,37 +47,39 @@ export function GuidebookPage1() {
className="flex flex-col items-center"
>
<motion.div
className="mb-3 flex h-16 w-16 items-center justify-center rounded-full max-[1024px]:h-14 max-[1024px]:w-14"
className="mb-2 flex h-12 w-12 items-center justify-center rounded-full sm:mb-3 sm:h-16 sm:w-16"
style={{ backgroundColor: "oklch(0.4758 0.2241 288.5 / 0.1)" }}
whileHover={{ scale: 1.1, backgroundColor: "oklch(0.4758 0.2241 288.5 / 0.2)" }}
>
<keyword.icon
className="h-8 w-8 max-[1024px]:h-7 max-[1024px]:w-7"
className="h-6 w-6 sm:h-8 sm:w-8"
style={{ color: "oklch(0.4758 0.2241 288.5)" }}
/>
</motion.div>

<motion.h3
className="mb-1 text-lg font-semibold max-[1024px]:text-base"
className="mb-1 text-sm font-semibold sm:text-lg"
style={{ color: "oklch(0.4758 0.2241 288.5)" }}
>
{keyword.label}
</motion.h3>

<motion.div
className="mb-2 h-0.5 w-0"
className="mb-1.5 h-0.5 w-0 sm:mb-2"
style={{ backgroundColor: "oklch(0.4758 0.2241 288.5)" }}
animate={{ width: "100%" }}
transition={{ delay: 0.8 + index * 0.15, duration: 0.6 }}
/>

<p className="text-xs text-gray-600 max-[1024px]:text-[11px]">{keyword.description}</p>
<p className="text-[11px] leading-snug text-gray-600 sm:text-xs sm:leading-normal">
{keyword.description}
</p>
</motion.div>
))}
</div>

<motion.p
className="mt-8 max-w-2xl text-xs text-gray-500 max-[1024px]:mt-6 max-[1024px]:text-[11px]"
className="mt-5 max-w-2xl text-[11px] leading-snug text-gray-500 sm:mt-8 sm:text-xs sm:leading-normal"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 1.5, duration: 0.6 }}
Expand Down
24 changes: 12 additions & 12 deletions src/screens/guide/ui/pages/guidebook-page2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,33 @@ export function GuidebookPage2() {
}, []);

return (
<section className="flex h-full flex-col items-center justify-center gap-6 lg:gap-8 xl:gap-12">
<section className="flex h-full min-h-full w-full flex-col items-center justify-center gap-5 overflow-y-auto px-4 py-8 sm:gap-6 sm:overflow-visible sm:px-0 sm:py-0 lg:gap-8 xl:gap-12">
<motion.div
className="text-center"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<h2 className="text-muted-foreground text-base">
<h2 className="text-muted-foreground text-sm leading-relaxed sm:text-base sm:leading-normal">
판매자가 정한 <strong>Stop Loss</strong>까지
<br />
<span className="font-semibold text-red-500">5분</span>
마다 가격이 하락합니다
</h2>
</motion.div>

<div className="flex w-full max-w-lg flex-col gap-3">
<div className="flex w-full max-w-lg flex-col gap-3 sm:gap-3">
{priceData.map((point, index) => (
<motion.div
key={point.time}
className="flex flex-col gap-2 px-1"
className="flex flex-col gap-2 px-0.5 sm:gap-2 sm:px-1"
initial={{ opacity: 0 }}
animate={{ opacity: index < visibleBars ? 1 : 0 }}
transition={{ duration: 0.4 }}
>
<div className="flex items-center gap-4">
<motion.span
className="w-16 text-xs text-gray-500 sm:text-sm"
className="w-14 text-[11px] text-gray-500 sm:w-16 sm:text-sm"
initial={{ opacity: 0, x: -10 }}
animate={{ opacity: index < visibleBars ? 1 : 0, x: index < visibleBars ? 0 : -10 }}
transition={{ delay: 0.08, duration: 0.25 }}
Expand All @@ -55,7 +55,7 @@ export function GuidebookPage2() {

{point.label && (
<motion.span
className="rounded-full px-2.5 py-0.5 text-xs font-medium"
className="rounded-full px-2 py-0.5 text-[11px] font-medium sm:px-2.5 sm:text-xs"
style={{
backgroundColor:
index === priceData.length - 1
Expand All @@ -81,7 +81,7 @@ export function GuidebookPage2() {
</div>

<motion.div
className="h-fit rounded-lg py-2"
className="h-fit rounded-lg py-1.5 sm:py-2"
style={{
backgroundColor:
index === priceData.length - 1
Expand All @@ -100,9 +100,9 @@ export function GuidebookPage2() {
}}
transition={{ duration: 0.65, ease: [0.34, 1.56, 0.64, 1] }}
>
<div className="flex items-center justify-between px-3">
<div className="flex items-center justify-between px-2 sm:px-3">
<motion.span
className="text-md font-bold"
className="sm:text-md text-sm font-bold"
style={{
color: index === priceData.length - 1 ? "white" : "oklch(0.4758 0.2241 288.5)",
}}
Expand All @@ -118,7 +118,7 @@ export function GuidebookPage2() {

{index > 0 && (
<motion.div
className="rounded-full px-2 py-0.5 text-xs font-semibold"
className="rounded-full px-1.5 py-0.5 text-[11px] font-semibold sm:px-2 sm:text-xs"
style={{
backgroundColor:
index === priceData.length - 1
Expand All @@ -144,13 +144,13 @@ export function GuidebookPage2() {
</div>

<motion.div
className="rounded-xl px-3 py-2.5 text-center"
className="mt-3 rounded-xl px-3 py-3 text-center sm:py-2.5"
style={{ backgroundColor: "oklch(0.4758 0.2241 288.5 / 0.15)" }}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 2, duration: 0.6 }}
>
<p className="text-brand-text text-xs font-semibold">
<p className="text-brand-text text-[11px] font-semibold sm:text-xs">
💡 원하는 가격이 되면 즉시 구매할 수 있습니다
</p>
</motion.div>
Expand Down
64 changes: 31 additions & 33 deletions src/screens/guide/ui/pages/guidebook-page5.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,17 @@ export function GuidebookPage5() {
};

return (
<section className="flex h-full min-h-full w-full flex-col items-center justify-center">
<section className="flex h-full min-h-full w-full flex-col items-center justify-start gap-2 overflow-y-auto px-4 py-4 sm:justify-center sm:gap-3 sm:overflow-visible sm:px-0 sm:py-0 lg:gap-4 xl:gap-6">
<motion.div
className="mb-6 text-center max-[1024px]:mb-4"
className="mb-3 text-center sm:mb-6"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<p className="text-muted-foreground text-base max-[1024px]:text-sm">
5단계로 간편하게 경매를 등록하세요
</p>
<h2 className="text-muted-foreground text-sm sm:text-base">간편하게 경매를 등록하세요</h2>
</motion.div>

<div className="mb-8 flex flex-wrap items-center justify-center gap-3 max-[1024px]:mb-6 max-[1024px]:gap-2.5">
<div className="flex flex-wrap items-center justify-center gap-2 sm:gap-3">
{steps.map((step, index) => {
const isCompleted = completedSteps.includes(index);
const isCurrent = index === currentStep;
Expand All @@ -49,14 +47,14 @@ export function GuidebookPage5() {
<React.Fragment key={step.id}>
<motion.button
onClick={() => setCurrentStep(index)}
className="flex flex-col items-center gap-2 transition-all"
className="flex flex-col items-center gap-1.5 transition-all sm:gap-2"
initial={{ opacity: 0, scale: 0.8 }}
animate={{ opacity: 1, scale: 1 }}
transition={{ delay: index * 0.1 }}
whileHover={{ scale: 1.05 }}
>
<motion.div
className="flex h-12 w-12 items-center justify-center rounded-full border-2 transition-all max-[1024px]:h-10 max-[1024px]:w-10"
className="flex h-9 w-9 items-center justify-center rounded-full border-2 transition-all sm:h-12 sm:w-12"
style={{
borderColor,
backgroundColor,
Expand All @@ -74,27 +72,24 @@ export function GuidebookPage5() {
transition={{ duration: 1.5, repeat: Infinity }}
>
{isCompleted ? (
<CheckCircle className="h-6 w-6 text-white max-[1024px]:h-5 max-[1024px]:w-5" />
<CheckCircle className="size-5 text-white sm:size-6" />
) : (
React.createElement(step.icon, {
className: "h-5 w-5 max-[1024px]:h-4 max-[1024px]:w-4",
className: "size-4 sm:size-5",
style: {
color: iconColor,
},
})
)}
</motion.div>
<span
className="text-xs font-medium max-[1024px]:text-[11px]"
style={{ color: labelColor }}
>
<span className="text-xs font-medium sm:text-xs" style={{ color: labelColor }}>
Step {index + 1}
</span>
</motion.button>

{index < steps.length - 1 && (
<div
className="-mt-4 h-0.5 w-8 max-[1024px]:w-6"
className="-mt-3 h-0.5 w-3 sm:-mt-4 sm:w-4"
style={{
backgroundColor: isCompleted ? "oklch(0.4758 0.2241 288.5)" : "#E5E7EB",
}}
Expand All @@ -112,22 +107,20 @@ export function GuidebookPage5() {
transition={{ duration: 0.3 }}
className="mx-auto w-full max-w-xl"
>
<div className="bg-card rounded-2xl p-6 max-[1024px]:p-5">
<div className="mb-6 flex items-center gap-3">
<div className="bg-card rounded-2xl p-4 sm:p-6">
<div className="mb-4 flex items-center gap-2 sm:mb-6 sm:gap-3">
<div
className="flex h-10 w-10 items-center justify-center rounded-full max-[1024px]:h-9 max-[1024px]:w-9"
className="flex h-9 w-9 items-center justify-center rounded-full sm:h-10 sm:w-10"
style={{ backgroundColor: "oklch(0.4758 0.2241 288.5 / 0.1)" }}
>
{React.createElement(steps[currentStep].icon, {
className: "h-5 w-5 max-[1024px]:h-4 max-[1024px]:w-4",
className: "size-5",
style: { color: "oklch(0.4758 0.2241 288.5)" },
})}
</div>
<div>
<h3 className="text-lg font-semibold max-[1024px]:text-base">
{steps[currentStep].label}
</h3>
<p className="text-muted-foreground text-xs max-[1024px]:text-[11px]">
<h3 className="font-semibold">{steps[currentStep].label}</h3>
<p className="text-muted-foreground text-[11px] sm:text-xs">
{steps[currentStep].description}
</p>
</div>
Expand All @@ -136,7 +129,7 @@ export function GuidebookPage5() {
<motion.input
type="text"
placeholder={steps[currentStep].placeholder}
className="w-full rounded-lg border-2 px-4 py-3 text-sm transition-all outline-none max-[1024px]:px-3 max-[1024px]:py-2.5 max-[1024px]:text-xs"
className="w-full rounded-lg border-2 px-3 py-2 text-xs transition-all outline-none sm:px-4 sm:py-3 sm:text-sm"
style={{
borderColor: "oklch(0.4758 0.2241 288.5)",
boxShadow: "0 0 0 4px oklch(0.4758 0.2241 288.5 / 0.1)",
Expand All @@ -148,32 +141,37 @@ export function GuidebookPage5() {

<motion.button
onClick={handleComplete}
className="mt-4 flex w-full items-center justify-center gap-2 rounded-lg py-3 text-sm font-semibold text-white max-[1024px]:py-2.5 max-[1024px]:text-xs"
className="mt-3 flex w-full items-center justify-center gap-2 rounded-lg py-2.5 text-xs font-semibold text-white sm:mt-4 sm:py-3 sm:text-sm"
style={{ backgroundColor: "oklch(0.4758 0.2241 288.5)" }}
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
>
{currentStep < steps.length - 1 ? "다음 단계" : "경매 등록하기"}
<ChevronRight className="h-4 w-4 max-[1024px]:h-3.5 max-[1024px]:w-3.5" />
<ChevronRight className="size-4" />
</motion.button>
</div>
</motion.div>

{completedSteps.length === steps.length && (
<div className="h-11 text-center sm:h-11">
<motion.div
className="mt-6 text-center max-[1024px]:mt-4"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
initial={false}
animate={
completedSteps.length === steps.length ? { opacity: 1, y: 0 } : { opacity: 0, y: 20 }
}
transition={{ duration: 0.25 }}
className="flex justify-center"
style={{ pointerEvents: completedSteps.length === steps.length ? "auto" : "none" }}
>
<div
className="inline-flex items-center gap-2 rounded-full px-5 py-2.5 text-sm font-semibold text-white max-[1024px]:px-4 max-[1024px]:py-2 max-[1024px]:text-xs"
className="inline-flex items-center gap-2 rounded-full px-4 py-2 text-xs font-semibold text-white sm:px-5 sm:py-2.5 sm:text-sm"
style={{ backgroundColor: "oklch(0.4758 0.2241 288.5)" }}
aria-hidden={completedSteps.length !== steps.length}
>
<CheckCircle className="h-4 w-4 max-[1024px]:h-3.5 max-[1024px]:w-3.5" />
<CheckCircle className="size-3.5 sm:size-4" />
모든 단계 완료!
</div>
</motion.div>
)}
</div>
</section>
);
}