@edu-tosel/design 1.0.159 → 1.0.160
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/asset/SVG.d.ts +3 -3
- package/asset/sizes.d.ts +1 -1
- package/card/design/InfoCard.design.js +4 -4
- package/interface/Card.d.ts +1 -0
- package/layout/index.d.ts +1 -0
- package/layout/index.js +1 -0
- package/layout/template/MonthlyProgressReport/Layout.d.ts +4 -0
- package/layout/template/MonthlyProgressReport/Layout.js +52 -0
- package/layout/template/MonthlyProgressReport/Report.d.ts +11 -4
- package/layout/template/MonthlyProgressReport/Report.js +50 -33
- package/layout/template/MonthlyProgressReport/index.d.ts +5 -2
- package/layout/template/MonthlyProgressReport/index.js +2 -0
- package/layout/template/Row.d.ts +3 -3
- package/layout/template/Ticket/Layout.d.ts +5 -0
- package/layout/template/Ticket/Layout.js +48 -0
- package/layout/template/Ticket/Ticket.d.ts +18 -0
- package/layout/template/Ticket/Ticket.js +13 -0
- package/layout/template/Ticket/index.d.ts +5 -0
- package/layout/template/Ticket/index.js +5 -0
- package/layout/template/dashboard/mypage/Profile.d.ts +2 -2
- package/layout/template/home/layout/Navigation.js +32 -10
- package/package.json +2 -1
- package/util/compareDates.js +10 -10
- package/version.txt +1 -1
- package/widget/design/Label.design.js +1 -0
- package/widget/template/Label.d.ts +1 -1
package/asset/SVG.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ declare const SVG: {
|
|
|
27
27
|
Browser: ({ size, onClick }: import("./svg/Icon").IconProps) => import("react/jsx-runtime").JSX.Element;
|
|
28
28
|
Event: ({ size, onClick }: import("./svg/Icon").IconProps) => import("react/jsx-runtime").JSX.Element;
|
|
29
29
|
Document: ({ theme }: {
|
|
30
|
-
theme: "
|
|
30
|
+
theme: "blue" | "red";
|
|
31
31
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
32
32
|
};
|
|
33
33
|
Image: typeof Image;
|
|
@@ -37,8 +37,8 @@ declare const SVG: {
|
|
|
37
37
|
Minus: ({ onClick }: Operation) => import("react/jsx-runtime").JSX.Element;
|
|
38
38
|
Checked: ({ flag, size, theme, }: {
|
|
39
39
|
flag: boolean;
|
|
40
|
-
size?: number
|
|
41
|
-
theme?: import("../interface
|
|
40
|
+
size?: number;
|
|
41
|
+
theme?: import("../interface").Theme;
|
|
42
42
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
43
43
|
RightArrow: ({ onClick }: Operation) => import("react/jsx-runtime").JSX.Element;
|
|
44
44
|
};
|
package/asset/sizes.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const widthSizes: Record<
|
|
1
|
+
export declare const widthSizes: Record<number | string, string>;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { cn } from "../../util";
|
|
3
3
|
import Card from "./Card.design";
|
|
4
4
|
export function InfoCardDesign({ titles: { title, subtitle }, topRight, debug, image, option, children, }) {
|
|
5
|
-
const { titleBorder, text } = option ?? {};
|
|
5
|
+
const { titleBorder, text, titleColor } = option ?? {};
|
|
6
6
|
const container = {
|
|
7
7
|
displays: "flex flex-col",
|
|
8
8
|
paddings: "pt-5 px-5",
|
|
@@ -14,12 +14,12 @@ export function InfoCardDesign({ titles: { title, subtitle }, topRight, debug, i
|
|
|
14
14
|
sizes: "w-full h-13.25",
|
|
15
15
|
styles: `${titleBorder} border-b-2 pb-2.5`,
|
|
16
16
|
},
|
|
17
|
-
titleText:
|
|
18
|
-
subtitleText: "h-4.75 text-
|
|
17
|
+
titleText: `h-6 font-pretendard-bold text-xl w-52 truncate leading-none ${titleColor ?? "text-gray-dark"}`,
|
|
18
|
+
subtitleText: "h-4.75 text-sm font-medium flex items-center leading-none",
|
|
19
19
|
right: {
|
|
20
20
|
fontColor: `${text ?? "text-black"}`,
|
|
21
21
|
displays: "flex flex-col-reverse",
|
|
22
22
|
},
|
|
23
23
|
};
|
|
24
|
-
return (_jsxs(Card, { option: { ...option, className: cn(container) }, debug: debug, children: [_jsxs("div", { className: cn(topBox.container), children: [_jsxs("div", {
|
|
24
|
+
return (_jsxs(Card, { option: { ...option, className: cn(container) }, debug: debug, children: [_jsxs("div", { className: cn(topBox.container), children: [_jsxs("div", { children: [_jsx("div", { className: cn(topBox.titleText), children: title }), _jsx("div", { className: cn(topBox.subtitleText), children: subtitle ?? "" })] }), topRight] }), image && (_jsx("div", { className: "absolute right-5 top-5 w-22.5 h-22.5", children: _jsx("div", { className: "relative h-full w-full rounded-md overflow-hidden", children: _jsx("img", { className: "bg-cover rounded-md ", src: image }) }) })), children] }));
|
|
25
25
|
}
|
package/interface/Card.d.ts
CHANGED
package/layout/index.d.ts
CHANGED
|
@@ -20,3 +20,4 @@ export { default as Gomito } from "./template/Gomito";
|
|
|
20
20
|
export { default as RegexamLayout } from "./template/Regexam/Regexam.layout";
|
|
21
21
|
export { default as LegacyLayout } from "./template/Legacy/Legacy.layout";
|
|
22
22
|
export { default as MonthlyProgressReport } from "./template/MonthlyProgressReport";
|
|
23
|
+
export { default as Ticket } from "./template/Ticket";
|
package/layout/index.js
CHANGED
|
@@ -20,3 +20,4 @@ export { default as Gomito } from "./template/Gomito";
|
|
|
20
20
|
export { default as RegexamLayout } from "./template/Regexam/Regexam.layout";
|
|
21
21
|
export { default as LegacyLayout } from "./template/Legacy/Legacy.layout";
|
|
22
22
|
export { default as MonthlyProgressReport } from "./template/MonthlyProgressReport";
|
|
23
|
+
export { default as Ticket } from "./template/Ticket";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useRef } from "react";
|
|
3
|
+
import { cn } from "../../../util";
|
|
4
|
+
import { Label } from "../../../widget";
|
|
5
|
+
import Action from "../Action";
|
|
6
|
+
import ModalProvider from "../../../modal/design/Modal.design";
|
|
7
|
+
import { useActionStore } from "../../../store";
|
|
8
|
+
import { useReactToPrint } from "react-to-print";
|
|
9
|
+
import MonthlyProgressReport from ".";
|
|
10
|
+
export default function Layout({ props }) {
|
|
11
|
+
const { setModal } = useActionStore();
|
|
12
|
+
const container = {
|
|
13
|
+
displays: "flex flex-col justify-center items-center",
|
|
14
|
+
fonts: "font-pretendard-var",
|
|
15
|
+
sizes: "w-full min-h-screen",
|
|
16
|
+
};
|
|
17
|
+
const header = {
|
|
18
|
+
displays: "flex justify-end gap-3.5",
|
|
19
|
+
sizes: "w-full max-w-[297mm]",
|
|
20
|
+
};
|
|
21
|
+
const ref = useRef(null);
|
|
22
|
+
const handlePrint = useReactToPrint({
|
|
23
|
+
content: () => ref.current,
|
|
24
|
+
});
|
|
25
|
+
return (_jsx("div", { className: cn(container), children: _jsxs(Action.Show, { actions: [
|
|
26
|
+
[
|
|
27
|
+
"whatIsMPR",
|
|
28
|
+
_jsx(ModalProvider, { titles: {
|
|
29
|
+
title: "Monthly Progress Report",
|
|
30
|
+
subtitle: [
|
|
31
|
+
"MPR에서 학생들의 학습 성취도를 확인할 수 있습니다.",
|
|
32
|
+
"토셀 랩의 커리큘럼으로 학습 능력을 끌어올리세요!",
|
|
33
|
+
],
|
|
34
|
+
}, children: _jsx("div", { className: "flex justify-center items-center w-full h-80", children: _jsx("img", { src: "/images/progress/mock.png", className: "w-full h-full" }) }) }),
|
|
35
|
+
],
|
|
36
|
+
], children: [_jsxs("div", { className: cn(header), children: [_jsx(Label.Button, { title: "MPR\uC774\uB780?", option: {
|
|
37
|
+
width: "xs",
|
|
38
|
+
height: "xs",
|
|
39
|
+
background: "bg-blue-navy",
|
|
40
|
+
text: "text-white",
|
|
41
|
+
}, onClick: () => setModal("whatIsMPR") }), _jsx(Label.Button, { title: "\uAD50\uC7AC \uB77C\uC778\uC5C5", option: {
|
|
42
|
+
width: "xs",
|
|
43
|
+
height: "xs",
|
|
44
|
+
background: "bg-blue-navy",
|
|
45
|
+
text: "text-white",
|
|
46
|
+
}, onClick: () => window.open("https://smartstore.naver.com/tosel/shoppingstory/detail?id=5001356529&page=1") }), _jsx(Label.Button, { title: "\uCD9C\uB825\uD558\uAE30", option: {
|
|
47
|
+
width: "xs",
|
|
48
|
+
height: "xs",
|
|
49
|
+
background: "bg-blue-navy",
|
|
50
|
+
text: "text-white",
|
|
51
|
+
}, onClick: handlePrint })] }), _jsx(MonthlyProgressReport.Report, { ref: ref, props: props })] }) }));
|
|
52
|
+
}
|
|
@@ -19,18 +19,25 @@ export interface Result {
|
|
|
19
19
|
answers: number[];
|
|
20
20
|
userId: number;
|
|
21
21
|
}
|
|
22
|
-
interface ProgressReportProps {
|
|
22
|
+
export interface ProgressReportProps {
|
|
23
23
|
studentInfo: {
|
|
24
24
|
name: string;
|
|
25
25
|
birthday: string;
|
|
26
26
|
belong?: string;
|
|
27
27
|
academy?: string;
|
|
28
|
+
image: string;
|
|
28
29
|
};
|
|
29
|
-
results: Result[];
|
|
30
30
|
recentResult: Result & {
|
|
31
31
|
examName: string;
|
|
32
32
|
};
|
|
33
|
+
results: {
|
|
34
|
+
date: number;
|
|
35
|
+
score: number;
|
|
36
|
+
}[];
|
|
33
37
|
comment: string | string[];
|
|
38
|
+
commentType?: "director" | "tosel";
|
|
34
39
|
}
|
|
35
|
-
|
|
36
|
-
|
|
40
|
+
declare const _default: import("react").ForwardRefExoticComponent<{
|
|
41
|
+
props: ProgressReportProps;
|
|
42
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
43
|
+
export default _default;
|
|
@@ -3,13 +3,15 @@ import { InfoCard } from "../../../card";
|
|
|
3
3
|
import CardDesign from "../../../card/design/Card.design";
|
|
4
4
|
import { LineBreaks } from "../../../text";
|
|
5
5
|
import { cn } from "../../../util";
|
|
6
|
-
import { ResponsiveContainer,
|
|
6
|
+
import { ResponsiveContainer, PieChart, Pie, Cell, LineChart, XAxis, YAxis, Line, Legend, } from "recharts";
|
|
7
7
|
import moment from "moment-timezone";
|
|
8
|
-
|
|
8
|
+
import { forwardRef } from "react";
|
|
9
|
+
function ProgressReport({ props, }, ref) {
|
|
10
|
+
const { studentInfo, recentResult, comment, results, commentType = "tosel", } = props;
|
|
9
11
|
const container = {
|
|
10
12
|
displays: "flex justify-between ",
|
|
11
13
|
sizes: "w-[297mm] h-[210mm]",
|
|
12
|
-
boundaries: "
|
|
14
|
+
boundaries: " px-10 pt-7 pb-9",
|
|
13
15
|
fonts: "font-pretendard-var",
|
|
14
16
|
};
|
|
15
17
|
const leftBody = {
|
|
@@ -18,6 +20,7 @@ export default function ProgressReport({ studentInfo, recentResult, comment, })
|
|
|
18
20
|
const rightBody = {
|
|
19
21
|
displays: "flex flex-col",
|
|
20
22
|
};
|
|
23
|
+
// 계산 함수 (50점 만점 기준)
|
|
21
24
|
const calculate = (result, type) => {
|
|
22
25
|
const section1 = Object.values(result.report)
|
|
23
26
|
.slice(0, 4)
|
|
@@ -34,47 +37,61 @@ export default function ProgressReport({ studentInfo, recentResult, comment, })
|
|
|
34
37
|
return section2;
|
|
35
38
|
return total;
|
|
36
39
|
};
|
|
37
|
-
const
|
|
38
|
-
|
|
40
|
+
const preparePieChartData = (result, type) => {
|
|
41
|
+
const sectionScore = calculate(result, type);
|
|
42
|
+
const maxScore = 50; // 만점
|
|
43
|
+
const remainingScore = maxScore - sectionScore;
|
|
44
|
+
return [
|
|
45
|
+
{ name: "Score", value: sectionScore },
|
|
46
|
+
{ name: "Remaining", value: remainingScore },
|
|
47
|
+
];
|
|
48
|
+
};
|
|
49
|
+
const sectionWrapper = {
|
|
50
|
+
displays: "relative flex items-center justify-center overflow-visible",
|
|
39
51
|
sizes: "aspect-square ",
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
fonts: "text-4xl font-bold text-blue-navy",
|
|
53
|
+
};
|
|
54
|
+
const pieTray = {
|
|
55
|
+
displays: "absolute left-0 top-0",
|
|
56
|
+
sizes: "h-full w-full",
|
|
57
|
+
};
|
|
58
|
+
const gradientId = "gradient1";
|
|
59
|
+
const gradientDefinition = (_jsx("defs", { children: _jsxs("linearGradient", { id: gradientId, x1: "0%", y1: "0%", x2: "100%", y2: "100%", children: [_jsx("stop", { offset: "0%", style: { stopColor: "#82ca9d", stopOpacity: 1 } }), _jsx("stop", { offset: "100%", style: { stopColor: "#8884d8", stopOpacity: 1 } })] }) }));
|
|
60
|
+
const pieStyles = {
|
|
61
|
+
cx: "50%",
|
|
62
|
+
cy: "50%",
|
|
63
|
+
innerRadius: 35,
|
|
64
|
+
outerRadius: 49,
|
|
65
|
+
dataKey: "value",
|
|
66
|
+
nameKey: "name",
|
|
67
|
+
};
|
|
68
|
+
const cellStyles = {
|
|
69
|
+
stroke: "rgba(255, 255, 255, 0)",
|
|
42
70
|
};
|
|
43
|
-
return (_jsxs("div", { className: cn(container), children: [_jsxs("div", { className: cn(leftBody), children: [_jsxs("div", { className: "flex flex-col text-blue-navy pl-4 border-l-4 border-blue-navy", children: [_jsx("div", { className: "flex items-center", children: _jsx("img", { src: "/images/logos/lab-spiral.png", alt: "lab" }) }), _jsx("div", { className: "text-2xl leading-tight font-bold", children: "
|
|
71
|
+
return (_jsxs("div", { ref: ref, className: cn(container), children: [_jsxs("div", { className: cn(leftBody), children: [_jsxs("div", { className: "flex flex-col text-blue-navy pl-4 border-l-4 border-blue-navy", children: [_jsx("div", { className: "flex items-center", children: _jsx("img", { src: "/images/logos/lab-spiral.png", alt: "lab" }) }), _jsx("div", { className: "text-2xl leading-tight font-bold", children: "Monthly Progress Report" })] }), _jsxs("div", { className: "flex flex-col justify-between h-full", children: [_jsx(InfoCard.Student, { titles: {
|
|
44
72
|
title: studentInfo.name,
|
|
45
73
|
subtitle: studentInfo.birthday,
|
|
46
|
-
}, image:
|
|
74
|
+
}, image: studentInfo.image, data: {
|
|
47
75
|
belong: studentInfo.belong,
|
|
48
76
|
academy: studentInfo.academy,
|
|
49
77
|
}, option: {
|
|
50
|
-
boundary: "border-2 border-
|
|
78
|
+
boundary: "border-2 border-slate-300",
|
|
79
|
+
titleColor: "text-blue-navy",
|
|
51
80
|
} }), _jsx("div", { className: "h-96", children: _jsxs(CardDesign, { option: {
|
|
52
81
|
height: "full",
|
|
53
|
-
boundary: "border-2 border-
|
|
54
|
-
}, children: [_jsxs("div", { className: "flex flex-col justify-center border-b-
|
|
82
|
+
boundary: "border-2 border-slate-300 pt-5 px-6 pb-6",
|
|
83
|
+
}, children: [_jsxs("div", { className: "flex flex-col justify-center border-b-2 border-blue-navy pb-2.5", children: [_jsx("div", { className: " text-lg font-bold text-blue-navy", children: "\uCD5C\uADFC \uC2DC\uD5D8" }), _jsx("div", { children: recentResult.examName })] }), _jsxs("div", { className: "flex flex-col gap-y-7.5 absolute bottom-0 w-full px-3.5", children: [_jsxs("div", { className: "flex gap-x-12 justify-between w-full", children: [_jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-center mb-3.5 text-lg font-bold text-blue-navy", children: "Section I" }), _jsxs("div", { className: cn(sectionWrapper), children: [_jsx("div", { className: cn(pieTray), children: _jsx(ResponsiveContainer, { children: _jsxs(PieChart, { children: [gradientDefinition, _jsxs(Pie, { data: preparePieChartData(recentResult, "section1"), ...pieStyles, children: [_jsx(Cell, { fill: `url(#${gradientId})`, ...cellStyles }), _jsx(Cell, { fill: "rgba(255, 255, 255, 0)", ...cellStyles })] })] }) }) }), calculate(recentResult, "section1")] })] }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-center mb-3.5 text-lg font-bold text-blue-navy", children: "Section II" }), _jsxs("div", { className: cn(sectionWrapper), children: [_jsx("div", { className: cn(pieTray), children: _jsx(ResponsiveContainer, { children: _jsxs(PieChart, { children: [gradientDefinition, _jsxs(Pie, { data: preparePieChartData(recentResult, "section2"), ...pieStyles, children: [_jsx(Cell, { fill: `url(#${gradientId})`, ...cellStyles }), _jsx(Cell, { fill: "rgba(255, 255, 255, 0)", ...cellStyles })] })] }) }) }), calculate(recentResult, "section2")] })] })] }), _jsxs("div", { className: "flex gap-x-2 justify-end items-end font-bold text-blue-navy", children: [_jsx("div", { className: "text-xl", children: "total" }), _jsx("div", { className: "text-5xl leading-none ", children: calculate(recentResult) })] })] })] }) })] })] }), _jsxs("div", { className: cn(rightBody), children: [_jsx("div", { className: "h-12 flex justify-end text-blue-navy font-bold", children: _jsx("div", { children: moment(new Date()).format("YYYY-MM-DD HH:mm:ss") }) }), _jsxs("div", { className: "flex flex-col justify-between h-full", children: [_jsx("div", { className: "h-88", children: _jsx(CardDesign, { option: {
|
|
55
84
|
width: "xl",
|
|
56
85
|
height: "full",
|
|
57
|
-
boundary: "border-2 border-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
{
|
|
64
|
-
date: "2024-03-02",
|
|
65
|
-
score: 45,
|
|
66
|
-
},
|
|
67
|
-
// {
|
|
68
|
-
// date: "2024-03-03",
|
|
69
|
-
// score: 47,
|
|
70
|
-
// },
|
|
71
|
-
// {
|
|
72
|
-
// date: "2024-03-04",
|
|
73
|
-
// score: 53,
|
|
74
|
-
// },
|
|
75
|
-
], children: [_jsx(XAxis, { dataKey: "date" }), _jsx(YAxis, { dataKey: "score", scale: "log", domain: ["auto", "auto"] }), _jsx(Line, { type: "monotone", name: "Monthly Test", dataKey: "score", stroke: "#173A8B", fill: "#173A8B" }), _jsx(Legend, {})] }) }) }) }), _jsx("div", { className: "h-72", children: _jsxs(CardDesign, { option: {
|
|
86
|
+
boundary: "border-2 border-slate-300 pt-8 pr-8",
|
|
87
|
+
background: "bg-slate-200",
|
|
88
|
+
}, children: _jsx(ResponsiveContainer, { width: "100%", height: "100%", className: "absolute left-0 bottom-0", children: _jsxs(LineChart, { data: results.map((result) => ({
|
|
89
|
+
...result,
|
|
90
|
+
date: moment.unix(result.date).format("YY-MM-DD"),
|
|
91
|
+
})), children: [_jsx(XAxis, { dataKey: "date" }), _jsx(YAxis, { dataKey: "score", scale: "log", domain: ["auto", "auto"] }), _jsx(Line, { type: "monotone", name: "Monthly Test", dataKey: "score", stroke: "#173A8B", fill: "#173A8B" }), _jsx(Legend, {})] }) }) }) }), _jsx("div", { className: "h-72", children: _jsxs(CardDesign, { option: {
|
|
76
92
|
width: "xl",
|
|
77
93
|
height: "full",
|
|
78
|
-
boundary: "border-2 border-
|
|
79
|
-
}, children: [
|
|
94
|
+
boundary: "border-2 border-slate-300 p-5",
|
|
95
|
+
}, children: [_jsxs("div", { className: "flex text-blue-navy font-bold text-lg", children: [_jsx("div", { children: commentType === "director" ? "원장님" : "TOSEL Lab" }), _jsx("div", { children: "\uC758 \uCF54\uBA58\uD2B8" })] }), _jsx("div", { className: "h-52 overflow-y-scroll scrollbar-hidden text-sm mt-2.5", children: _jsx(LineBreaks, { texts: comment }) })] }) })] })] })] }));
|
|
80
96
|
}
|
|
97
|
+
export default forwardRef(ProgressReport);
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import Layout from "./Layout";
|
|
2
2
|
declare const MonthlyProgressReport: {
|
|
3
|
-
Report:
|
|
3
|
+
Report: import("react").ForwardRefExoticComponent<{
|
|
4
|
+
props: import("./Report").ProgressReportProps;
|
|
5
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
6
|
+
Layout: typeof Layout;
|
|
4
7
|
};
|
|
5
8
|
export default MonthlyProgressReport;
|
package/layout/template/Row.d.ts
CHANGED
|
@@ -3,9 +3,9 @@ declare function Row<T>({ item, dataField, onClick, buttons, dot }: RowProps<T>)
|
|
|
3
3
|
declare namespace Row {
|
|
4
4
|
var Board: <T>({ item, dataField, onClick, buttons, dot, option, }: RowProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
5
5
|
var Card: <T>({ item, dataField, stateAction, onClick, buttons, height, noPadding, noHover, dot, option, }: RowProps<T> & {
|
|
6
|
-
height?: string
|
|
7
|
-
noPadding?: boolean
|
|
8
|
-
noHover?: boolean
|
|
6
|
+
height?: string;
|
|
7
|
+
noPadding?: boolean;
|
|
8
|
+
noHover?: boolean;
|
|
9
9
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
10
10
|
}
|
|
11
11
|
export default Row;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useReactToPrint } from "react-to-print";
|
|
3
|
+
import { cn } from "../../../util";
|
|
4
|
+
import { Label } from "../../../widget";
|
|
5
|
+
import Ticket from "./Ticket";
|
|
6
|
+
import { useRef } from "react";
|
|
7
|
+
export default function Layout({ exam, name, birthday, level, code, }) {
|
|
8
|
+
const container = {
|
|
9
|
+
displays: "flex justify-center items-center",
|
|
10
|
+
sizes: "w-full min-h-screen",
|
|
11
|
+
};
|
|
12
|
+
const body = {
|
|
13
|
+
positions: "relative",
|
|
14
|
+
displays: "flex gap-x-3.5",
|
|
15
|
+
};
|
|
16
|
+
const ref = useRef(null);
|
|
17
|
+
const handlePrint = useReactToPrint({
|
|
18
|
+
content: () => ref.current,
|
|
19
|
+
});
|
|
20
|
+
return (_jsx("div", { className: cn(container), children: _jsxs("div", { className: cn(body), children: [_jsx(Ticket, { ref: ref, props: {
|
|
21
|
+
exam,
|
|
22
|
+
name,
|
|
23
|
+
birthday,
|
|
24
|
+
level,
|
|
25
|
+
code,
|
|
26
|
+
} }), _jsxs("div", { children: [_jsx(Label.Button, { title: "OMR \uC778\uC1C4", onClick: () => { }, option: {
|
|
27
|
+
width: "sm",
|
|
28
|
+
height: "xs",
|
|
29
|
+
background: "bg-green-dark",
|
|
30
|
+
text: "text-white",
|
|
31
|
+
} }), _jsx(Label.Button, { title: "\uC9C0\uB3C4\uB85C \uBCF4\uAE30", onClick: () => { }, option: {
|
|
32
|
+
width: "sm",
|
|
33
|
+
height: "xs",
|
|
34
|
+
background: "bg-green-dark",
|
|
35
|
+
text: "text-white",
|
|
36
|
+
} }), _jsx(Label.Button, { title: "\uC790\uC138\uD788 \uBCF4\uAE30", onClick: () => { }, option: {
|
|
37
|
+
width: "sm",
|
|
38
|
+
height: "xs",
|
|
39
|
+
background: "bg-green-dark",
|
|
40
|
+
text: "text-white",
|
|
41
|
+
} }), _jsx(Label.Button, { title: "\uC218\uD5D8\uD45C \uCD9C\uB825\uD558\uAE30", onClick: handlePrint, option: {
|
|
42
|
+
width: "md",
|
|
43
|
+
height: "sm",
|
|
44
|
+
background: "bg-white",
|
|
45
|
+
boundary: "border-2 border-green-dark",
|
|
46
|
+
text: "text-green-dark",
|
|
47
|
+
} })] })] }) }));
|
|
48
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface TicketProps {
|
|
2
|
+
exam: {
|
|
3
|
+
title: string;
|
|
4
|
+
hall: string;
|
|
5
|
+
room: string;
|
|
6
|
+
date: string;
|
|
7
|
+
startedAt: number;
|
|
8
|
+
endedAt: number;
|
|
9
|
+
};
|
|
10
|
+
name: string;
|
|
11
|
+
birthday: string;
|
|
12
|
+
level: string;
|
|
13
|
+
code: string;
|
|
14
|
+
}
|
|
15
|
+
declare const _default: import("react").ForwardRefExoticComponent<{
|
|
16
|
+
props: TicketProps;
|
|
17
|
+
} & import("react").RefAttributes<HTMLDivElement>>;
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef } from "react";
|
|
3
|
+
import { cn } from "../../../util";
|
|
4
|
+
import moment from "moment-timezone";
|
|
5
|
+
function Ticket({ props }, ref) {
|
|
6
|
+
const { title, date, startedAt, endedAt } = props.exam;
|
|
7
|
+
const container = {
|
|
8
|
+
sizes: "w-[340px] h-[700px]",
|
|
9
|
+
boundaries: "border-2",
|
|
10
|
+
};
|
|
11
|
+
return (_jsxs("div", { ref: ref, className: cn(container), children: [_jsx("div", { className: "text-xl font-bold", children: title }), _jsx("div", { className: "text-sm", children: date }), _jsx("div", { className: "text-sm", children: moment.unix(startedAt).format("YYYY-MM-DD") }), _jsx("div", { className: "text-sm", children: moment.unix(startedAt).format("YYYY년 MM월 DD일") })] }));
|
|
12
|
+
}
|
|
13
|
+
export default forwardRef(Ticket);
|
|
@@ -13,8 +13,8 @@ declare function Profile({ name, birthday, image, modify }: ProfileProps): impor
|
|
|
13
13
|
declare namespace Profile {
|
|
14
14
|
var Detail: ({ titles, infos, toggle, }: {
|
|
15
15
|
titles: Titles;
|
|
16
|
-
infos?: Info[]
|
|
17
|
-
toggle?: State<boolean
|
|
16
|
+
infos?: Info[];
|
|
17
|
+
toggle?: State<boolean>;
|
|
18
18
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
19
19
|
var Preview: ({ image, username, email, }: {
|
|
20
20
|
username: string;
|
|
@@ -74,7 +74,7 @@ export default function Navigation({ browser, calendar, notice, event, }) {
|
|
|
74
74
|
textStyles: "text-lg font-bold text-green-dark",
|
|
75
75
|
};
|
|
76
76
|
return (_jsxs(_Fragment, { children: [overlayCoverTransition((styles, item) => item && (_jsxs(animated.div, { style: styles, className: "bg-white h-screen fixed top-0 left-0 z-40 flex flex-col justify-center items-center overflow-hidden gap-y-14 ", children: [_jsx("img", { src: "/images/logos/tosel.png", alt: "tosel", width: 368.56, height: 80.07 }), _jsx("div", { children: "dashboard loading..." })] }))), overlayPopTransition((styles, item) => type &&
|
|
77
|
-
item && (_jsx(animated.div, { style: styles, className: cn(itemContainer), children: _jsxs("div", { className: cn(itemBody), children: [_jsx("div", { className: cn(scrollTitleWrapper), children: _jsx("div", { className: cn(scrollTitle), children: navigationTypeString[type] }) }), _jsx(NavigationItem, { type: type, calendar: calendar, notice: notice, event: event })] }) }))), _jsx("div", { className: "fixed bottom-0 md:top-1/2 md:-translate-y-1/2 flex justify-center items-center z-45", children: _jsxs("div", { onClick: (e) => e.stopPropagation(), className: cn(container), children: [_jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("calendar"), children: _jsx(SVG.Icon.Calendar, { size: isMobile ? "md" : "lg" }) }), _jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("notification"), children: _jsx(SVG.Icon.Notification, { size: isMobile ? "md" : "lg" }) }), _jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("search"), children: _jsx(SVG.Icon.Search, { size: isMobile ? "md" : "lg" }) }), _jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("browser"), children: _jsx(SVG.Icon.Browser, { size: isMobile ? "md" : "lg" }) }), _jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("event"), children: _jsx(SVG.Icon.Event, { size: isMobile ? "md" : "lg" }) })] }) })] }));
|
|
77
|
+
item && (_jsx(animated.div, { style: styles, className: cn(itemContainer), children: _jsxs("div", { className: cn(itemBody), onClick: (e) => e.stopPropagation(), children: [_jsx("div", { className: cn(scrollTitleWrapper), children: _jsx("div", { className: cn(scrollTitle), children: navigationTypeString[type] }) }), _jsx(NavigationItem, { type: type, calendar: calendar, notice: notice, event: event })] }) }))), _jsx("div", { className: "fixed bottom-0 md:top-1/2 md:-translate-y-1/2 flex justify-center items-center z-45", children: _jsxs("div", { onClick: (e) => e.stopPropagation(), className: cn(container), children: [_jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("calendar"), children: _jsx(SVG.Icon.Calendar, { size: isMobile ? "md" : "lg" }) }), _jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("notification"), children: _jsx(SVG.Icon.Notification, { size: isMobile ? "md" : "lg" }) }), _jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("search"), children: _jsx(SVG.Icon.Search, { size: isMobile ? "md" : "lg" }) }), _jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("browser"), children: _jsx(SVG.Icon.Browser, { size: isMobile ? "md" : "lg" }) }), _jsx("div", { className: cn(iconWrapper), onClick: () => handleOpen("event"), children: _jsx(SVG.Icon.Event, { size: isMobile ? "md" : "lg" }) })] }) })] }));
|
|
78
78
|
}
|
|
79
79
|
const navigationTypeString = {
|
|
80
80
|
calendar: "시험 접수 일정",
|
|
@@ -82,7 +82,7 @@ const navigationTypeString = {
|
|
|
82
82
|
event: "이벤트",
|
|
83
83
|
};
|
|
84
84
|
function NavigationItem({ type, calendar, notice, event, }) {
|
|
85
|
-
//scroll action
|
|
85
|
+
//scroll action
|
|
86
86
|
const container = {
|
|
87
87
|
displays: "relative flex flex-row md:flex-col",
|
|
88
88
|
sizss: "h-full",
|
|
@@ -116,16 +116,38 @@ function NavigationItem({ type, calendar, notice, event, }) {
|
|
|
116
116
|
};
|
|
117
117
|
const iconWrapper = {};
|
|
118
118
|
const item = {
|
|
119
|
-
displays: "flex-shrink-0 flex flex-col md:justify-
|
|
119
|
+
displays: "flex-shrink-0 flex flex-col md:justify-start snap-start",
|
|
120
120
|
};
|
|
121
|
+
const [currentTime, setCurrentTime] = useState(new Date());
|
|
122
|
+
const [scheduleState, setScheduleState] = useState(calendar.schedules.map(() => ({
|
|
123
|
+
isBeforeStart: false,
|
|
124
|
+
dDayStart: "",
|
|
125
|
+
isBeforeEnd: false,
|
|
126
|
+
dDayEnd: "",
|
|
127
|
+
})));
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
const interval = setInterval(() => {
|
|
130
|
+
setCurrentTime(new Date());
|
|
131
|
+
}, 1000);
|
|
132
|
+
return () => clearInterval(interval);
|
|
133
|
+
}, []);
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
const updatedScheduleState = calendar.schedules.map(({ applyStart, applyEnd }) => {
|
|
136
|
+
const startInfo = compareDates(applyStart);
|
|
137
|
+
const endInfo = compareDates(applyEnd);
|
|
138
|
+
return {
|
|
139
|
+
isBeforeStart: startInfo.isBefore,
|
|
140
|
+
dDayStart: startInfo.dDay,
|
|
141
|
+
isBeforeEnd: endInfo.isBefore,
|
|
142
|
+
dDayEnd: endInfo.dDay,
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
setScheduleState(updatedScheduleState);
|
|
146
|
+
}, [currentTime, calendar.schedules]);
|
|
121
147
|
if (type === "calendar")
|
|
122
|
-
return (_jsx("div", { className: cn(container), children: calendar.schedules.map(({ applyEnd,
|
|
123
|
-
const {
|
|
124
|
-
|
|
125
|
-
return (_jsxs("div", { onClick: onClick, className: cn(item, "w-[360px] h-[184px] rounded-[8px] p-5 bg-gray-light/30 border-1 border-gray-light"), children: [_jsxs("div", { className: cn(titleWrapper), children: [_jsx("div", { className: cn(titleText), children: title }), _jsx("div", { children: isbefore1 ?
|
|
126
|
-
_jsxs("div", { className: cn(tag, "bg-red-burgundy"), children: ["\uC811\uC218 ", dDay1] }) :
|
|
127
|
-
(isbefore2 ?
|
|
128
|
-
_jsx("div", { className: cn(tag, "bg-green-dark"), children: "\uC811\uC218\uC911" }) : _jsx("div", { className: cn(tag, "bg-gray-medium/30"), children: "\uB9C8\uAC10" })) })] }), !isbefore1 && isbefore2 ? _jsxs("div", { className: "text-xs", children: ["\uC811\uC218 \uB9C8\uAC10\uAE4C\uC9C0 ", dDay2] }) : "", _jsx("div", { children: _jsx("div", { className: "text-[16px] font-bold text-gray-dark", children: convertDateToString(applyEnd) }) })] }));
|
|
148
|
+
return (_jsx("div", { className: cn(container), children: calendar.schedules.map(({ applyEnd, title, onClick }, index) => {
|
|
149
|
+
const { isBeforeStart, dDayStart, isBeforeEnd, dDayEnd } = scheduleState[index];
|
|
150
|
+
return (_jsxs("div", { onClick: onClick, className: cn(item, "w-[360px] h-[184px] rounded-[8px] p-5 bg-gray-light/30 border-1 border-gray-light"), children: [_jsxs("div", { className: cn(titleWrapper), children: [_jsx("div", { className: cn(titleText), children: title }), _jsx("div", { children: isBeforeStart ? (_jsxs("div", { className: cn(tag, "bg-red-burgundy"), children: ["\uC811\uC218\uAE4C\uC9C0 ", dDayStart] })) : isBeforeEnd ? (_jsx("div", { className: cn(tag, "bg-green-dark"), children: "\uC811\uC218\uC911" })) : (_jsx("div", { className: cn(tag, "bg-gray-medium/30"), children: "\uB9C8\uAC10" })) })] }), !isBeforeStart && isBeforeEnd ? (_jsxs("div", { className: "text-xs", children: ["\uC811\uC218 \uB9C8\uAC10\uAE4C\uC9C0 ", dDayEnd] })) : (""), _jsx("div", { children: _jsx("div", { className: "text-[16px] font-bold text-gray-dark", children: convertDateToString(applyEnd) }) })] }));
|
|
129
151
|
}) }));
|
|
130
152
|
if (type === "notification")
|
|
131
153
|
return (_jsx("div", { className: cn(container), children: notice.announcements.map(({ title, date, description, onClick }) => (_jsxs("div", { onClick: onClick, className: cn(item, "h-[140px] box-shadow rounded-[10px] p-7.5"), children: [_jsxs("div", { children: [_jsx("div", { className: "text-[15px] text-gray-medium", children: date }), _jsx("div", { className: "text-[20px] font-bold text-gray-dark", children: title })] }), _jsx(LineBreaks, { texts: description, className: "text-gray-dark text-[18px]" })] }))) }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edu-tosel/design",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.160",
|
|
4
4
|
"description": "UI components for International TOSEL Committee",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jsx",
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"react-lottie-player": "^1.5.6",
|
|
31
31
|
"react-router-dom": "^6.21.3",
|
|
32
32
|
"react-spring": "^9.7.3",
|
|
33
|
+
"react-to-print": "^2.15.1",
|
|
33
34
|
"react-transition-group": "^4.4.5",
|
|
34
35
|
"react-youtube": "^10.1.0",
|
|
35
36
|
"recharts": "^2.11.0",
|
package/util/compareDates.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
import moment from "moment-timezone";
|
|
1
2
|
export default function compareDates(targetDate) {
|
|
2
|
-
const currentDate =
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const isBefore = KSTDate < targetDateKST;
|
|
7
|
-
const timeDiff = targetDateKST.getTime() - KSTDate.getTime();
|
|
3
|
+
const currentDate = moment();
|
|
4
|
+
const targetDateMoment = moment(targetDate).tz("Asia/Seoul");
|
|
5
|
+
const isBefore = currentDate.isBefore(targetDateMoment);
|
|
6
|
+
const timeDiff = targetDateMoment.diff(currentDate);
|
|
8
7
|
if (isBefore) {
|
|
9
8
|
if (timeDiff < 24 * 60 * 60 * 1000) {
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
9
|
+
const duration = moment.duration(timeDiff);
|
|
10
|
+
const hours = duration.hours();
|
|
11
|
+
const minutes = duration.minutes();
|
|
12
|
+
const seconds = duration.seconds();
|
|
13
13
|
return {
|
|
14
14
|
isBefore,
|
|
15
|
-
dDay: `${hours}
|
|
15
|
+
dDay: `${hours < 10 ? `0${hours}` : hours} : ${minutes < 10 ? `0${minutes}` : minutes} : ${seconds < 10 ? `0${seconds}` : seconds}`,
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
18
|
else {
|
package/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.160
|
|
@@ -35,6 +35,7 @@ export default function LabelDesign({ title, onClick, disabled, option, hoverSta
|
|
|
35
35
|
texts: text ?? "text-gray-dim",
|
|
36
36
|
animation: "duration-500",
|
|
37
37
|
fonts: "font-pretendard-light",
|
|
38
|
+
boundary,
|
|
38
39
|
styles: height === "xs" ||
|
|
39
40
|
height === "2xs" ||
|
|
40
41
|
height === "3xs" ||
|
|
@@ -2,7 +2,7 @@ import { LabelWidget } from "../../interface";
|
|
|
2
2
|
declare function Label({ title, option }: Omit<LabelWidget, "onClick">): import("react/jsx-runtime").JSX.Element;
|
|
3
3
|
declare namespace Label {
|
|
4
4
|
var Button: ({ title, hoverTitle, onClick, disabled, option, }: Omit<LabelWidget, "hoverState"> & {
|
|
5
|
-
hoverTitle?: string
|
|
5
|
+
hoverTitle?: string;
|
|
6
6
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
7
7
|
}
|
|
8
8
|
export default Label;
|