diff --git a/frontend/src/components/Login/LoginTemplate.tsx b/frontend/src/components/Login/LoginTemplate.tsx
index be92e122a..f949764c5 100644
--- a/frontend/src/components/Login/LoginTemplate.tsx
+++ b/frontend/src/components/Login/LoginTemplate.tsx
@@ -1,6 +1,7 @@
import { useState } from "react";
import styled from "styled-components";
import LoadingAnimation from "@/components/Common/LoadingAnimation";
+import { ReactComponent as LoginImg } from "@/assets/images/loginImg.svg";
const LoginTemplate = (props: {
url: string;
@@ -23,7 +24,7 @@ const LoginTemplate = (props: {
-
+
diff --git a/frontend/src/components/MapInfo/MapItem/MapItem.tsx b/frontend/src/components/MapInfo/MapItem/MapItem.tsx
index 4787bb9e8..de08f87c4 100644
--- a/frontend/src/components/MapInfo/MapItem/MapItem.tsx
+++ b/frontend/src/components/MapInfo/MapItem/MapItem.tsx
@@ -54,7 +54,7 @@ const ItemStyled = styled.div<{
grid-row-end: ${({ info }) => info.rowEnd};
background: ${({ info }) =>
info.type === "cabinet"
- ? "#9747ff"
+ ? "var(--main-color)"
: info.type === "floorInfo"
? "transparent"
: "#bcb9b9"};
diff --git a/frontend/src/components/Profile/ThemeColor.container.tsx b/frontend/src/components/Profile/ThemeColor.container.tsx
new file mode 100644
index 000000000..e702ec5ef
--- /dev/null
+++ b/frontend/src/components/Profile/ThemeColor.container.tsx
@@ -0,0 +1,71 @@
+import { useEffect, useState } from "react";
+import ThemeColor from "./ThemeColor";
+
+const ThemeColorContainer: React.FC<{
+ showColorPicker: boolean;
+ setShowColorPicker: React.Dispatch>;
+}> = ({ showColorPicker, setShowColorPicker }) => {
+ const savedColor = localStorage.getItem("mainColor");
+ const defaultColor = "#9747ff";
+ const [mainColor, setMainColor] = useState(
+ savedColor ? savedColor : defaultColor
+ );
+ const root: HTMLElement = document.documentElement;
+
+ const handleChange = (mainColor: { hex: string }) => {
+ const selectedColor: string = mainColor.hex;
+ setMainColor(selectedColor);
+ };
+
+ const handleReset = () => {
+ setMainColor(defaultColor);
+ root.style.setProperty("--main-color", defaultColor);
+ root.style.setProperty("--lightpurple-color", "#b18cff");
+ localStorage.setItem("mainColor", defaultColor);
+ };
+
+ const handleSave = () => {
+ localStorage.setItem("mainColor", mainColor);
+ root.style.setProperty("--main-color", mainColor);
+ toggleColorPicker(true);
+ };
+
+ const handleCancel = () => {
+ const savedColor = localStorage.getItem("mainColor");
+ root.style.setProperty("--main-color", savedColor);
+ toggleColorPicker(true);
+ };
+
+ const toggleColorPicker = (isChange: boolean) => {
+ if (isChange) setShowColorPicker(!showColorPicker);
+ };
+
+ const confirmBeforeUnload = (e: BeforeUnloadEvent) => {
+ if (mainColor !== localStorage.getItem("mainColor")) {
+ e.returnValue =
+ "변경된 색상이 저장되지 않을 수 있습니다. 계속하시겠습니까?";
+ }
+ };
+
+ useEffect(() => {
+ root.style.setProperty("--main-color", mainColor);
+ window.addEventListener("beforeunload", confirmBeforeUnload);
+ return () => {
+ window.removeEventListener("beforeunload", confirmBeforeUnload);
+ };
+ }, [mainColor]);
+
+ return (
+
+ );
+};
+
+export default ThemeColorContainer;
diff --git a/frontend/src/components/Profile/ThemeColor.tsx b/frontend/src/components/Profile/ThemeColor.tsx
new file mode 100644
index 000000000..9b725a90e
--- /dev/null
+++ b/frontend/src/components/Profile/ThemeColor.tsx
@@ -0,0 +1,128 @@
+import React from "react";
+import { TwitterPicker } from "react-color";
+import styled from "styled-components";
+
+const ThemeColor: React.FC<{
+ showColorPicker: boolean;
+ setShowColorPicker: React.Dispatch>;
+ handleChange: (mainColor: { hex: string }) => void;
+ handleReset: Function;
+ handleSave: Function;
+ handleCancel: Function;
+ mainColor: string;
+}> = ({
+ showColorPicker,
+ setShowColorPicker,
+ handleChange,
+ handleReset,
+ handleSave,
+ handleCancel,
+ mainColor,
+}) => {
+ return (
+
+
+ 테마 컬러
+ {showColorPicker ? (
+ <>
+
+ handleSave()}>저장
+ handleCancel()}>
+ 취소
+
+
+ >
+ ) : (
+ handleReset()}>초기화
+ )}
+
+
+
+ 메인 컬러
+ setShowColorPicker(!showColorPicker)}
+ />
+
+ {showColorPicker && (
+
+ )}
+
+
+ );
+};
+
+const ThemeColorStyled = styled.div`
+ width: 350px;
+ height: 215px;
+ background-color: var(--lightgary-color);
+ border-radius: 10px;
+ padding: 30px;
+`;
+
+const TableTitleStyled = styled.div`
+ font-size: 18px;
+ font-weight: bold;
+`;
+
+const TableTopStyled = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 20px;
+`;
+
+const BtnWrapStyled = styled.div`
+ display: flex;
+`;
+
+const ResetBtnStyled = styled.div`
+ width: 54px;
+ height: 23px;
+ background-color: white;
+ border-radius: 4px;
+ color: var(--gray-color);
+ font-size: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+`;
+
+const SaveBtnStyled = styled.div`
+ width: 54px;
+ height: 23px;
+ background-color: var(--main-color);
+ border-radius: 4px;
+ color: white;
+ font-size: 12px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 15px;
+`;
+
+const MainColorButtonStyled = styled.button`
+ width: 28px;
+ height: 28px;
+ background-color: var(--main-color);
+ border-radius: 8px;
+`;
+
+const ColorSelectStyled = styled.div`
+ padding: 20px;
+ width: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+`;
+
+const TableBodyStyled = styled.div`
+ background-color: white;
+ width: 290px;
+ height: 120px;
+ border-radius: 8px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+`;
+
+export default ThemeColor;
diff --git a/frontend/src/components/SectionPagination/SectionPagination.tsx b/frontend/src/components/SectionPagination/SectionPagination.tsx
index c36c02eed..38c92b4d7 100644
--- a/frontend/src/components/SectionPagination/SectionPagination.tsx
+++ b/frontend/src/components/SectionPagination/SectionPagination.tsx
@@ -21,7 +21,9 @@ const SectionPagination: React.FC<{
const paginationIndexBar = sectionList.map((sectionName, index) => (
changeSectionOnClickIndexButton(index)}
className="cabiButton"
/>
diff --git a/frontend/src/custom.d.ts b/frontend/src/custom.d.ts
new file mode 100644
index 000000000..b1d9a523d
--- /dev/null
+++ b/frontend/src/custom.d.ts
@@ -0,0 +1,7 @@
+declare module "*.svg" {
+ import * as React from "react";
+
+ export const ReactComponent: React.FunctionComponent<
+ React.SVGProps & { title?: string }
+ >;
+}
diff --git a/frontend/src/pages/Layout.tsx b/frontend/src/pages/Layout.tsx
index 6b53f97a2..369d06252 100644
--- a/frontend/src/pages/Layout.tsx
+++ b/frontend/src/pages/Layout.tsx
@@ -55,6 +55,9 @@ const Layout = (): JSX.Element => {
}
};
+ const savedColor = localStorage.getItem("mainColor");
+ const root: HTMLElement = document.documentElement;
+
useEffect(() => {
if (!token && !isLoginPage) navigate("/login");
else if (token) {
@@ -62,6 +65,12 @@ const Layout = (): JSX.Element => {
}
}, []);
+ useEffect(() => {
+ root.style.setProperty("--main-color", savedColor);
+ if (savedColor !== "#9747ff")
+ root.style.setProperty("--lightpurple-color", "#7b7b7b");
+ }, [savedColor]);
+
const { closeAll } = useMenu();
const handleClickBg = () => {
diff --git a/frontend/src/pages/ProfilePage.tsx b/frontend/src/pages/ProfilePage.tsx
index a111bf2d4..b08bae54e 100644
--- a/frontend/src/pages/ProfilePage.tsx
+++ b/frontend/src/pages/ProfilePage.tsx
@@ -1,7 +1,20 @@
+import { useState } from "react";
import styled from "styled-components";
+import ThemeColorContainer from "@/components/Profile/ThemeColor.container";
const ProfilePage = () => {
- return 내 정보 여기에 넣어주세용;
+ const [showThemeChange, setShowThemeChange] = useState(false);
+ return (
+
+ {showThemeChange && }
+
+
+
+
+ );
};
const WrapperStyled = styled.div`
@@ -15,4 +28,17 @@ const WrapperStyled = styled.div`
}
`;
+const BackgroundOverlayStyled = styled.div`
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.4);
+ z-index: 0;
+`;
+
+const ItemStyeld = styled.div`
+ z-index: 1;
+`;
export default ProfilePage;
diff --git a/frontend/src/pages/admin/AdminLayout.tsx b/frontend/src/pages/admin/AdminLayout.tsx
index 57df74d38..836649a06 100644
--- a/frontend/src/pages/admin/AdminLayout.tsx
+++ b/frontend/src/pages/admin/AdminLayout.tsx
@@ -39,6 +39,14 @@ const Layout = (): JSX.Element => {
}
}, []);
+ const savedColor = localStorage.getItem("mainColor");
+ const root: HTMLElement = document.documentElement;
+ useEffect(() => {
+ root.style.setProperty("--main-color", savedColor);
+ if (savedColor !== "#9747ff")
+ root.style.setProperty("--lightpurple-color", "#7b7b7b");
+ }, [savedColor]);
+
const { closeAll } = useMenu();
const handleClickBg = () => {
diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts
index 11f02fe2a..b1f45c786 100644
--- a/frontend/src/vite-env.d.ts
+++ b/frontend/src/vite-env.d.ts
@@ -1 +1,2 @@
///
+///
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
index dbcf2884b..98c9bfd9f 100644
--- a/frontend/tsconfig.json
+++ b/frontend/tsconfig.json
@@ -16,11 +16,11 @@
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
- "types": ["node"],
+ "types": ["node", "vite-plugin-svgr/client"],
"paths": {
"@/*": ["./src/*"]
}
},
- "include": ["src"],
+ "include": ["src", "custom.d.ts"],
"references": [{ "path": "./tsconfig.node.json" }]
}
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index ec0ffa0bf..d1621437f 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -1,14 +1,16 @@
///
-import { defineConfig } from "vite";
+import svgr from "@svgr/rollup";
import react from "@vitejs/plugin-react";
import * as path from "path";
import { visualizer } from "rollup-plugin-visualizer";
+import { defineConfig } from "vite";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
react(),
visualizer({ open: true, gzipSize: true, template: "treemap" }),
+ svgr(),
],
resolve: {
alias: [{ find: "@", replacement: path.resolve(__dirname, "src") }],