@edu-tosel/design 1.0.297 → 1.0.298
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/card/design/RollCard.design.js +0 -1
- package/hook/useBussinessHours.js +0 -4
- package/layout/template/BbsLayout.js +1 -1
- package/layout/template/Event/Event.d.ts +1 -2
- package/layout/template/Event/Event.js +1 -76
- package/layout/template/Event/Many.js +1 -1
- package/layout/template/Event/One.d.ts +3 -1
- package/layout/template/Event/One.js +43 -3
- package/layout/template/Event/mock.d.ts +2 -0
- package/layout/template/Event/mock.js +95 -0
- package/layout/template/Event/molecule/Banner.d.ts +4 -2
- package/layout/template/Event/molecule/Banner.js +9 -9
- package/layout/template/Event/useEventElement.d.ts +2 -0
- package/layout/template/Event/useEventElement.js +117 -0
- package/package.json +1 -1
- package/util/createSearch.js +3 -2
- package/version.txt +1 -1
- package/widget/design/Label.design.js +2 -0
- package/widget/template/Select/Select.js +1 -1
|
@@ -23,7 +23,6 @@ export default function RollCardDesign({ titles, state, disabled, isFixed, child
|
|
|
23
23
|
sizes: "h-full",
|
|
24
24
|
styles: isFixed && "hidden",
|
|
25
25
|
};
|
|
26
|
-
console.log(isFixed, isOpen);
|
|
27
26
|
const isMobile = useResponsive("md");
|
|
28
27
|
return (_jsxs(Card, { option: {
|
|
29
28
|
width: "3xl",
|
|
@@ -9,10 +9,6 @@ function useBusinessHours() {
|
|
|
9
9
|
const dayOfWeek = kstTime.getDay(); // 0: 일요일, 1: 월요일, ..., 6: 토요일
|
|
10
10
|
const hour = kstTime.getHours(); // 0 - 23 시
|
|
11
11
|
const isCurrentlyOpen = dayOfWeek >= 1 && dayOfWeek <= 5 && hour >= 10 && hour < 17;
|
|
12
|
-
console.log("현재 KST:", kstTime.toString());
|
|
13
|
-
console.log("요일 (0=일요일):", dayOfWeek);
|
|
14
|
-
console.log("시간 (0-23):", hour);
|
|
15
|
-
console.log("영업 여부:", isCurrentlyOpen);
|
|
16
12
|
setIsOpen(isCurrentlyOpen);
|
|
17
13
|
}
|
|
18
14
|
// 처음에 한 번 실행하고, 1분마다 체크
|
|
@@ -12,7 +12,7 @@ export default function BbsLayout({ title, children, icon, links, }) {
|
|
|
12
12
|
sizes: "w-full max-w-[1200px]",
|
|
13
13
|
};
|
|
14
14
|
const body = {
|
|
15
|
-
displays: "flex
|
|
15
|
+
displays: "flex items-center gap-y-5 md:flex-row justify-between md:items-end",
|
|
16
16
|
sizes: "w-full md:h-[188px]",
|
|
17
17
|
boundaries: "pt-8 md:pt-0 px-5 md:px-12 md:pb-10 ",
|
|
18
18
|
};
|
|
@@ -18,12 +18,11 @@ interface EventButton extends _Button {
|
|
|
18
18
|
text?: string;
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
|
-
interface EventElement {
|
|
21
|
+
export interface EventElement {
|
|
22
22
|
tag: {
|
|
23
23
|
text: string;
|
|
24
24
|
style?: string;
|
|
25
25
|
};
|
|
26
26
|
button: EventButton;
|
|
27
27
|
}
|
|
28
|
-
export declare function convertEventElement(event: Event, diffTime?: string): EventElement;
|
|
29
28
|
export {};
|
|
@@ -1,76 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { toMoment } from "../../../util/moment";
|
|
3
|
-
import { gradient } from "../../../util";
|
|
4
|
-
export function convertEventElement(event, diffTime) {
|
|
5
|
-
const now = moment().tz("Asia/Seoul");
|
|
6
|
-
const startedAt = toMoment(event.startedAt);
|
|
7
|
-
const expiredAt = toMoment(event.expiredAt);
|
|
8
|
-
if (event.category === "notice") {
|
|
9
|
-
return {
|
|
10
|
-
tag: { text: "토셀 소식", style: "bg-blue-navy/10 text-blue-navy" },
|
|
11
|
-
button: {
|
|
12
|
-
title: "자세히 보기",
|
|
13
|
-
onClick: event.button?.onClick,
|
|
14
|
-
option: {
|
|
15
|
-
background: "bg-green-light",
|
|
16
|
-
text: "text-green-dark",
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
if (event.category === "event") {
|
|
22
|
-
if (now.isBefore(startedAt))
|
|
23
|
-
return {
|
|
24
|
-
tag: {
|
|
25
|
-
text: "오픈예정",
|
|
26
|
-
style: "bg-green-dark text-white",
|
|
27
|
-
},
|
|
28
|
-
button: {
|
|
29
|
-
title: `오픈까지 ${diffTime}`,
|
|
30
|
-
onClick: () => { },
|
|
31
|
-
option: {
|
|
32
|
-
background: "bg-gray-light",
|
|
33
|
-
text: "text-green-dark",
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
if (now.isAfter(startedAt) && now.isSameOrBefore(expiredAt))
|
|
39
|
-
return {
|
|
40
|
-
tag: {
|
|
41
|
-
text: `진행중 | D-${now.diff(expiredAt, "days")}`,
|
|
42
|
-
style: "bg-green-light text-green-dark",
|
|
43
|
-
},
|
|
44
|
-
button: {
|
|
45
|
-
title: event.button?.title ?? "참여하기",
|
|
46
|
-
onClick: event.button?.onClick,
|
|
47
|
-
option: {
|
|
48
|
-
background: gradient.bg.greenToRed,
|
|
49
|
-
text: "text-white",
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
|
-
};
|
|
53
|
-
if (now.isAfter(expiredAt))
|
|
54
|
-
return {
|
|
55
|
-
tag: { text: "마감", style: "bg-gray-light text-gray-medium" },
|
|
56
|
-
button: {
|
|
57
|
-
title: "이벤트가 마감되었어요",
|
|
58
|
-
onClick: () => { },
|
|
59
|
-
option: {
|
|
60
|
-
background: "bg-gray-light",
|
|
61
|
-
text: "text-gray-medium",
|
|
62
|
-
},
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
return {
|
|
66
|
-
tag: { text: "토셀 소식", style: "bg-blue-navy/10 text-blue-navy" },
|
|
67
|
-
button: {
|
|
68
|
-
title: "자세히 보기",
|
|
69
|
-
onClick: event.button?.onClick,
|
|
70
|
-
option: {
|
|
71
|
-
background: "bg-green-light",
|
|
72
|
-
text: "text-green-dark",
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
}
|
|
1
|
+
export {};
|
|
@@ -25,5 +25,5 @@ export default function Many({ events }) {
|
|
|
25
25
|
return false;
|
|
26
26
|
})
|
|
27
27
|
.filter((event) => event.title.includes(searchQuery));
|
|
28
|
-
return (_jsxs("div", { children: [_jsxs("div", { className: "flex flex-col sm:flex-row justify-between min-h-14.5 border-b-1", children: [_jsxs("div", { className: "w-full mb-5 h-9 sm:w-80 sm:h-9.5 flex items-center bg-[#f0f0f0]/10 rounded-xl", children: [_jsx(IoIosSearch, { className: "text-xl text-green-dark mr-3" }), _jsx("input", { type: "text", placeholder: "\uD0A4\uC6CC\uB4DC\uB97C \uC785\uB825\uD558\uC138\uC694.", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full h-full text-sm bg-[#f0f0f0]/10 placeholder:text-[#7f7f7f] placeholder:font-light outline-none" })] }), _jsx("div", { className: "flex h-9 pb-5 sm:pb-0 sm:h-9.5 items-center sm:justify-center ", children: ["모두보기", "진행 중", "예정된", "토셀소식"].map((item) => (_jsx("div", { className: `text-xs sm:text-2xs md:text-xs p-2 sm:p-3 flex items-center justify-center cursor-pointer rounded-lg ${filter === item ? "bg-green-dark/10 text-green-dark" : ""}`, onClick: () => setFilter(item), children: item }, item))) })] }), _jsx("div", { className: "pt-5 grid sm:grid-cols-2 mmd:grid-cols-3 gap-5 rounded-xl", children: filteredEvents.map((event) => (_jsxs("div", { onClick: event.onClick, className: "w-full max-h-84 shadow-md rounded-xl cursor-pointer box-shadow-green transition-all duration-500", children: [_jsx("div", { className: "w-full max-h-50 rounded-t-xl overflow-hidden relative", children: _jsx("img", { src: event.thumbnail, alt: "", className: "w-full" }) }), _jsxs("div", { className: "w-full min-h-34 p-8 gap-3 flex flex-col", children: [_jsx("div", { className: "flex items-center", children: _jsx(Tag, { event: event }) }), _jsx(LineBreaks, { className: "text-sm font-bold text-gray-dark flex items-
|
|
28
|
+
return (_jsxs("div", { children: [_jsxs("div", { className: "flex flex-col sm:flex-row justify-between min-h-14.5 border-b-1", children: [_jsxs("div", { className: "w-full mb-5 h-9 sm:w-80 sm:h-9.5 flex items-center bg-[#f0f0f0]/10 rounded-xl", children: [_jsx(IoIosSearch, { className: "text-xl text-green-dark mr-3" }), _jsx("input", { type: "text", placeholder: "\uD0A4\uC6CC\uB4DC\uB97C \uC785\uB825\uD558\uC138\uC694.", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), className: "w-full h-full text-sm bg-[#f0f0f0]/10 placeholder:text-[#7f7f7f] placeholder:font-light outline-none" })] }), _jsx("div", { className: "flex h-9 pb-5 sm:pb-0 sm:h-9.5 items-center sm:justify-center ", children: ["모두보기", "진행 중", "예정된", "토셀소식"].map((item) => (_jsx("div", { className: `text-xs sm:text-2xs md:text-xs p-2 sm:p-3 flex items-center justify-center cursor-pointer rounded-lg ${filter === item ? "bg-green-dark/10 text-green-dark" : ""}`, onClick: () => setFilter(item), children: item }, item))) })] }), _jsx("div", { className: "pt-5 grid sm:grid-cols-2 mmd:grid-cols-3 gap-5 rounded-xl", children: filteredEvents.map((event) => (_jsxs("div", { onClick: event.onClick, className: "w-full max-h-84 shadow-md rounded-xl cursor-pointer box-shadow-green transition-all duration-500", children: [_jsx("div", { className: "w-full max-h-50 rounded-t-xl overflow-hidden relative", children: _jsx("img", { src: event.thumbnail, alt: "", className: "w-full" }) }), _jsxs("div", { className: "w-full min-h-34 p-8 gap-3 flex flex-col", children: [_jsx("div", { className: "flex items-center", children: _jsx(Tag, { event: event }) }), _jsx(LineBreaks, { className: "text-sm font-bold text-gray-dark flex flex-col items-start", texts: event.title })] })] }, event.id))) })] }));
|
|
29
29
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Event } from "./Event";
|
|
2
|
+
import { Button } from "../../../interface";
|
|
2
3
|
interface EventProps {
|
|
3
4
|
event: Event;
|
|
5
|
+
button?: Button;
|
|
4
6
|
}
|
|
5
|
-
export default function One({ event }: EventProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
export default function One({ event, button }: EventProps): import("react/jsx-runtime").JSX.Element;
|
|
6
8
|
export {};
|
|
@@ -1,9 +1,49 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useEffect } from "react";
|
|
2
3
|
import { cn, isHTMLString } from "../../../util";
|
|
3
4
|
import BannerMolecule from "./molecule/Banner";
|
|
4
|
-
|
|
5
|
+
import gsap from "gsap";
|
|
6
|
+
import ScrollTrigger from "gsap/ScrollTrigger";
|
|
7
|
+
import { useResponsive } from "../../../hook";
|
|
8
|
+
import { Label } from "../../../widget";
|
|
9
|
+
gsap.registerPlugin(ScrollTrigger);
|
|
10
|
+
export default function One({ event, button }) {
|
|
11
|
+
const ref = useRef(null);
|
|
12
|
+
const isMD = useResponsive("md");
|
|
5
13
|
const container = {
|
|
6
|
-
|
|
14
|
+
trigger: ".test",
|
|
15
|
+
displays: "relative flex flex-col xl:flex-row xl: justify-end gap-x-8 gap-y-5",
|
|
16
|
+
paddings: "pt-5 sm:pt-0 pb-16",
|
|
7
17
|
};
|
|
8
|
-
|
|
18
|
+
const content = {
|
|
19
|
+
displays: "flex flex-col",
|
|
20
|
+
sizes: "w-full xl:max-w-[796px]",
|
|
21
|
+
spacing: "gap-y-8 ",
|
|
22
|
+
};
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (!isMD)
|
|
25
|
+
return;
|
|
26
|
+
const ctx = gsap.context(() => {
|
|
27
|
+
const scrollWrapper = ref.current;
|
|
28
|
+
if (scrollWrapper) {
|
|
29
|
+
const scrollTrigger = ScrollTrigger.create({
|
|
30
|
+
trigger: scrollWrapper,
|
|
31
|
+
start: "top-=120 top",
|
|
32
|
+
end: "bottom+=80 bottom",
|
|
33
|
+
pin: true,
|
|
34
|
+
markers: false,
|
|
35
|
+
});
|
|
36
|
+
return () => {
|
|
37
|
+
scrollTrigger.kill();
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
return () => ctx.revert();
|
|
42
|
+
}, [isMD]);
|
|
43
|
+
return (_jsxs("div", { className: cn(container), children: [_jsx(BannerMolecule, { props: { event }, ref: ref }), _jsxs("div", { className: cn(content), children: [isHTMLString(event.content) ? (_jsx("div", { className: "prose max-w-none", dangerouslySetInnerHTML: { __html: event.content } })) : (_jsx("div", { className: "prose max-w-none", children: event.content })), button && (_jsx(Label.Button, { title: button.title, onClick: button.onClick, option: {
|
|
44
|
+
width: "lg",
|
|
45
|
+
height: "2xl",
|
|
46
|
+
background: "bg-[#105652]/5 hover:bg-[#105652]/20",
|
|
47
|
+
text: "text-green-dark",
|
|
48
|
+
} }))] })] }));
|
|
9
49
|
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// 현재 시간 기준: 2025-04-18T14:26:20+09:00
|
|
2
|
+
export const events = [
|
|
3
|
+
{
|
|
4
|
+
id: 1,
|
|
5
|
+
category: "event",
|
|
6
|
+
thumbnail: "/images/promotion/future-event.png",
|
|
7
|
+
createdAt: 1681795580, // 2023-04-18
|
|
8
|
+
startedAt: 1735372800, // 2025-12-28 (미래)
|
|
9
|
+
expiredAt: 1737273600, // 2026-01-19 (미래)
|
|
10
|
+
title: "[오픈예정] 미래에 시작될 이벤트",
|
|
11
|
+
content: "미래 이벤트 테스트",
|
|
12
|
+
button: {
|
|
13
|
+
title: "오픈 알림 신청",
|
|
14
|
+
onClick: () => {
|
|
15
|
+
console.log("future event");
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 2,
|
|
21
|
+
category: "event",
|
|
22
|
+
thumbnail: "/images/promotion/ongoing-event.png",
|
|
23
|
+
createdAt: 1681795580, // 2023-04-18
|
|
24
|
+
startedAt: 1714435200, // 2024-05-01 (과거)
|
|
25
|
+
expiredAt: 1751328000, // 2025-07-01 (미래)
|
|
26
|
+
title: "[진행중] 현재 진행 중인 이벤트",
|
|
27
|
+
content: "진행중 이벤트 테스트",
|
|
28
|
+
button: {
|
|
29
|
+
title: "참여하기",
|
|
30
|
+
onClick: () => {
|
|
31
|
+
console.log("ongoing event");
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 3,
|
|
37
|
+
category: "event",
|
|
38
|
+
thumbnail: "/images/promotion/expired-event.png",
|
|
39
|
+
createdAt: 1681795580, // 2023-04-18
|
|
40
|
+
startedAt: 1704067200, // 2024-01-01 (과거)
|
|
41
|
+
expiredAt: 1709251200, // 2024-03-01 (과거)
|
|
42
|
+
title: "[마감] 이미 종료된 이벤트",
|
|
43
|
+
content: "종료된 이벤트 테스트",
|
|
44
|
+
button: {
|
|
45
|
+
title: "다시보기",
|
|
46
|
+
onClick: () => {
|
|
47
|
+
console.log("expired event");
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 4,
|
|
53
|
+
category: "event",
|
|
54
|
+
thumbnail: "/images/promotion/no-dates.png",
|
|
55
|
+
createdAt: 1681795580, // 2023-04-18
|
|
56
|
+
title: "[진행중] 시작/종료 시간이 없는 이벤트",
|
|
57
|
+
content: "시작/종료 시간 없음 테스트",
|
|
58
|
+
button: {
|
|
59
|
+
title: "참여하기",
|
|
60
|
+
onClick: () => {
|
|
61
|
+
console.log("no dates event");
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
id: 5,
|
|
67
|
+
category: "event",
|
|
68
|
+
thumbnail: "/images/promotion/same-dates.png",
|
|
69
|
+
createdAt: 1681795580, // 2023-04-18
|
|
70
|
+
startedAt: 1704067200, // 2024-01-01 (과거)
|
|
71
|
+
expiredAt: 1704067200, // 2024-01-01 (과거, startedAt과 동일)
|
|
72
|
+
title: "[마감] 시작/종료 시간이 동일한 이벤트",
|
|
73
|
+
content: "시작/종료 시간 동일 테스트",
|
|
74
|
+
button: {
|
|
75
|
+
title: "결과보기",
|
|
76
|
+
onClick: () => {
|
|
77
|
+
console.log("same dates event");
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: 6,
|
|
83
|
+
category: "notice",
|
|
84
|
+
thumbnail: "/images/promotion/notice.png",
|
|
85
|
+
createdAt: 1681795580, // 2023-04-18
|
|
86
|
+
title: "[공지] 일반 공지사항",
|
|
87
|
+
content: "공지사항 테스트",
|
|
88
|
+
button: {
|
|
89
|
+
title: "자세히 보기",
|
|
90
|
+
onClick: () => {
|
|
91
|
+
console.log("notice");
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
];
|
|
@@ -2,8 +2,10 @@ import { Event } from "../Event";
|
|
|
2
2
|
interface BannerProps {
|
|
3
3
|
event: Event;
|
|
4
4
|
}
|
|
5
|
-
export default function BannerMolecule({ event }: BannerProps): import("react/jsx-runtime").JSX.Element;
|
|
6
5
|
export declare function Tag({ event }: {
|
|
7
6
|
event: Event;
|
|
8
7
|
}): import("react/jsx-runtime").JSX.Element;
|
|
9
|
-
|
|
8
|
+
declare const _default: import("react").ForwardRefExoticComponent<{
|
|
9
|
+
props: BannerProps;
|
|
10
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
11
|
+
export default _default;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
2
|
+
import { forwardRef, useEffect, useState } from "react";
|
|
3
3
|
import { LineBreaks } from "../../../../text";
|
|
4
4
|
import { cn } from "../../../../util";
|
|
5
5
|
import { Label } from "../../../../widget";
|
|
6
|
-
import { convertEventElement } from "../Event";
|
|
7
6
|
import moment from "moment-timezone";
|
|
8
7
|
import { toDiffFromCurrent } from "../../../../util/moment";
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import { useEventElement } from "../useEventElement";
|
|
9
|
+
function BannerMolecule({ props }, ref) {
|
|
10
|
+
const { thumbnail, title } = props.event;
|
|
11
11
|
const [currentTime, setCurrentTime] = useState(moment);
|
|
12
12
|
useEffect(() => {
|
|
13
13
|
const timer = setInterval(() => {
|
|
@@ -15,21 +15,20 @@ export default function BannerMolecule({ event }) {
|
|
|
15
15
|
}, 1000);
|
|
16
16
|
return () => clearInterval(timer);
|
|
17
17
|
}, []);
|
|
18
|
-
const diffTime = toDiffFromCurrent(event.expiredAt, currentTime);
|
|
19
|
-
const { button } =
|
|
18
|
+
const diffTime = toDiffFromCurrent(props.event.expiredAt, currentTime);
|
|
19
|
+
const { button } = useEventElement(props.event, diffTime);
|
|
20
20
|
const container = {
|
|
21
|
-
positions: "relative",
|
|
22
21
|
displays: "flex flex-col sm:flex-row xl:flex-col xl:gap-5 justify-center xl:justify-start items-center xl:items-start",
|
|
23
22
|
sizes: "w-full xl:w-[320px]",
|
|
24
23
|
};
|
|
25
|
-
return (_jsxs("div", { className: cn(container), children: [_jsx("div", { className: "w-full
|
|
24
|
+
return (_jsxs("div", { ref: ref, className: cn(container), children: [_jsx("div", { className: "w-full sm:max-w-[352px] xl:max-w-max h-[200px] overflow-hidden bg-cover rounded-[12px]", children: _jsx("img", { src: thumbnail, className: "w-full h-full object-cover" }) }), _jsxs("div", { className: "flex flex-col gap-y-5 py-5 sm:px-5 xl:p-0 w-full sm:max-w-[320px] xl:max-w-full xl:w-full", children: [_jsxs("div", { className: "flex flex-col gap-y-3", children: [_jsx(Tag, { event: props.event }), _jsx(LineBreaks, { texts: title, className: "text-[16px] font-bold" })] }), _jsx(Label.Button, { title: button?.title, onClick: button?.onClick, option: {
|
|
26
25
|
width: "full",
|
|
27
26
|
background: button?.option?.background,
|
|
28
27
|
text: [button?.option?.text, "font-bold"].join(" "),
|
|
29
28
|
} })] })] }));
|
|
30
29
|
}
|
|
31
30
|
export function Tag({ event }) {
|
|
32
|
-
const { tag } =
|
|
31
|
+
const { tag } = useEventElement(event);
|
|
33
32
|
const container = {
|
|
34
33
|
selfAligns: "self-start",
|
|
35
34
|
displays: "flex items-center",
|
|
@@ -41,3 +40,4 @@ export function Tag({ event }) {
|
|
|
41
40
|
};
|
|
42
41
|
return _jsx("div", { className: cn(container), children: tag.text });
|
|
43
42
|
}
|
|
43
|
+
export default forwardRef(BannerMolecule);
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import moment from "moment-timezone";
|
|
2
|
+
import { toMoment } from "../../../util/moment";
|
|
3
|
+
import { gradient } from "../../../util";
|
|
4
|
+
import { useEffect, useState } from "react";
|
|
5
|
+
export function useEventElement(event, diffTime) {
|
|
6
|
+
const [now, setNow] = useState(moment().tz("Asia/Seoul"));
|
|
7
|
+
// 시작 시간과 종료 시간을 직접 변환하여 사용
|
|
8
|
+
const startedAt = event.startedAt ? toMoment(event.startedAt) : null;
|
|
9
|
+
const expiredAt = event.expiredAt ? toMoment(event.expiredAt) : null;
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
const interval = setInterval(() => {
|
|
12
|
+
setNow(moment().tz("Asia/Seoul"));
|
|
13
|
+
}, 1000);
|
|
14
|
+
return () => clearInterval(interval);
|
|
15
|
+
}, []);
|
|
16
|
+
if (event.category === "notice") {
|
|
17
|
+
return {
|
|
18
|
+
tag: { text: "토셀 소식", style: "bg-blue-navy/10 text-blue-navy" },
|
|
19
|
+
button: {
|
|
20
|
+
title: "자세히 보기",
|
|
21
|
+
onClick: event.button?.onClick,
|
|
22
|
+
option: {
|
|
23
|
+
background: "bg-green-light",
|
|
24
|
+
text: "text-green-dark",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (event.category === "event") {
|
|
30
|
+
// 시작 시간이 없는 경우
|
|
31
|
+
if (!startedAt) {
|
|
32
|
+
return {
|
|
33
|
+
tag: { text: "진행중", style: "bg-green-light text-green-dark" },
|
|
34
|
+
button: {
|
|
35
|
+
title: event.button?.title ?? "참여하기",
|
|
36
|
+
onClick: event.button?.onClick,
|
|
37
|
+
option: {
|
|
38
|
+
background: gradient.bg.greenToRed,
|
|
39
|
+
text: "text-white",
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// 시작 시간 이전인 경우
|
|
45
|
+
if (now.isBefore(startedAt)) {
|
|
46
|
+
return {
|
|
47
|
+
tag: {
|
|
48
|
+
text: "오픈예정",
|
|
49
|
+
style: "bg-green-dark text-white",
|
|
50
|
+
},
|
|
51
|
+
button: {
|
|
52
|
+
title: `오픈까지 ${diffTime}`,
|
|
53
|
+
onClick: () => { },
|
|
54
|
+
option: {
|
|
55
|
+
background: "bg-gray-light",
|
|
56
|
+
text: "text-green-dark",
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
// 종료 시간이 없는 경우 진행중으로 처리
|
|
62
|
+
if (!expiredAt) {
|
|
63
|
+
return {
|
|
64
|
+
tag: { text: "진행중", style: "bg-green-light text-green-dark" },
|
|
65
|
+
button: {
|
|
66
|
+
title: event.button?.title ?? "참여하기",
|
|
67
|
+
onClick: event.button?.onClick,
|
|
68
|
+
option: {
|
|
69
|
+
background: gradient.bg.greenToRed,
|
|
70
|
+
text: "text-white",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
// 종료된 경우 (현재 시간이 종료 시간과 같거나 이후)
|
|
76
|
+
if (now.isSameOrAfter(expiredAt || startedAt && expiredAt && startedAt.isSame(expiredAt))) {
|
|
77
|
+
return {
|
|
78
|
+
tag: { text: "마감", style: "bg-gray-light text-gray-medium" },
|
|
79
|
+
button: {
|
|
80
|
+
title: "이벤트가 마감되었어요",
|
|
81
|
+
onClick: () => { },
|
|
82
|
+
option: {
|
|
83
|
+
background: "bg-gray-light",
|
|
84
|
+
text: "text-gray-medium",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// 진행 중인 경우
|
|
90
|
+
const daysLeft = Math.ceil(expiredAt.diff(now, "days", true));
|
|
91
|
+
return {
|
|
92
|
+
tag: {
|
|
93
|
+
text: `진행중 | D-${daysLeft}`,
|
|
94
|
+
style: "bg-green-light text-green-dark",
|
|
95
|
+
},
|
|
96
|
+
button: {
|
|
97
|
+
title: event.button?.title ?? "참여하기",
|
|
98
|
+
onClick: event.button?.onClick,
|
|
99
|
+
option: {
|
|
100
|
+
background: gradient.bg.greenToRed,
|
|
101
|
+
text: "text-white",
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
tag: { text: "토셀 소식", style: "bg-blue-navy/10 text-blue-navy" },
|
|
108
|
+
button: {
|
|
109
|
+
title: "자세히 보기",
|
|
110
|
+
onClick: event.button?.onClick,
|
|
111
|
+
option: {
|
|
112
|
+
background: "bg-green-light",
|
|
113
|
+
text: "text-green-dark",
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
}
|
package/package.json
CHANGED
package/util/createSearch.js
CHANGED
|
@@ -215,7 +215,8 @@ function createSearch({ record, } = {}) {
|
|
|
215
215
|
entireMatch = entries
|
|
216
216
|
.filter(([_, value]) => {
|
|
217
217
|
const normalizedValue = value.toLowerCase();
|
|
218
|
-
return (normalizedValue === lowerQuery ||
|
|
218
|
+
return (normalizedValue === lowerQuery ||
|
|
219
|
+
value.includes(lowerQuery) ||
|
|
219
220
|
new RegExp(`\\b${lowerQuery}`).test(normalizedValue));
|
|
220
221
|
})
|
|
221
222
|
.map(([key, value]) => [
|
|
@@ -265,7 +266,7 @@ const getConstantVowel = (kor) => {
|
|
|
265
266
|
const ga = 44032;
|
|
266
267
|
let uni = kor.charCodeAt(0);
|
|
267
268
|
uni = uni - ga;
|
|
268
|
-
|
|
269
|
+
const fn = Math.floor(uni / 588);
|
|
269
270
|
// let sn = Math.floor((uni - (fn * 588)) / 28);
|
|
270
271
|
// let tn = uni % 28;
|
|
271
272
|
return fn < 0;
|
package/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.298
|
|
@@ -10,6 +10,7 @@ const widthSize = {
|
|
|
10
10
|
md: "w-45",
|
|
11
11
|
lg: "w-50",
|
|
12
12
|
full: "w-full",
|
|
13
|
+
auto: "w-auto",
|
|
13
14
|
};
|
|
14
15
|
const heightSize = {
|
|
15
16
|
"4xs": "h-5", // 20px
|
|
@@ -20,6 +21,7 @@ const heightSize = {
|
|
|
20
21
|
md: "h-12.25",
|
|
21
22
|
lg: "h-[45px]",
|
|
22
23
|
xl: "h-[50px]",
|
|
24
|
+
"2xl": "h-[60px]",
|
|
23
25
|
};
|
|
24
26
|
export default function LabelDesign({ title, onClick, disabled, option, hoverState, }) {
|
|
25
27
|
const [hover, setHover] = hoverState ?? [false, () => { }];
|
|
@@ -103,7 +103,7 @@ export default function Select({ state, selectOptions: selectOptionsInput, place
|
|
|
103
103
|
setIsOpen(false);
|
|
104
104
|
}, [flag]);
|
|
105
105
|
return (_jsxs("div", { className: cn(container), id: `select-box-${uniqueKey}`, onClick: (e) => e.stopPropagation(), children: [_jsx("button", { onClick: () => {
|
|
106
|
-
setIsOpen(!isOpen)
|
|
106
|
+
setIsOpen(!isOpen);
|
|
107
107
|
}, className: cn(button, "border-1 border-gray-light hover:border-none"), onMouseEnter: () => setIsHover(true), onMouseLeave: () => setIsHover(false), children: value ? (_jsx("div", { className: cn(label, "bg-white/0"), children: selectOptions?.find((option) => value === option.value)?.title })) : (_jsx("div", { className: "text-xs pl-1", children: placeholder ?? "선택해주세요" })) }), bodyTransitions((styles, item) => {
|
|
108
108
|
return (item && (_jsx(animated.div, { style: styles, className: cn(body), ref: listRef, children: selectOptions?.map(({ value, title }, order) => (_jsx("section", { children: _jsx("div", { className: cn(labelCoating), onClick: () => {
|
|
109
109
|
setValue(value);
|