@edu-tosel/design 1.0.4 → 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.
- package/.eslintrc.cjs +17 -0
- package/Dockerfile +16 -0
- package/LICENCE +19 -0
- package/README.md +20 -0
- package/docs/README.md +47 -0
- package/index.html +13 -0
- package/package.json +49 -28
- package/postcss.config.js +6 -0
- package/public/images/daeng.jpg +0 -0
- package/public/images/faker.jpg +0 -0
- package/public/images/haerin.png +0 -0
- package/public/images/haewon.png +0 -0
- package/public/images/hani.png +0 -0
- package/public/images/home/admin.png +0 -0
- package/public/images/home/dashboard.png +0 -0
- package/public/images/home/detection.png +0 -0
- package/public/images/home/homepage.png +0 -0
- package/public/images/home/olympiad.png +0 -0
- package/public/images/home/partner.png +0 -0
- package/public/images/home/report.png +0 -0
- package/public/images/home/space.png +0 -0
- package/public/images/home/sun.png +0 -0
- package/public/images/info.png +0 -0
- package/public/images/itc.png +0 -0
- package/public/images/jenkins.png +0 -0
- package/public/images/minji.png +0 -0
- package/public/images/seulgi.png +0 -0
- package/public/images/test-full.png +0 -0
- package/public/images/test-image.png +0 -0
- package/public/images/test-paper.png +0 -0
- package/public/images/tosel-blue-lab-spiral.png +0 -0
- package/public/images/tosel.png +0 -0
- package/public/images/yujin.png +0 -0
- package/public/videos/loading.gif +0 -0
- package/public/vite.svg +1 -0
- package/setupPackage.js +78 -0
- package/src/App.tsx +32 -0
- package/src/_components/asset/interface.ts +2 -0
- package/src/_components/asset/links.ts +17 -0
- package/src/_components/asset/mock/academies.ts +52 -0
- package/src/_components/asset/mock/chartData.ts +104 -0
- package/src/_components/asset/mock/exams.ts +42 -0
- package/src/_components/asset/mock/index.ts +2 -0
- package/src/_components/asset/mock/people.ts +291 -0
- package/src/_components/asset/mock/test.ts +67 -0
- package/src/_components/asset/navigation.ts +17 -0
- package/src/_components/asset/people.ts +226 -0
- package/src/_components/asset/planets.ts +49 -0
- package/src/_components/controller/store.ts +11 -0
- package/src/_components/hook/useRoute.ts +47 -0
- package/src/_components/hook/useTyping.ts +46 -0
- package/src/_components/types/Level.ts +1 -0
- package/src/_components/view/Explore.tsx +16 -0
- package/src/_components/view/Home.tsx +180 -0
- package/src/_components/view/LottiePlayer.tsx +17 -0
- package/src/app/admin/exam/page.tsx +36 -0
- package/src/app/admin/grade/page.tsx +5 -0
- package/src/app/admin/layout.tsx +56 -0
- package/src/app/admin/news/page.tsx +15 -0
- package/src/app/admin/page.tsx +42 -0
- package/src/app/admin/rnd/monthly-test/page.tsx +5 -0
- package/src/app/admin/rnd/page.tsx +17 -0
- package/src/app/admin/statistics/page.tsx +5 -0
- package/src/app/admin/user/page.tsx +147 -0
- package/src/app/agency/exam/page.tsx +5 -0
- package/src/app/agency/group/page.tsx +5 -0
- package/src/app/agency/layout.tsx +55 -0
- package/src/app/agency/page.tsx +68 -0
- package/src/app/agency/sales/page.tsx +5 -0
- package/src/app/convention/page.tsx +58 -0
- package/src/app/page.tsx +4 -0
- package/src/asset/fonts/Kostar.ttf +0 -0
- package/src/asset/fonts/Megrim.ttf +0 -0
- package/src/asset/fonts/NicoMoji.ttf +0 -0
- package/src/asset/fonts/Pretendard-Medium.otf +0 -0
- package/{board/index.d.ts → src/board/index.tsx} +4 -3
- package/src/board/template/CanvasBoard.tsx +17 -0
- package/src/board/template/ManageBoard.tsx +56 -0
- package/src/board/widget/Board.tsx +28 -0
- package/src/board/widget/DataField.tsx +70 -0
- package/src/board/widget/Header.tsx +63 -0
- package/src/board/widget/Tab.tsx +36 -0
- package/src/board/widget/Tags.tsx +81 -0
- package/{card/index.d.ts → src/card/index.tsx} +6 -5
- package/src/card/template/ChartCard.tsx +42 -0
- package/src/card/template/InfoCard.tsx +22 -0
- package/src/card/template/ProfileCard.tsx +36 -0
- package/src/card/template/RowCard.tsx +91 -0
- package/src/card/template/TableCard.tsx +41 -0
- package/src/card/template/TrumpCard.tsx +46 -0
- package/src/card/widget/Card.tsx +53 -0
- package/src/deck/Deck.tsx +46 -0
- package/{deck/index.d.ts → src/deck/index.tsx} +1 -1
- package/{index.d.ts → src/index.tsx} +11 -11
- package/src/interaction/Exception.tsx +10 -0
- package/src/interaction/LoadingSpinner.tsx +10 -0
- package/src/interaction/NoData.tsx +5 -0
- package/{interaction/index.d.ts → src/interaction/index.tsx} +2 -2
- package/src/interface/Board.ts +55 -0
- package/src/interface/Card.ts +66 -0
- package/src/interface/HTMLElement.ts +27 -0
- package/src/interface/Interaction.ts +4 -0
- package/src/interface/Menu.ts +5 -0
- package/src/interface/Modal.ts +19 -0
- package/{interface/Property.d.ts → src/interface/Property.ts} +46 -34
- package/src/interface/Widget.ts +4 -0
- package/{interface/index.d.ts → src/interface/index.ts} +3 -2
- package/src/layout/dashboard/Header.tsx +56 -0
- package/src/layout/dashboard/index.tsx +38 -0
- package/{layout/index.d.ts → src/layout/index.tsx} +1 -1
- package/src/main.tsx +10 -0
- package/src/menu/SideMenu.tsx +104 -0
- package/{menu/index.d.ts → src/menu/index.tsx} +1 -1
- package/src/modal/AlertModal.tsx +24 -0
- package/src/modal/ControllerModal.tsx +17 -0
- package/src/modal/Modal.tsx +66 -0
- package/src/modal/TestModal.tsx +19 -0
- package/{modal/index.d.ts → src/modal/index.tsx} +3 -3
- package/src/navigation/Navigation.tsx +37 -0
- package/{navigation/index.d.ts → src/navigation/index.tsx} +1 -1
- package/src/shelf/Shelf.tsx +3 -0
- package/{shelf/index.d.ts → src/shelf/index.tsx} +1 -1
- package/src/store/index.ts +66 -0
- package/src/text/LineBreaks.tsx +13 -0
- package/{text/index.d.ts → src/text/index.tsx} +1 -1
- package/src/util/classNames.ts +4 -0
- package/src/util/colors.ts +11 -0
- package/src/util/display.ts +31 -0
- package/src/util/displayResponsive.ts +17 -0
- package/{util/index.d.ts → src/util/index.ts} +7 -7
- package/src/util/pattern.ts +18 -0
- package/src/util/position.ts +43 -0
- package/src/util/shape.ts +3 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.build.json +42 -0
- package/tsconfig.json +28 -0
- package/tsconfig.node.json +10 -0
- package/vite.config.ts +10 -0
- package/board/index.js +0 -3
- package/board/template/CanvasBoard.d.ts +0 -2
- package/board/template/CanvasBoard.js +0 -10
- package/board/template/ManageBoard.d.ts +0 -4
- package/board/template/ManageBoard.js +0 -28
- package/board/widget/Board.d.ts +0 -2
- package/board/widget/Board.js +0 -16
- package/board/widget/DataField.d.ts +0 -6
- package/board/widget/DataField.js +0 -24
- package/board/widget/Header.d.ts +0 -2
- package/board/widget/Header.js +0 -22
- package/board/widget/Tab.d.ts +0 -4
- package/board/widget/Tab.js +0 -17
- package/board/widget/Tags.d.ts +0 -3
- package/board/widget/Tags.js +0 -30
- package/card/index.js +0 -5
- package/card/template/ChartCard.d.ts +0 -2
- package/card/template/ChartCard.js +0 -6
- package/card/template/ProfileCard.d.ts +0 -14
- package/card/template/ProfileCard.js +0 -8
- package/card/template/RowCard.d.ts +0 -5
- package/card/template/RowCard.js +0 -26
- package/card/template/TableCard.d.ts +0 -2
- package/card/template/TableCard.js +0 -12
- package/card/template/TrumpCard.d.ts +0 -2
- package/card/template/TrumpCard.js +0 -19
- package/card/widget/Card.d.ts +0 -2
- package/card/widget/Card.js +0 -45
- package/deck/Deck.d.ts +0 -16
- package/deck/Deck.js +0 -15
- package/deck/index.js +0 -1
- package/index.js +0 -11
- package/interaction/Exception.d.ts +0 -2
- package/interaction/Exception.js +0 -9
- package/interaction/LoadingSpinner.d.ts +0 -1
- package/interaction/LoadingSpinner.js +0 -5
- package/interaction/index.js +0 -2
- package/interface/Board.d.ts +0 -57
- package/interface/Board.js +0 -1
- package/interface/Card.d.ts +0 -73
- package/interface/Card.js +0 -1
- package/interface/HTMLElement.d.ts +0 -13
- package/interface/HTMLElement.js +0 -1
- package/interface/Interaction.d.ts +0 -5
- package/interface/Interaction.js +0 -1
- package/interface/Modal.d.ts +0 -18
- package/interface/Modal.js +0 -1
- package/interface/Property.js +0 -14
- package/interface/Widget.d.ts +0 -4
- package/interface/Widget.js +0 -1
- package/interface/index.js +0 -2
- package/layout/dashboard/Header.d.ts +0 -5
- package/layout/dashboard/Header.js +0 -19
- package/layout/dashboard/index.d.ts +0 -7
- package/layout/dashboard/index.js +0 -10
- package/layout/index.js +0 -1
- package/menu/SideMenu.d.ts +0 -1
- package/menu/SideMenu.js +0 -14
- package/menu/index.js +0 -1
- package/modal/AlertModal.d.ts +0 -2
- package/modal/AlertModal.js +0 -8
- package/modal/ControllerModal.d.ts +0 -6
- package/modal/ControllerModal.js +0 -6
- package/modal/Modal.d.ts +0 -2
- package/modal/Modal.js +0 -31
- package/modal/TestModal.d.ts +0 -8
- package/modal/TestModal.js +0 -6
- package/modal/index.js +0 -3
- package/navigation/Navigation.d.ts +0 -5
- package/navigation/Navigation.js +0 -24
- package/navigation/index.js +0 -1
- package/shelf/Shelf.d.ts +0 -4
- package/shelf/Shelf.js +0 -4
- package/shelf/index.js +0 -1
- package/store/index.d.ts +0 -16
- package/store/index.js +0 -39
- package/text/LineBreaks.d.ts +0 -4
- package/text/LineBreaks.js +0 -5
- package/text/index.js +0 -1
- package/util/classNames.d.ts +0 -1
- package/util/classNames.js +0 -4
- package/util/colors.d.ts +0 -10
- package/util/colors.js +0 -10
- package/util/display.d.ts +0 -25
- package/util/display.js +0 -25
- package/util/displayResponsive.d.ts +0 -3
- package/util/displayResponsive.js +0 -15
- package/util/index.js +0 -7
- package/util/pattern.d.ts +0 -7
- package/util/pattern.js +0 -15
- package/util/position.d.ts +0 -14
- package/util/position.js +0 -44
- package/util/shape.d.ts +0 -1
- package/util/shape.js +0 -3
- package/version.txt +0 -1
- /package/{asset → public}/fonts/Kostar.ttf +0 -0
- /package/{asset → public}/fonts/Megrim.ttf +0 -0
- /package/{asset → public}/fonts/NicoMoji.ttf +0 -0
- /package/{asset → public}/fonts/Pretendard-Medium.otf +0 -0
- /package/{asset → src/asset}/json/credit-lottie.json +0 -0
- /package/{asset → src/asset}/json/loading-lottie.json +0 -0
- /package/{asset → src/asset}/json/test.svg +0 -0
- /package/{globals.css → src/globals.css} +0 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { CanvasBoard, Deck, Shelf, TableCard, TrumpCard } from "../..";
|
|
2
|
+
|
|
3
|
+
export default function PartnerPage() {
|
|
4
|
+
return (
|
|
5
|
+
<CanvasBoard>
|
|
6
|
+
<Shelf>
|
|
7
|
+
<Deck titles={{ title: "이번달 집중 실적" }}>
|
|
8
|
+
<TrumpCard
|
|
9
|
+
titles={{
|
|
10
|
+
title: "이번달 정기시험 성과는",
|
|
11
|
+
subTitle: ["0원입니다."],
|
|
12
|
+
}}
|
|
13
|
+
options={{ width: "xl" }}
|
|
14
|
+
/>
|
|
15
|
+
<TrumpCard
|
|
16
|
+
titles={{
|
|
17
|
+
title: "이번달 기관시험 성과는",
|
|
18
|
+
subTitle: ["1000원입니다."],
|
|
19
|
+
}}
|
|
20
|
+
options={{ width: "sm" }}
|
|
21
|
+
/>
|
|
22
|
+
</Deck>
|
|
23
|
+
</Shelf>
|
|
24
|
+
<Shelf>
|
|
25
|
+
<Deck titles={{ title: "정기시험" }}>
|
|
26
|
+
<TrumpCard
|
|
27
|
+
titles={{
|
|
28
|
+
title: "정기시험",
|
|
29
|
+
subTitle: [
|
|
30
|
+
"고사장 마감까지 D-1입니다.",
|
|
31
|
+
"접수 마감까지 D-7입니다.",
|
|
32
|
+
],
|
|
33
|
+
}}
|
|
34
|
+
options={{ width: "md" }}
|
|
35
|
+
/>
|
|
36
|
+
</Deck>
|
|
37
|
+
<Deck titles={{ title: "우리 TOSEL MVP" }}>
|
|
38
|
+
<TableCard
|
|
39
|
+
data={data}
|
|
40
|
+
fields={{ name: "이름", sales: "매출액" }}
|
|
41
|
+
sizes={{ name: "1/3" }}
|
|
42
|
+
/>
|
|
43
|
+
</Deck>
|
|
44
|
+
</Shelf>
|
|
45
|
+
</CanvasBoard>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface Data extends Record<string, string | number> {
|
|
50
|
+
name: string;
|
|
51
|
+
sales: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const data: Data[] = [
|
|
55
|
+
{
|
|
56
|
+
name: "최광주",
|
|
57
|
+
sales: "13,000,000",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: "장호성",
|
|
61
|
+
sales: "2,000,000",
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
{
|
|
65
|
+
name: "안혜진",
|
|
66
|
+
sales: "1,200,000",
|
|
67
|
+
},
|
|
68
|
+
];
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import tovention from "../../../tailwind.config";
|
|
2
|
+
|
|
3
|
+
export default function Convention() {
|
|
4
|
+
const {
|
|
5
|
+
extend: { fontFamily, screens, fontSize, colors, inset },
|
|
6
|
+
} = tovention.theme;
|
|
7
|
+
|
|
8
|
+
const scripts = [
|
|
9
|
+
{
|
|
10
|
+
name: "colors",
|
|
11
|
+
help: "기본적으로 color-description 형태로 설정되어 있다.",
|
|
12
|
+
value: colors,
|
|
13
|
+
display: "bg-",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: "screens",
|
|
17
|
+
help: "화면 크기에 따른 breakpoint 설정",
|
|
18
|
+
value: screens,
|
|
19
|
+
display: "",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: "fontSize",
|
|
23
|
+
help: "rem은 px을 16으로 나눈 값이다. 16px = 1rem",
|
|
24
|
+
value: fontSize,
|
|
25
|
+
display: "text-",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "fontFamily",
|
|
29
|
+
help: "",
|
|
30
|
+
value: fontFamily,
|
|
31
|
+
display: "font-",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className="min-h-screen w-full flex flex-col items-center text-xl pt-16">
|
|
37
|
+
<div className="border-2 w-9/10 p-4 flex flex-col gap-4">
|
|
38
|
+
{scripts.map(({ name, help, value, display }) => (
|
|
39
|
+
<div key={name} className="flex flex-col gap-4">
|
|
40
|
+
<div className="text-3xl font-bold">{`${name}: ${help}`}</div>
|
|
41
|
+
<div className="text-xl">
|
|
42
|
+
{Object.entries(value).map(([innerKey, innerValue]) => {
|
|
43
|
+
return (
|
|
44
|
+
<div key={innerKey} className="flex gap-4">
|
|
45
|
+
<div>{innerKey}</div>
|
|
46
|
+
<div className={display ? `${display}${innerKey}` : ""}>
|
|
47
|
+
{innerValue}
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
);
|
|
51
|
+
})}
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
))}
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
}
|
package/src/app/page.tsx
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import "../globals.css";
|
|
2
|
-
|
|
3
|
-
export { default as
|
|
1
|
+
import "../globals.css";
|
|
2
|
+
|
|
3
|
+
export { default as CanvasBoard } from "./template/CanvasBoard";
|
|
4
|
+
export { default as ManageBoard } from "./template/ManageBoard";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BoardProps } from "../../interface/Board";
|
|
2
|
+
import { cn } from "../../util";
|
|
3
|
+
import { Board } from "../widget/Board";
|
|
4
|
+
|
|
5
|
+
export default function CanvasBoard({ children, options }: BoardProps) {
|
|
6
|
+
const layouts = "flex flex-col lg:flex-row lg:flex-wrap gap-7.5 ";
|
|
7
|
+
const sizes = "h-full ";
|
|
8
|
+
const paddings =
|
|
9
|
+
"pb-36 xl:pb-0 px-2 xs:px-4 xl:pl-8 xl:pr-2 pt-2 xs:pt-4 xl:pt-8";
|
|
10
|
+
const styles = "overflow-y-scroll ";
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<Board options={options}>
|
|
14
|
+
<div className={cn(layouts, sizes, paddings, styles)}>{children}</div>
|
|
15
|
+
</Board>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Deck } from "../../deck";
|
|
2
|
+
import { cn } from "../../util";
|
|
3
|
+
import { Board } from "../widget/Board";
|
|
4
|
+
import BoardHeader from "../widget/Header";
|
|
5
|
+
import BoardDataField from "../widget/DataField";
|
|
6
|
+
import { ManageBoardProps } from "../../interface/Board";
|
|
7
|
+
import { useWidgetStore } from "../../store";
|
|
8
|
+
import { Exception } from "../../interaction";
|
|
9
|
+
|
|
10
|
+
type Item = Record<string, any>;
|
|
11
|
+
export default function ManageBoard<T extends Item>({
|
|
12
|
+
header,
|
|
13
|
+
data,
|
|
14
|
+
widgets,
|
|
15
|
+
}: ManageBoardProps<T>) {
|
|
16
|
+
const {
|
|
17
|
+
order: [orderBy, orderHow],
|
|
18
|
+
} = useWidgetStore();
|
|
19
|
+
const { dataSets, dataField, gap } = data;
|
|
20
|
+
const positions = `flex flex-col gap-${gap ?? 0}`;
|
|
21
|
+
const sizes = `h-full ${dataField ? "xl:h-135" : "xl:h-158"}`;
|
|
22
|
+
const paddings = "pb-60 xl:pb-0 px-2 xs:px-4 xl:px-8";
|
|
23
|
+
const styles = "overflow-y-scroll";
|
|
24
|
+
return (
|
|
25
|
+
<Board widgets={widgets}>
|
|
26
|
+
<BoardHeader {...header} />
|
|
27
|
+
{dataField && <BoardDataField dataField={dataField} />}
|
|
28
|
+
<div className={cn(positions, sizes, paddings, styles)}>
|
|
29
|
+
<Exception exceptions={widgets?.exceptions}>
|
|
30
|
+
{dataSets.map(({ title: deckTitle, items, renderItem }) =>
|
|
31
|
+
deckTitle ? (
|
|
32
|
+
<div key={deckTitle} className="pt-4">
|
|
33
|
+
<Deck titles={{ title: deckTitle ?? "" }}>
|
|
34
|
+
{items?.map((item) => renderItem(item))}
|
|
35
|
+
</Deck>
|
|
36
|
+
</div>
|
|
37
|
+
) : (
|
|
38
|
+
items
|
|
39
|
+
?.slice()
|
|
40
|
+
.sort((a, b) => {
|
|
41
|
+
if (orderBy) {
|
|
42
|
+
if (orderHow === "asc")
|
|
43
|
+
return a[orderBy] > b[orderBy] ? 1 : -1;
|
|
44
|
+
return a[orderBy] < b[orderBy] ? 1 : -1;
|
|
45
|
+
}
|
|
46
|
+
return 0;
|
|
47
|
+
})
|
|
48
|
+
.map((item) => renderItem(item))
|
|
49
|
+
)
|
|
50
|
+
)}
|
|
51
|
+
</Exception>
|
|
52
|
+
</div>
|
|
53
|
+
{widgets?.menu}
|
|
54
|
+
</Board>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useWidgetStore } from "../../store";
|
|
2
|
+
import { BoardProps } from "../../interface/Board";
|
|
3
|
+
import Tab from "./Tab";
|
|
4
|
+
|
|
5
|
+
export function Board({ children, widgets }: BoardProps) {
|
|
6
|
+
const { events } = useWidgetStore();
|
|
7
|
+
const { components, tabs } = widgets ?? {};
|
|
8
|
+
|
|
9
|
+
const classNames = [
|
|
10
|
+
`h-full xl:min-h-0 `,
|
|
11
|
+
"xl:rounded-xl bg-white relative w-full z-10 overflow-hidden",
|
|
12
|
+
].join(" ");
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<div className="h-full xl:min-h-0 xl:h-178 w-full relative ">
|
|
16
|
+
<div className={classNames}>
|
|
17
|
+
{children}
|
|
18
|
+
{components?.map(([flag, Component]) => {
|
|
19
|
+
if (typeof flag === "boolean") return flag ? <>{Component}</> : null;
|
|
20
|
+
return events?.some(({ event }) => event === flag) ? (
|
|
21
|
+
<>{Component}</>
|
|
22
|
+
) : null;
|
|
23
|
+
})}
|
|
24
|
+
</div>
|
|
25
|
+
{tabs && <Tab tabs={tabs} />}
|
|
26
|
+
</div>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { cn } from "../../util";
|
|
2
|
+
import { useWidgetStore } from "./../../store";
|
|
3
|
+
|
|
4
|
+
export default function BoardDataField({
|
|
5
|
+
dataField,
|
|
6
|
+
}: {
|
|
7
|
+
dataField: {
|
|
8
|
+
fields: Record<string, string>;
|
|
9
|
+
sizes: Record<string, string>;
|
|
10
|
+
};
|
|
11
|
+
}) {
|
|
12
|
+
const {
|
|
13
|
+
order: [orderBy, orderHow],
|
|
14
|
+
setOrder,
|
|
15
|
+
} = useWidgetStore();
|
|
16
|
+
const { fields, sizes } = dataField;
|
|
17
|
+
|
|
18
|
+
const container = {
|
|
19
|
+
positions: "fixed top-40 left-0 xl:static",
|
|
20
|
+
displays: "flex items-center",
|
|
21
|
+
styles: `bg-gray-200`,
|
|
22
|
+
sizes: "w-full h-23",
|
|
23
|
+
};
|
|
24
|
+
const dataFieldContainer = {
|
|
25
|
+
displays: "flex items-center",
|
|
26
|
+
sizes: "w-full h-12",
|
|
27
|
+
paddings: "px-2 xs:px-4 xl:px-8",
|
|
28
|
+
styles: "bg-white-off",
|
|
29
|
+
};
|
|
30
|
+
const block = {
|
|
31
|
+
displays: "xl:hidden block ",
|
|
32
|
+
sizes: container.sizes,
|
|
33
|
+
};
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
<div
|
|
37
|
+
className={cn(
|
|
38
|
+
container.positions,
|
|
39
|
+
container.displays,
|
|
40
|
+
container.sizes,
|
|
41
|
+
container.styles
|
|
42
|
+
)}
|
|
43
|
+
>
|
|
44
|
+
<div
|
|
45
|
+
className={cn(
|
|
46
|
+
dataFieldContainer.displays,
|
|
47
|
+
dataFieldContainer.sizes,
|
|
48
|
+
dataFieldContainer.paddings,
|
|
49
|
+
dataFieldContainer.styles
|
|
50
|
+
)}
|
|
51
|
+
>
|
|
52
|
+
{Object.entries(fields).map(([key, value]) => (
|
|
53
|
+
<div key={key} className={`w-${`${sizes[key]}/100` ?? "auto"}`}>
|
|
54
|
+
<button
|
|
55
|
+
onClick={() => setOrder(key)}
|
|
56
|
+
className="flex items-center gap-1"
|
|
57
|
+
>
|
|
58
|
+
<div>{value}</div>
|
|
59
|
+
<div className="text-xs">
|
|
60
|
+
{orderBy === key ? (orderHow === "asc" ? "▼" : "▲") : ""}
|
|
61
|
+
</div>
|
|
62
|
+
</button>
|
|
63
|
+
</div>
|
|
64
|
+
))}
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
<div className={cn(block.sizes, block.displays)} />
|
|
68
|
+
</>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { cn } from "../../util";
|
|
2
|
+
import { Input, Select } from "./Tags";
|
|
3
|
+
import { BoardHeaderProps } from "./../../interface/Board";
|
|
4
|
+
export default function BoardHeader({
|
|
5
|
+
title,
|
|
6
|
+
tags,
|
|
7
|
+
options,
|
|
8
|
+
}: BoardHeaderProps) {
|
|
9
|
+
const { selects, inputs } = tags ?? {};
|
|
10
|
+
const { colors } = options ?? {};
|
|
11
|
+
const { bgColor, textColor } = colors ?? {
|
|
12
|
+
bgColor: "gray-200",
|
|
13
|
+
textColor: "black",
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const container = {
|
|
17
|
+
positions: "fixed top-20 left-0 xl:static flex items-center",
|
|
18
|
+
paddings: "px-12",
|
|
19
|
+
styles: `bg-${bgColor} text-${textColor} pl-12 pr-9`,
|
|
20
|
+
sizes: "w-full h-20",
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const block = {
|
|
24
|
+
displays: "xl:hidden block ",
|
|
25
|
+
sizes: container.sizes,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
<div
|
|
31
|
+
className={cn(
|
|
32
|
+
container.positions,
|
|
33
|
+
container.paddings,
|
|
34
|
+
container.sizes,
|
|
35
|
+
container.styles
|
|
36
|
+
)}
|
|
37
|
+
>
|
|
38
|
+
<div className="text-xl font-bold">{title}</div>
|
|
39
|
+
<div className="flex items-center ml-auto gap-4">
|
|
40
|
+
{selects?.map(({ width, title, options, onChange }) => (
|
|
41
|
+
<Select
|
|
42
|
+
key={title}
|
|
43
|
+
width={width}
|
|
44
|
+
title={title}
|
|
45
|
+
selectOptions={options}
|
|
46
|
+
onChange={onChange}
|
|
47
|
+
/>
|
|
48
|
+
))}
|
|
49
|
+
{inputs?.map(({ width, title, placeholder, onChange }) => (
|
|
50
|
+
<Input
|
|
51
|
+
key={title + placeholder}
|
|
52
|
+
width={width}
|
|
53
|
+
title={title}
|
|
54
|
+
placeholder={placeholder}
|
|
55
|
+
onChange={onChange}
|
|
56
|
+
/>
|
|
57
|
+
))}
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
<div className={cn(block.sizes, block.displays)} />
|
|
61
|
+
</>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { Button } from "../../interface";
|
|
3
|
+
import { cn } from "../../util";
|
|
4
|
+
|
|
5
|
+
export default function Tab({ tabs }: { tabs: Button[] }) {
|
|
6
|
+
const [tabsSelection, setTabsSelection] = useState(
|
|
7
|
+
tabs.map((_, i) => i === 0)
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
const positions = "xl:absolute xl:-bottom-14 xl:left-0 z-5";
|
|
11
|
+
const displays = "hidden xl:flex xl:items-end xl:gap-4";
|
|
12
|
+
const sizes = "xl:h-16";
|
|
13
|
+
const paddings = "xl:px-8 xl:pb-2 ";
|
|
14
|
+
const styles = "bg-white/50 rounded-b-xl ";
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<div className={cn(displays, positions, sizes, paddings, styles)}>
|
|
18
|
+
{tabs.map(([title, onClick], index) => (
|
|
19
|
+
<button
|
|
20
|
+
key={title}
|
|
21
|
+
onClick={() => {
|
|
22
|
+
setTabsSelection(tabsSelection.map((_, i) => i === index));
|
|
23
|
+
return onClick();
|
|
24
|
+
}}
|
|
25
|
+
className={`h-9 w-32 rounded-md ${
|
|
26
|
+
tabsSelection[index]
|
|
27
|
+
? "border-4 border-blue-500"
|
|
28
|
+
: "border-4 border-red-500"
|
|
29
|
+
}`}
|
|
30
|
+
>
|
|
31
|
+
{title}
|
|
32
|
+
</button>
|
|
33
|
+
))}
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { useId } from "react";
|
|
2
|
+
import {
|
|
3
|
+
HTMLInputElement,
|
|
4
|
+
HTMLSelectElement,
|
|
5
|
+
} from "../../interface/HTMLElement";
|
|
6
|
+
|
|
7
|
+
export function Select({
|
|
8
|
+
title,
|
|
9
|
+
width,
|
|
10
|
+
onChange,
|
|
11
|
+
selectOptions,
|
|
12
|
+
}: HTMLSelectElement) {
|
|
13
|
+
const id = useId();
|
|
14
|
+
|
|
15
|
+
const widthSize = {
|
|
16
|
+
xs: "w-32",
|
|
17
|
+
sm: "w-48",
|
|
18
|
+
md: "w-64",
|
|
19
|
+
lg: "w-96",
|
|
20
|
+
xl: "w-128",
|
|
21
|
+
"2xl": "w-144",
|
|
22
|
+
full: "w-full",
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const classNames = `${widthSize[width ?? "md"]} h-10 rounded-full pl-4`;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<div className="flex justify-center items-center gap-4">
|
|
29
|
+
<label htmlFor={id} className="font-bold">
|
|
30
|
+
{title}
|
|
31
|
+
</label>
|
|
32
|
+
<select
|
|
33
|
+
id={id}
|
|
34
|
+
onChange={(e) => onChange(e.target.value)}
|
|
35
|
+
className={classNames}
|
|
36
|
+
>
|
|
37
|
+
{selectOptions?.map(([id, title]) => (
|
|
38
|
+
<option key={id} value={id}>
|
|
39
|
+
{title}
|
|
40
|
+
</option>
|
|
41
|
+
))}
|
|
42
|
+
</select>
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function Input({
|
|
48
|
+
title,
|
|
49
|
+
onChange,
|
|
50
|
+
placeholder,
|
|
51
|
+
width,
|
|
52
|
+
}: HTMLInputElement) {
|
|
53
|
+
const id = useId();
|
|
54
|
+
|
|
55
|
+
const widthSize = {
|
|
56
|
+
xs: "w-28",
|
|
57
|
+
sm: "w-48",
|
|
58
|
+
md: "w-64",
|
|
59
|
+
lg: "w-96",
|
|
60
|
+
xl: "w-128",
|
|
61
|
+
"2xl": "w-144",
|
|
62
|
+
full: "w-full",
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const classNames = `${widthSize[width ?? "md"]} h-10 rounded-full pl-4`;
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className="flex justify-center items-center gap-4">
|
|
69
|
+
<label htmlFor={id} className="font-bold">
|
|
70
|
+
{title}
|
|
71
|
+
</label>
|
|
72
|
+
<input
|
|
73
|
+
className={classNames}
|
|
74
|
+
id={id}
|
|
75
|
+
type="text"
|
|
76
|
+
placeholder={placeholder ?? ""}
|
|
77
|
+
onChange={(e) => onChange(e.target.value)}
|
|
78
|
+
/>
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export { default as ProfileCard } from "./template/ProfileCard";
|
|
2
|
-
export { default as TrumpCard } from "./template/TrumpCard";
|
|
3
|
-
export { default as ChartCard } from "./template/ChartCard";
|
|
4
|
-
export { default as TableCard } from "./template/TableCard";
|
|
5
|
-
export { default as RowCard } from "./template/RowCard";
|
|
1
|
+
export { default as ProfileCard } from "./template/ProfileCard";
|
|
2
|
+
export { default as TrumpCard } from "./template/TrumpCard";
|
|
3
|
+
export { default as ChartCard } from "./template/ChartCard";
|
|
4
|
+
export { default as TableCard } from "./template/TableCard";
|
|
5
|
+
export { default as RowCard } from "./template/RowCard";
|
|
6
|
+
export { default as InfoCard } from "./template/InfoCard";
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Area,
|
|
3
|
+
Bar,
|
|
4
|
+
ComposedChart,
|
|
5
|
+
Line,
|
|
6
|
+
ResponsiveContainer,
|
|
7
|
+
Tooltip,
|
|
8
|
+
XAxis,
|
|
9
|
+
YAxis,
|
|
10
|
+
} from "recharts";
|
|
11
|
+
import { Card } from "../widget/Card";
|
|
12
|
+
import { ChartCardProps } from "../../interface/Card";
|
|
13
|
+
|
|
14
|
+
export default function ChartCard({
|
|
15
|
+
data,
|
|
16
|
+
xAxis,
|
|
17
|
+
yAxis,
|
|
18
|
+
lines,
|
|
19
|
+
bars,
|
|
20
|
+
areas,
|
|
21
|
+
}: ChartCardProps) {
|
|
22
|
+
return (
|
|
23
|
+
<Card options={{ width: "xl", height: "lg", text: { size: "xs" } }}>
|
|
24
|
+
<ResponsiveContainer width="100%" height="100%">
|
|
25
|
+
<ComposedChart data={data}>
|
|
26
|
+
<XAxis dataKey={xAxis} />
|
|
27
|
+
<YAxis dataKey={yAxis} />
|
|
28
|
+
<Tooltip />
|
|
29
|
+
{lines?.map((line) => (
|
|
30
|
+
<Line key={line.dataKey} {...line} />
|
|
31
|
+
))}
|
|
32
|
+
{bars?.map((bar) => (
|
|
33
|
+
<Bar key={bar.dataKey} {...bar} />
|
|
34
|
+
))}
|
|
35
|
+
{areas?.map((area) => (
|
|
36
|
+
<Area key={area.dataKey} {...area} />
|
|
37
|
+
))}
|
|
38
|
+
</ComposedChart>
|
|
39
|
+
</ResponsiveContainer>
|
|
40
|
+
</Card>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Deck } from "../..";
|
|
2
|
+
import { InfoCardProps } from "../../interface/Card";
|
|
3
|
+
import { Card } from "../widget/Card";
|
|
4
|
+
|
|
5
|
+
export default function InfoCard({ type }: InfoCardProps) {
|
|
6
|
+
return (
|
|
7
|
+
<Deck>
|
|
8
|
+
<Card options={{ width: "xs", height: "lg" }}>
|
|
9
|
+
<div className="p-5">
|
|
10
|
+
<div>{type}</div>
|
|
11
|
+
<div>{}</div>
|
|
12
|
+
</div>
|
|
13
|
+
</Card>
|
|
14
|
+
<Card options={{ width: "md" }}>
|
|
15
|
+
<div className="p-5">
|
|
16
|
+
<div>{type}</div>
|
|
17
|
+
<div>{}</div>
|
|
18
|
+
</div>
|
|
19
|
+
</Card>
|
|
20
|
+
</Deck>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Card } from "../widget/Card";
|
|
2
|
+
import { center, between, colorsByLevel } from "../../util";
|
|
3
|
+
type Level = "PS" | "ST" | "BA" | "JR" | "HJ";
|
|
4
|
+
|
|
5
|
+
export default function ProfileCard({
|
|
6
|
+
info,
|
|
7
|
+
gradeData,
|
|
8
|
+
}: {
|
|
9
|
+
info: { name: string; birthday: string; image?: string };
|
|
10
|
+
gradeData?: { level?: Level; score?: number; grade?: number };
|
|
11
|
+
}) {
|
|
12
|
+
const { name, birthday, image } = info;
|
|
13
|
+
const { level, score, grade } = gradeData ?? {};
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<Card options={{ width: "sm" }}>
|
|
17
|
+
<div className="flex">
|
|
18
|
+
<img
|
|
19
|
+
src={image}
|
|
20
|
+
alt="profile"
|
|
21
|
+
className="h-20 w-20 overflow-hidden rounded-full object-cover "
|
|
22
|
+
/>
|
|
23
|
+
<div className="ml-auto flex flex-col gap-4">
|
|
24
|
+
<div className="flex w-52 items-end gap-2 border-b-2 border-blue-navy pb-2">
|
|
25
|
+
<div className="text-xl font-bold">{name}</div>
|
|
26
|
+
<div>{birthday}</div>
|
|
27
|
+
</div>
|
|
28
|
+
<div>
|
|
29
|
+
<div>학원생</div>
|
|
30
|
+
<div>{level ? colorsByLevel[level] : ""}</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</Card>
|
|
35
|
+
);
|
|
36
|
+
}
|