@edu-tosel/design 1.0.5 → 1.0.6

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.
Files changed (243) hide show
  1. package/.eslintrc.cjs +17 -0
  2. package/Dockerfile +16 -0
  3. package/LICENCE +19 -0
  4. package/README.md +20 -0
  5. package/docs/README.md +47 -0
  6. package/index.html +13 -0
  7. package/package.json +49 -28
  8. package/postcss.config.js +6 -0
  9. package/public/images/daeng.jpg +0 -0
  10. package/public/images/faker.jpg +0 -0
  11. package/public/images/haerin.png +0 -0
  12. package/public/images/haewon.png +0 -0
  13. package/public/images/hani.png +0 -0
  14. package/public/images/home/admin.png +0 -0
  15. package/public/images/home/dashboard.png +0 -0
  16. package/public/images/home/detection.png +0 -0
  17. package/public/images/home/homepage.png +0 -0
  18. package/public/images/home/olympiad.png +0 -0
  19. package/public/images/home/partner.png +0 -0
  20. package/public/images/home/report.png +0 -0
  21. package/public/images/home/space.png +0 -0
  22. package/public/images/home/sun.png +0 -0
  23. package/public/images/info.png +0 -0
  24. package/public/images/itc.png +0 -0
  25. package/public/images/jenkins.png +0 -0
  26. package/public/images/minji.png +0 -0
  27. package/public/images/seulgi.png +0 -0
  28. package/public/images/test-full.png +0 -0
  29. package/public/images/test-image.png +0 -0
  30. package/public/images/test-paper.png +0 -0
  31. package/public/images/tosel-blue-lab-spiral.png +0 -0
  32. package/public/images/tosel.png +0 -0
  33. package/public/images/yujin.png +0 -0
  34. package/public/videos/loading.gif +0 -0
  35. package/public/vite.svg +1 -0
  36. package/setupPackage.js +78 -0
  37. package/src/App.tsx +32 -0
  38. package/src/_components/asset/interface.ts +2 -0
  39. package/src/_components/asset/links.ts +17 -0
  40. package/src/_components/asset/mock/academies.ts +52 -0
  41. package/src/_components/asset/mock/chartData.ts +104 -0
  42. package/src/_components/asset/mock/exams.ts +42 -0
  43. package/src/_components/asset/mock/index.ts +2 -0
  44. package/src/_components/asset/mock/people.ts +291 -0
  45. package/src/_components/asset/mock/test.ts +67 -0
  46. package/src/_components/asset/navigation.ts +17 -0
  47. package/src/_components/asset/people.ts +226 -0
  48. package/src/_components/asset/planets.ts +49 -0
  49. package/src/_components/controller/store.ts +11 -0
  50. package/src/_components/hook/useRoute.ts +47 -0
  51. package/src/_components/hook/useTyping.ts +46 -0
  52. package/src/_components/types/Level.ts +1 -0
  53. package/src/_components/view/Explore.tsx +16 -0
  54. package/src/_components/view/Home.tsx +180 -0
  55. package/src/_components/view/LottiePlayer.tsx +17 -0
  56. package/src/app/admin/exam/page.tsx +36 -0
  57. package/src/app/admin/grade/page.tsx +5 -0
  58. package/src/app/admin/layout.tsx +56 -0
  59. package/src/app/admin/news/page.tsx +15 -0
  60. package/src/app/admin/page.tsx +42 -0
  61. package/src/app/admin/rnd/monthly-test/page.tsx +5 -0
  62. package/src/app/admin/rnd/page.tsx +17 -0
  63. package/src/app/admin/statistics/page.tsx +5 -0
  64. package/src/app/admin/user/page.tsx +147 -0
  65. package/src/app/agency/exam/page.tsx +5 -0
  66. package/src/app/agency/group/page.tsx +5 -0
  67. package/src/app/agency/layout.tsx +55 -0
  68. package/src/app/agency/page.tsx +68 -0
  69. package/src/app/agency/sales/page.tsx +5 -0
  70. package/src/app/convention/page.tsx +58 -0
  71. package/src/app/page.tsx +4 -0
  72. package/src/asset/fonts/Kostar.ttf +0 -0
  73. package/src/asset/fonts/Megrim.ttf +0 -0
  74. package/src/asset/fonts/NicoMoji.ttf +0 -0
  75. package/src/asset/fonts/Pretendard-Medium.otf +0 -0
  76. package/{board/index.d.ts → src/board/index.tsx} +4 -3
  77. package/src/board/template/CanvasBoard.tsx +17 -0
  78. package/src/board/template/ManageBoard.tsx +56 -0
  79. package/src/board/widget/Board.tsx +28 -0
  80. package/src/board/widget/DataField.tsx +70 -0
  81. package/src/board/widget/Header.tsx +63 -0
  82. package/src/board/widget/Tab.tsx +36 -0
  83. package/src/board/widget/Tags.tsx +81 -0
  84. package/{card/index.d.ts → src/card/index.tsx} +6 -5
  85. package/src/card/template/ChartCard.tsx +42 -0
  86. package/src/card/template/InfoCard.tsx +22 -0
  87. package/src/card/template/ProfileCard.tsx +36 -0
  88. package/src/card/template/RowCard.tsx +91 -0
  89. package/src/card/template/TableCard.tsx +41 -0
  90. package/src/card/template/TrumpCard.tsx +46 -0
  91. package/src/card/widget/Card.tsx +53 -0
  92. package/src/deck/Deck.tsx +46 -0
  93. package/{deck/index.d.ts → src/deck/index.tsx} +1 -1
  94. package/{index.d.ts → src/index.tsx} +11 -11
  95. package/src/interaction/Exception.tsx +10 -0
  96. package/src/interaction/LoadingSpinner.tsx +10 -0
  97. package/src/interaction/NoData.tsx +5 -0
  98. package/{interaction/index.d.ts → src/interaction/index.tsx} +2 -2
  99. package/src/interface/Board.ts +55 -0
  100. package/src/interface/Card.ts +66 -0
  101. package/src/interface/HTMLElement.ts +27 -0
  102. package/src/interface/Interaction.ts +4 -0
  103. package/src/interface/Menu.ts +5 -0
  104. package/src/interface/Modal.ts +19 -0
  105. package/{interface/Property.d.ts → src/interface/Property.ts} +46 -34
  106. package/src/interface/Widget.ts +4 -0
  107. package/{interface/index.d.ts → src/interface/index.ts} +3 -2
  108. package/src/layout/dashboard/Header.tsx +56 -0
  109. package/src/layout/dashboard/index.tsx +38 -0
  110. package/{layout/index.d.ts → src/layout/index.tsx} +1 -1
  111. package/src/main.tsx +10 -0
  112. package/src/menu/SideMenu.tsx +104 -0
  113. package/{menu/index.d.ts → src/menu/index.tsx} +1 -1
  114. package/src/modal/AlertModal.tsx +24 -0
  115. package/src/modal/ControllerModal.tsx +17 -0
  116. package/src/modal/Modal.tsx +66 -0
  117. package/src/modal/TestModal.tsx +19 -0
  118. package/{modal/index.d.ts → src/modal/index.tsx} +3 -3
  119. package/src/navigation/Navigation.tsx +37 -0
  120. package/{navigation/index.d.ts → src/navigation/index.tsx} +1 -1
  121. package/src/shelf/Shelf.tsx +3 -0
  122. package/{shelf/index.d.ts → src/shelf/index.tsx} +1 -1
  123. package/src/store/index.ts +66 -0
  124. package/src/text/LineBreaks.tsx +13 -0
  125. package/{text/index.d.ts → src/text/index.tsx} +1 -1
  126. package/src/util/classNames.ts +4 -0
  127. package/src/util/colors.ts +11 -0
  128. package/src/util/display.ts +31 -0
  129. package/src/util/displayResponsive.ts +17 -0
  130. package/{util/index.d.ts → src/util/index.ts} +7 -7
  131. package/src/util/pattern.ts +18 -0
  132. package/src/util/position.ts +43 -0
  133. package/src/util/shape.ts +3 -0
  134. package/src/vite-env.d.ts +1 -0
  135. package/tsconfig.build.json +42 -0
  136. package/tsconfig.json +28 -0
  137. package/tsconfig.node.json +10 -0
  138. package/vite.config.ts +10 -0
  139. package/board/index.js +0 -3
  140. package/board/template/CanvasBoard.d.ts +0 -2
  141. package/board/template/CanvasBoard.js +0 -10
  142. package/board/template/ManageBoard.d.ts +0 -4
  143. package/board/template/ManageBoard.js +0 -28
  144. package/board/widget/Board.d.ts +0 -2
  145. package/board/widget/Board.js +0 -16
  146. package/board/widget/DataField.d.ts +0 -6
  147. package/board/widget/DataField.js +0 -24
  148. package/board/widget/Header.d.ts +0 -2
  149. package/board/widget/Header.js +0 -22
  150. package/board/widget/Tab.d.ts +0 -4
  151. package/board/widget/Tab.js +0 -17
  152. package/board/widget/Tags.d.ts +0 -3
  153. package/board/widget/Tags.js +0 -30
  154. package/card/index.js +0 -5
  155. package/card/template/ChartCard.d.ts +0 -2
  156. package/card/template/ChartCard.js +0 -6
  157. package/card/template/ProfileCard.d.ts +0 -14
  158. package/card/template/ProfileCard.js +0 -8
  159. package/card/template/RowCard.d.ts +0 -5
  160. package/card/template/RowCard.js +0 -26
  161. package/card/template/TableCard.d.ts +0 -2
  162. package/card/template/TableCard.js +0 -12
  163. package/card/template/TrumpCard.d.ts +0 -2
  164. package/card/template/TrumpCard.js +0 -19
  165. package/card/widget/Card.d.ts +0 -2
  166. package/card/widget/Card.js +0 -45
  167. package/deck/Deck.d.ts +0 -16
  168. package/deck/Deck.js +0 -15
  169. package/deck/index.js +0 -1
  170. package/index.js +0 -11
  171. package/interaction/Exception.d.ts +0 -2
  172. package/interaction/Exception.js +0 -9
  173. package/interaction/LoadingSpinner.d.ts +0 -1
  174. package/interaction/LoadingSpinner.js +0 -5
  175. package/interaction/NoData.d.ts +0 -1
  176. package/interaction/NoData.js +0 -4
  177. package/interaction/index.js +0 -2
  178. package/interface/Board.d.ts +0 -57
  179. package/interface/Board.js +0 -1
  180. package/interface/Card.d.ts +0 -73
  181. package/interface/Card.js +0 -1
  182. package/interface/HTMLElement.d.ts +0 -13
  183. package/interface/HTMLElement.js +0 -1
  184. package/interface/Interaction.d.ts +0 -5
  185. package/interface/Interaction.js +0 -1
  186. package/interface/Modal.d.ts +0 -18
  187. package/interface/Modal.js +0 -1
  188. package/interface/Property.js +0 -14
  189. package/interface/Widget.d.ts +0 -4
  190. package/interface/Widget.js +0 -1
  191. package/interface/index.js +0 -2
  192. package/layout/dashboard/Header.d.ts +0 -5
  193. package/layout/dashboard/Header.js +0 -19
  194. package/layout/dashboard/index.d.ts +0 -7
  195. package/layout/dashboard/index.js +0 -10
  196. package/layout/index.js +0 -1
  197. package/menu/SideMenu.d.ts +0 -1
  198. package/menu/SideMenu.js +0 -14
  199. package/menu/index.js +0 -1
  200. package/modal/AlertModal.d.ts +0 -2
  201. package/modal/AlertModal.js +0 -8
  202. package/modal/ControllerModal.d.ts +0 -6
  203. package/modal/ControllerModal.js +0 -6
  204. package/modal/Modal.d.ts +0 -2
  205. package/modal/Modal.js +0 -31
  206. package/modal/TestModal.d.ts +0 -8
  207. package/modal/TestModal.js +0 -6
  208. package/modal/index.js +0 -3
  209. package/navigation/Navigation.d.ts +0 -5
  210. package/navigation/Navigation.js +0 -24
  211. package/navigation/index.js +0 -1
  212. package/shelf/Shelf.d.ts +0 -4
  213. package/shelf/Shelf.js +0 -4
  214. package/shelf/index.js +0 -1
  215. package/store/index.d.ts +0 -16
  216. package/store/index.js +0 -39
  217. package/text/LineBreaks.d.ts +0 -4
  218. package/text/LineBreaks.js +0 -5
  219. package/text/index.js +0 -1
  220. package/util/classNames.d.ts +0 -1
  221. package/util/classNames.js +0 -4
  222. package/util/colors.d.ts +0 -10
  223. package/util/colors.js +0 -10
  224. package/util/display.d.ts +0 -25
  225. package/util/display.js +0 -25
  226. package/util/displayResponsive.d.ts +0 -3
  227. package/util/displayResponsive.js +0 -15
  228. package/util/index.js +0 -7
  229. package/util/pattern.d.ts +0 -7
  230. package/util/pattern.js +0 -15
  231. package/util/position.d.ts +0 -14
  232. package/util/position.js +0 -44
  233. package/util/shape.d.ts +0 -1
  234. package/util/shape.js +0 -3
  235. package/version.txt +0 -1
  236. /package/{asset → public}/fonts/Kostar.ttf +0 -0
  237. /package/{asset → public}/fonts/Megrim.ttf +0 -0
  238. /package/{asset → public}/fonts/NicoMoji.ttf +0 -0
  239. /package/{asset → public}/fonts/Pretendard-Medium.otf +0 -0
  240. /package/{asset → src/asset}/json/credit-lottie.json +0 -0
  241. /package/{asset → src/asset}/json/loading-lottie.json +0 -0
  242. /package/{asset → src/asset}/json/test.svg +0 -0
  243. /package/{globals.css → src/globals.css} +0 -0
@@ -0,0 +1,46 @@
1
+ import { useState, useEffect } from "react";
2
+
3
+ export default function useTyping(
4
+ text: string,
5
+ flag: boolean,
6
+ isTitleComplete: boolean,
7
+ delay = 100,
8
+ ) {
9
+ const [displayedText, setDisplayedText] = useState<string[]>([]);
10
+ const [index, setIndex] = useState<number>(0);
11
+ const [isStarted, setIsStarted] = useState<boolean>(false);
12
+ useEffect(() => {
13
+ if (flag && !isStarted) {
14
+ const startTimer = setTimeout(() => {
15
+ setIsStarted(true);
16
+ }, 1500);
17
+ return () => clearTimeout(startTimer);
18
+ }
19
+ if (isStarted && flag && index <= text.length) {
20
+ if (!isTitleComplete) {
21
+ setDisplayedText([]);
22
+ setIndex(0);
23
+ return;
24
+ }
25
+ const timer = setTimeout(() => {
26
+ const nextChar = text[index] || "";
27
+ setDisplayedText((prev) => {
28
+ if (nextChar === "\n") {
29
+ return [...prev, ""];
30
+ }
31
+ const last = prev[prev.length - 1] || "";
32
+ return [...prev.slice(0, -1), last + nextChar];
33
+ });
34
+ setIndex(index + 1);
35
+ }, delay);
36
+ return () => clearTimeout(timer);
37
+ }
38
+ return () => {
39
+ setDisplayedText([]);
40
+ setIndex(0);
41
+ setIsStarted(false);
42
+ };
43
+ }, [text, index, delay, flag, isTitleComplete, isStarted]);
44
+
45
+ return displayedText;
46
+ }
@@ -0,0 +1 @@
1
+ export type Level = "" | "PS" | "ST" | "BA" | "JR" | "HJ";
@@ -0,0 +1,16 @@
1
+ import { Link } from "react-router-dom";
2
+
3
+ export default function Explore() {
4
+ return (
5
+ <Link
6
+ to="/"
7
+ className="fixed bottom-16 right-16 flex h-20 w-20 z-50 items-center justify-center rounded-full bg-black/80 shadow-md duration-500 "
8
+ >
9
+ <img
10
+ src="/images/home/sun.png"
11
+ alt="explore another space"
12
+ className="h-16 w-16"
13
+ />
14
+ </Link>
15
+ );
16
+ }
@@ -0,0 +1,180 @@
1
+ import { useState, useEffect } from "react";
2
+ import { Link } from "react-router-dom";
3
+ import { absolute } from "../../util/position";
4
+ import { links } from "../asset/links";
5
+ import { center } from "../../util/display";
6
+ import { Planet, Status } from "../asset/interface";
7
+ import { planets } from "../asset/planets";
8
+ import useTyping from "../hook/useTyping";
9
+ import Explore from "./Explore";
10
+ import { useWidgetStore } from "../../store";
11
+
12
+ export default function Home() {
13
+ const { setView } = useWidgetStore();
14
+ const [planet, setPlanet] = useState<Planet>("homepage");
15
+ const [clickSun, setClickSun] = useState<boolean>(false);
16
+ const [clickPlanet, setClickPlanet] = useState<boolean>(false);
17
+ const [planetStatus, setPlanetStatus] = useState<Status>("waiting");
18
+ const { title, description } = planets[planet];
19
+
20
+ const [hover, setHover] = useState<string>("");
21
+
22
+ const toggleSun = () => setClickSun(true);
23
+ const togglePlanet = (planet: string) => {
24
+ setClickPlanet(!clickPlanet);
25
+ setView("preview");
26
+ setPlanet(planet as Planet);
27
+ };
28
+
29
+ useEffect(() => {
30
+ if (clickPlanet) {
31
+ const timerDoing = setTimeout(() => {
32
+ setPlanetStatus("doing");
33
+ const timerDone = setTimeout(() => setPlanetStatus("done"), 1500);
34
+ return () => clearTimeout(timerDone);
35
+ }, 1500);
36
+ return () => clearTimeout(timerDoing);
37
+ }
38
+ }, [clickPlanet]);
39
+
40
+ const toselClassNames = () => {
41
+ const classNames =
42
+ "text-white text-center text-8xl animate-in duration-2000 font-nicomoji ";
43
+ if (clickPlanet) return classNames + absolute.full.tl(-48, 0);
44
+ if (clickSun) return classNames + absolute.full.tl("1/10", 0);
45
+ return classNames + absolute.full.tl("1/5", 0);
46
+ };
47
+
48
+ const sunClassNames = [
49
+ clickSun ? "" : "cursor-pointer",
50
+ "h-48 w-48 animate-spin duration-300000",
51
+ ].join(" ");
52
+ const sunMoveClassNames = () => {
53
+ const classNames =
54
+ "absolute top-2/5 animate-in duration-1000 flex justify-center w-full ";
55
+ if (clickPlanet) return classNames + "-left-3/4";
56
+ if (clickSun) return classNames + "-left-1/2";
57
+ return classNames + "left-0";
58
+ };
59
+
60
+ const designSpaceClassNames = [
61
+ clickSun ? absolute.full.bl("5/100", 0) : absolute.full.bl("1/5", 0),
62
+ "text-white text-center text-3xl animate-in duration-2000 font-kostar ",
63
+ ].join(" ");
64
+ const planetsContainerClassNames = (index: number) =>
65
+ [
66
+ clickSun && !clickPlanet
67
+ ? `top-43/100 delay-${600 * (index + 1.5)}`
68
+ : "-top-36",
69
+ `left-${72 + 48 * index}`,
70
+ "absolute cursor-pointer animate-in duration-1000 z-40",
71
+ ].join(" ");
72
+
73
+ const planetsClassName = ["h-36 w-36 "].join(" ");
74
+ const planetContainerClassNames = () => {
75
+ // const classNames = "border-4 border-white rounded-full duration-2000 delay-3000";
76
+ const hide = absolute.tl("1/4", -500) + "duration-500";
77
+ const appear = absolute.tl("1/4", "5/100") + "duration-2000";
78
+ if (planetStatus === "waiting") {
79
+ return hide;
80
+ }
81
+ if (planetStatus === "doing") return [appear].join(" ");
82
+ return [appear, "hover:scale-110"].join(" ");
83
+ };
84
+ const planetClassNames = "animate-spin duration-60000";
85
+
86
+ const descriptionClassNames = () => {
87
+ if (!clickPlanet) return "hidden";
88
+ return [
89
+ absolute.tr("1/3", "5/100"),
90
+ center.col(6),
91
+ "font-kostar text-green-500 w-240",
92
+ ].join(" ");
93
+ };
94
+
95
+ const displayedTitle = useTyping(title, clickPlanet, true);
96
+ const isTitleComplete = displayedTitle.join("") === title;
97
+ const displayedDescription = useTyping(
98
+ description,
99
+ clickPlanet,
100
+ isTitleComplete,
101
+ 50
102
+ );
103
+ return (
104
+ <div
105
+ className={`${center.screen.default} relative min-h-screen animate-[slideBackground_20s_ease-in-out_infinite] bg-image-space bg-contain `}
106
+ >
107
+ <div className={toselClassNames()}>TOSEL</div>
108
+ <div className={sunMoveClassNames()}>
109
+ <img
110
+ onClick={toggleSun}
111
+ src="/images/home/sun.png"
112
+ alt="sun"
113
+ className={sunClassNames}
114
+ />
115
+ </div>
116
+ <div className={designSpaceClassNames}>DESIGN SPACE</div>
117
+ {links.map(({ title }, index) => (
118
+ <div key={title} className={planetsContainerClassNames(index)}>
119
+ <div className="relative h-full w-full delay-200 duration-500 hover:scale-110">
120
+ <img
121
+ src={"/images/home/" + title + ".png"}
122
+ onClick={() => togglePlanet(title)}
123
+ alt={title}
124
+ className={planetsClassName}
125
+ onMouseEnter={() => setHover(title)}
126
+ onMouseLeave={() => setHover("")}
127
+ />
128
+ {hover === title && !clickPlanet && (
129
+ <div className="absolute bottom-40 left-28 z-10 flex h-26 w-75 flex-col items-end gap-2">
130
+ <div className="font-megrim text-4xl text-white">{title}</div>
131
+ <img
132
+ src="/images/home/detection.png"
133
+ alt="prject"
134
+ className="z-0 h-full w-full"
135
+ />
136
+ </div>
137
+ )}
138
+ </div>
139
+ </div>
140
+ ))}
141
+ <div className={planetContainerClassNames()}>
142
+ <Link to={planets[planet].href} className="relative h-full w-full">
143
+ <img
144
+ src={"/images/home/" + planet + ".png"}
145
+ alt={planet}
146
+ className={planetClassNames}
147
+ />
148
+ </Link>
149
+ </div>
150
+ {clickPlanet ? (
151
+ <div className={descriptionClassNames()}>
152
+ {displayedTitle.map((line, index) => (
153
+ <div key={`title-${index}`} className="text-5xl font-bold">
154
+ {line}
155
+ </div>
156
+ ))}
157
+ <div className={center.col(2)}>
158
+ {isTitleComplete &&
159
+ displayedDescription &&
160
+ displayedDescription.map((line, index) => (
161
+ <div key={`desc-${index}`} className="text-2xl">
162
+ {line}
163
+ </div>
164
+ ))}
165
+ </div>
166
+ </div>
167
+ ) : null}
168
+ {planetStatus === "done" ? (
169
+ <button
170
+ onClick={() => {
171
+ setPlanetStatus("waiting");
172
+ setClickPlanet(!clickPlanet);
173
+ }}
174
+ >
175
+ <Explore />
176
+ </button>
177
+ ) : null}
178
+ </div>
179
+ );
180
+ }
@@ -0,0 +1,17 @@
1
+ import Lottie from "react-lottie-player";
2
+ import loading from "../../asset/json/loading-lottie.json";
3
+ import test from "../../asset/json/test.svg";
4
+
5
+ export default function LottiePlayer() {
6
+ return (
7
+ <div className="flex">
8
+ <Lottie
9
+ animationData={loading}
10
+ style={{ width: 1920, height: 1080 }}
11
+ play={true}
12
+ placeholder={test}
13
+ />
14
+ <img src={"/videos/loading.gif"} />
15
+ </div>
16
+ );
17
+ }
@@ -0,0 +1,36 @@
1
+ import { Exam, exams } from "../../../_components/asset/mock/exams";
2
+ import { ManageBoard } from "../../../board";
3
+ import { Card } from "../../../card/widget/Card";
4
+
5
+ export default function Exams() {
6
+ return (
7
+ <ManageBoard
8
+ data={{
9
+ gap: 7.5,
10
+ dataSets: [
11
+ {
12
+ title: "진행 중인 시험",
13
+ items: exams.filter((exam) => exam.status === "active"),
14
+ renderItem: (exam) => <ExamComponent key={exam.id} {...exam} />,
15
+ },
16
+ {
17
+ title: "종료된 시험",
18
+ items: exams.filter((exam) => exam.status === "inactive"),
19
+ renderItem: (exam) => <ExamComponent key={exam.id} {...exam} />,
20
+ },
21
+ ],
22
+ }}
23
+ />
24
+ );
25
+ }
26
+
27
+ function ExamComponent({ title, type, managerUserId, createdAt }: Exam) {
28
+ return (
29
+ <Card>
30
+ <div>{title}</div>
31
+ <div>{type}</div>
32
+ <div>{managerUserId}</div>
33
+ <div>{createdAt}</div>
34
+ </Card>
35
+ );
36
+ }
@@ -0,0 +1,5 @@
1
+ import { CanvasBoard } from "../../../board";
2
+
3
+ export default function Grade() {
4
+ return <CanvasBoard>Grade</CanvasBoard>;
5
+ }
@@ -0,0 +1,56 @@
1
+ import { Link, useLocation } from "react-router-dom";
2
+ import { buttonClassNames } from "../../navigation";
3
+ import Explore from "../../_components/view/Explore";
4
+ import { DashboardLayout } from "../../layout";
5
+
6
+ const navigations = [
7
+ {
8
+ href: "/admin",
9
+ title: "홈",
10
+ },
11
+ {
12
+ href: "/admin/user",
13
+ title: "회원관리",
14
+ },
15
+ {
16
+ href: "/admin/exam",
17
+ title: "시험관리",
18
+ },
19
+ {
20
+ href: "/admin/rnd",
21
+ title: "연구/개발",
22
+ },
23
+ {
24
+ href: "/admin/news",
25
+ title: "마케팅/이벤트",
26
+ },
27
+ {
28
+ href: "/admin/statistics",
29
+ title: "통계",
30
+ },
31
+ ];
32
+
33
+ export default function Layout({ children }: { children: React.ReactNode }) {
34
+ const { pathname: nowPath } = useLocation();
35
+ const [title] = nowPath.split("/").slice(-1);
36
+ return (
37
+ <>
38
+ <DashboardLayout
39
+ subject={[title, "/images/tosel.png", "https://tosel.org"]}
40
+ colors={["gray-300", "black"]}
41
+ navigations={navigations.map(({ href, title }) => (
42
+ <Link
43
+ key={href}
44
+ to={href}
45
+ className={buttonClassNames(href, nowPath)}
46
+ >
47
+ {title}
48
+ </Link>
49
+ ))}
50
+ >
51
+ {children}
52
+ </DashboardLayout>
53
+ <Explore />
54
+ </>
55
+ );
56
+ }
@@ -0,0 +1,15 @@
1
+ import { Deck, Shelf } from "../../..";
2
+ import { CanvasBoard } from "../../../board";
3
+ import InfoCard from "../../../card/template/InfoCard";
4
+
5
+ export default function News() {
6
+ return (
7
+ <CanvasBoard>
8
+ <Shelf>
9
+ <Deck>
10
+ <InfoCard type="prpfileSmall" />
11
+ </Deck>
12
+ </Shelf>
13
+ </CanvasBoard>
14
+ );
15
+ }
@@ -0,0 +1,42 @@
1
+ import {
2
+ CanvasBoard,
3
+ ChartCard,
4
+ Deck,
5
+ Shelf,
6
+ TableCard,
7
+ TrumpCard,
8
+ } from "../..";
9
+ import { chartData, academies } from "../../_components/asset/mock";
10
+ import { useWidgetStore } from "./../../store";
11
+
12
+ export default function Admin() {
13
+ return (
14
+ <CanvasBoard>
15
+ <Shelf>
16
+ <Deck titles={{ title: "정기시험 접수자 추이" }}>
17
+ <ChartCard
18
+ data={chartData}
19
+ xAxis="date"
20
+ yAxis="pv"
21
+ lines={[
22
+ { dataKey: "uv", stroke: "blue" },
23
+ { dataKey: "pv", stroke: "red" },
24
+ ]}
25
+ />
26
+ </Deck>
27
+ <Deck titles={{ title: "학원 목록" }}>
28
+ <TrumpCard titles={{ title: "학원 목록" }} />
29
+ </Deck>
30
+ </Shelf>
31
+ <Shelf>
32
+ <Deck titles={{ title: "토셀랩 심사 대기" }}>
33
+ <TableCard
34
+ data={academies}
35
+ fields={{ a: "학원명", b: "학원장", c: "전화번호" }}
36
+ sizes={{ a: "1/3", b: "3/10" }}
37
+ />
38
+ </Deck>
39
+ </Shelf>
40
+ </CanvasBoard>
41
+ );
42
+ }
@@ -0,0 +1,5 @@
1
+ import { CanvasBoard } from "../../../..";
2
+
3
+ export default function MonthlyTestPage() {
4
+ return <CanvasBoard>Monthly fst-normal</CanvasBoard>;
5
+ }
@@ -0,0 +1,17 @@
1
+ import { TrumpCard } from "../../..";
2
+ import { CanvasBoard } from "../../../board";
3
+ import { useWidgetStore } from "../../../store";
4
+
5
+ export default function Rnd() {
6
+ const { setModal } = useWidgetStore();
7
+ return (
8
+ <CanvasBoard>
9
+ <TrumpCard
10
+ titles={{ title: "Monthly Test" }}
11
+ options={{
12
+ onClick: () => setModal("test"),
13
+ }}
14
+ />
15
+ </CanvasBoard>
16
+ );
17
+ }
@@ -0,0 +1,5 @@
1
+ import { CanvasBoard } from "../../../board";
2
+
3
+ export default function StatisticsPage() {
4
+ return <CanvasBoard>statistics</CanvasBoard>;
5
+ }
@@ -0,0 +1,147 @@
1
+ import { User, users } from "../../../_components/asset/mock/people";
2
+ import { Level } from "../../../_components/types/Level";
3
+ import { ManageBoard } from "../../../board";
4
+ import { useEffect, useState } from "react";
5
+ import SideMenu from "./../../../menu/SideMenu";
6
+ import RowCard from "../../../card/template/RowCard";
7
+ import { AlertModal } from "../../../modal";
8
+ import { LoadingSpinner } from "../../../interaction";
9
+ import NoData from "../../../interaction/NoData";
10
+ import { settings, userLogs } from "./../../../_components/asset/mock/test";
11
+
12
+ export default function Users() {
13
+ const [name, setName] = useState<string>("");
14
+ const [birthday, setBirthday] = useState<string>("");
15
+ const [level, setLevel] = useState<string>("");
16
+
17
+ const selectOptions: [Level, string][] = [
18
+ ["", "선택해주세요."],
19
+ ["PS", "Pre-Starter"],
20
+ ["ST", "Starter"],
21
+ ["BA", "Basic"],
22
+ ["JR", "Junior"],
23
+ ["HJ", "High Junior"],
24
+ ];
25
+
26
+ const selectUserOptions: [Level, string][] = [
27
+ ["PS", "Pre-Starter"],
28
+ ["ST", "Starter"],
29
+ ["BA", "Basic"],
30
+ ["JR", "Junior"],
31
+ ["HJ", "High Junior"],
32
+ ];
33
+
34
+ const [isLoading, setIsActive] = useState<boolean>(true);
35
+
36
+ useEffect(() => {
37
+ const timer = setTimeout(() => {
38
+ setIsActive(false);
39
+ }, 3000);
40
+
41
+ return () => clearTimeout(timer);
42
+ }, []);
43
+
44
+ const userTest = (prop?: "y" | "n") => {
45
+ return prop === "n" ? undefined : users;
46
+ };
47
+
48
+ const userTestValue = userTest("y");
49
+
50
+ return (
51
+ <ManageBoard
52
+ widgets={{
53
+ exceptions: [
54
+ [!userTestValue && !isLoading, <NoData />],
55
+ [isLoading, <LoadingSpinner />],
56
+ ],
57
+ components: [
58
+ [
59
+ "isLoading",
60
+ <AlertModal title="TITLE" scripts={{ script: "Script" }} />,
61
+ ],
62
+ ],
63
+ tabs: [
64
+ ["전체", () => {}],
65
+ ["학생", () => {}],
66
+ ["선생님", () => {}],
67
+ ],
68
+ menu: (
69
+ <SideMenu
70
+ log={{
71
+ prints: ["title"],
72
+ logs: userLogs,
73
+ }}
74
+ setting={settings}
75
+ />
76
+ ),
77
+ }}
78
+ header={{
79
+ title: "유저 관리",
80
+ tags: {
81
+ selects: [
82
+ {
83
+ width: "xs",
84
+ title: "레벨",
85
+ options: selectOptions,
86
+ onChange: setLevel,
87
+ },
88
+ ],
89
+ inputs: [
90
+ {
91
+ width: "xs",
92
+ title: "생년월일",
93
+ placeholder: "생일 입력",
94
+ onChange: setBirthday,
95
+ },
96
+ {
97
+ width: "sm",
98
+ title: "이름",
99
+ placeholder: "이름을 입력해주세요.",
100
+ onChange: setName,
101
+ },
102
+ ],
103
+ },
104
+ }}
105
+ data={{
106
+ dataField: {
107
+ fields: {
108
+ id: "ID",
109
+ name: "이름",
110
+ level: "레벨",
111
+ },
112
+ sizes: {
113
+ id: "8",
114
+ name: "25",
115
+ level: "33",
116
+ },
117
+ },
118
+ dataSets: [
119
+ {
120
+ items: userTestValue?.filter(
121
+ (user) =>
122
+ user.level.includes(level) &&
123
+ user.birthday.includes(birthday) &&
124
+ user.name.includes(name)
125
+ ),
126
+ renderItem: (user) => (
127
+ <RowCard
128
+ key={user.id}
129
+ row={user}
130
+ fields={{
131
+ id: "text",
132
+ name: "text",
133
+ level: ["select", selectUserOptions],
134
+ }}
135
+ sizes={{
136
+ id: "8",
137
+ name: "25",
138
+ level: "33",
139
+ }}
140
+ />
141
+ ),
142
+ },
143
+ ],
144
+ }}
145
+ />
146
+ );
147
+ }
@@ -0,0 +1,5 @@
1
+ import { CanvasBoard } from "../../..";
2
+
3
+ export default function Exam() {
4
+ return <CanvasBoard>group</CanvasBoard>;
5
+ }
@@ -0,0 +1,5 @@
1
+ import { CanvasBoard } from "../../..";
2
+
3
+ export default function User() {
4
+ return <CanvasBoard>Test</CanvasBoard>;
5
+ }
@@ -0,0 +1,55 @@
1
+ import { Link, useLocation } from "react-router-dom";
2
+ import { buttonClassNames } from "../../navigation";
3
+ import Explore from "../../_components/view/Explore";
4
+ import { DashboardLayout } from "../../layout";
5
+
6
+ const navigations = [
7
+ {
8
+ href: "",
9
+ title: "홈",
10
+ },
11
+ {
12
+ href: "/user",
13
+ title: "단체관리",
14
+ },
15
+ {
16
+ href: "/exam",
17
+ title: "시험관리",
18
+ // 학생 관리, 학생 정보 수정 정기시험-기관시험-경시대회
19
+ },
20
+ {
21
+ href: "/sales",
22
+ title: "매출 현황",
23
+ // 본인지역 얼마나 잘됐는지
24
+ },
25
+ {
26
+ href: "/headquarter",
27
+ title: "소통해요",
28
+ // 소통해요
29
+ },
30
+ ];
31
+
32
+ export default function Layout({ children }: { children: React.ReactNode }) {
33
+ const { pathname: nowPath } = useLocation();
34
+ const [title] = nowPath.split("/").slice(-1);
35
+ return (
36
+ <>
37
+ <DashboardLayout
38
+ subject={[title, "/images/tosel.png", "https://tosel.org"]}
39
+ colors={["green-dark/60", "green-dark"]}
40
+ navigations={navigations.map(({ href, title }) => (
41
+ <Link
42
+ key={href}
43
+ to={"/agency" + href}
44
+ className={buttonClassNames(href, nowPath, ["white", "green-dark"])}
45
+ >
46
+ {title}
47
+ </Link>
48
+ ))}
49
+ >
50
+ {children}
51
+ </DashboardLayout>
52
+ <Explore />
53
+ </>
54
+ );
55
+ }