From bf62dad6d707b1706b224f49da6f8b12dd889d9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EB=AC=B8=EC=A7=80=EC=9B=90?=
<81554184+jeewonMoon@users.noreply.github.com>
Date: Fri, 6 Sep 2024 20:32:13 +0900
Subject: [PATCH] =?UTF-8?q?design:=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20?=
=?UTF-8?q?=ED=99=94=EB=A9=B4=20=EA=B0=9C=EC=84=A0=20(#91)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- MediaQuery 속성들을 모듈화했습니다.
- 필터 레이아웃 중에서 공통으로 사용되는 부분들을 styles에 분리해 놨습니다.
- 모바일 환경에서는 헤더의 ': 세종대학교 수강신청 연습 사이트'가 나타나지 않도록 변경했습니다.
- 랩탑이 아닌 환경(모바일, 태블릿)에서는 기본적으로 사이드바가 접혀있도록 수정했습니다.
- modules 폴더 안에 없는 슬라이스들을 폴더 안으로 옮겼습니다.
---
package-lock.json | 75 ++++-
package.json | 2 +
src/apis/utils/instance.ts | 2 +-
src/assets/img/close-sidebar.svg | 1 +
.../CourseRegister/RegisterFilters.tsx | 14 +-
src/components/CourseRegister/index.tsx | 33 +-
src/components/Header/TopMenu.tsx | 4 +-
src/components/Header/TopNav.tsx | 4 +
src/components/Header/index.tsx | 37 ++-
src/components/LectureList/Filters.tsx | 35 +--
src/components/LoginForm/index.tsx | 9 +-
src/components/Menubar/BarTitle.tsx | 24 +-
src/components/Menubar/index.tsx | 44 ++-
src/components/Wishlist/Filters.tsx | 39 +--
src/components/common/FilterInput.tsx | 42 +--
src/components/common/Modal/WaitingModal.tsx | 2 +-
.../common/Modal/handlers/handler.tsx | 2 +-
src/components/common/SelectBox.tsx | 17 +-
src/components/common/Table/index.tsx | 4 +
src/pages/index/Home.tsx | 23 +-
src/pages/index/Login.tsx | 283 +++++++++++-------
.../{ => modules}/courseRegisteredSlice.ts | 0
src/store/{ => modules}/modalSlice.ts | 0
src/store/{ => modules}/userSlice.ts | 0
src/store/store.ts | 6 +-
src/styles/FilterLayout.tsx | 39 +++
src/styles/theme/Theme.ts | 8 +
src/styles/theme/style.d.ts | 5 +-
28 files changed, 482 insertions(+), 272 deletions(-)
create mode 100644 src/assets/img/close-sidebar.svg
rename src/store/{ => modules}/courseRegisteredSlice.ts (100%)
rename src/store/{ => modules}/modalSlice.ts (100%)
rename src/store/{ => modules}/userSlice.ts (100%)
create mode 100644 src/styles/FilterLayout.tsx
diff --git a/package-lock.json b/package-lock.json
index 994db82..9dc03d9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,12 +9,14 @@
"version": "0.0.0",
"dependencies": {
"@reduxjs/toolkit": "^2.2.6",
+ "@types/react-responsive": "^8.0.8",
"axios": "^1.7.2",
"js-cookie": "^3.0.5",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-ga4": "^2.1.0",
"react-redux": "^9.1.2",
+ "react-responsive": "^10.0.0",
"react-router-dom": "^6.24.0",
"redux-persist": "^6.0.0",
"styled-components": "^6.1.11",
@@ -1500,14 +1502,12 @@
"node_modules/@types/prop-types": {
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
- "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==",
- "devOptional": true
+ "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
},
"node_modules/@types/react": {
"version": "18.3.3",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz",
"integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==",
- "devOptional": true,
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
@@ -1522,6 +1522,14 @@
"@types/react": "*"
}
},
+ "node_modules/@types/react-responsive": {
+ "version": "8.0.8",
+ "resolved": "https://registry.npmjs.org/@types/react-responsive/-/react-responsive-8.0.8.tgz",
+ "integrity": "sha512-HDUZtoeFRHrShCGaND23HmXAB9evOOTjkghd2wAasLkuorYYitm5A1XLeKkhXKZppcMBxqB/8V4Snl6hRUTA8g==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/styled-components": {
"version": "5.1.34",
"resolved": "https://registry.npmjs.org/@types/styled-components/-/styled-components-5.1.34.tgz",
@@ -2050,6 +2058,11 @@
"node": ">=4"
}
},
+ "node_modules/css-mediaquery": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz",
+ "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q=="
+ },
"node_modules/css-to-react-native": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
@@ -2790,6 +2803,11 @@
"react-is": "^16.7.0"
}
},
+ "node_modules/hyphenate-style-name": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz",
+ "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="
+ },
"node_modules/ignore": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
@@ -3043,6 +3061,14 @@
"yallist": "^3.0.2"
}
},
+ "node_modules/matchmediaquery": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.4.2.tgz",
+ "integrity": "sha512-wrZpoT50ehYOudhDjt/YvUJc6eUzcdFPdmbizfgvswCKNHD1/OBOHYJpHie+HXpu6bSkEGieFMYk6VuutaiRfA==",
+ "dependencies": {
+ "css-mediaquery": "^0.1.2"
+ }
+ },
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -3141,6 +3167,14 @@
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
},
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
@@ -3332,6 +3366,16 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -3397,8 +3441,7 @@
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-redux": {
"version": "9.1.2",
@@ -3431,6 +3474,23 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-responsive": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-10.0.0.tgz",
+ "integrity": "sha512-N6/UiRLGQyGUqrarhBZmrSmHi2FXSD++N5VbSKsBBvWfG0ZV7asvUBluSv5lSzdMyEVjzZ6Y8DL4OHABiztDOg==",
+ "dependencies": {
+ "hyphenate-style-name": "^1.0.0",
+ "matchmediaquery": "^0.4.2",
+ "prop-types": "^15.6.1",
+ "shallow-equal": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
"node_modules/react-router": {
"version": "6.24.0",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-6.24.0.tgz",
@@ -3598,6 +3658,11 @@
"node": ">=10"
}
},
+ "node_modules/shallow-equal": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-3.1.0.tgz",
+ "integrity": "sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg=="
+ },
"node_modules/shallowequal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
diff --git a/package.json b/package.json
index 312c4cc..c2b82f8 100644
--- a/package.json
+++ b/package.json
@@ -12,12 +12,14 @@
},
"dependencies": {
"@reduxjs/toolkit": "^2.2.6",
+ "@types/react-responsive": "^8.0.8",
"axios": "^1.7.2",
"js-cookie": "^3.0.5",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-ga4": "^2.1.0",
"react-redux": "^9.1.2",
+ "react-responsive": "^10.0.0",
"react-router-dom": "^6.24.0",
"redux-persist": "^6.0.0",
"styled-components": "^6.1.11",
diff --git a/src/apis/utils/instance.ts b/src/apis/utils/instance.ts
index 21b2b88..b07fd24 100644
--- a/src/apis/utils/instance.ts
+++ b/src/apis/utils/instance.ts
@@ -1,4 +1,4 @@
-import {setModalName} from '@/store/modalSlice';
+import {setModalName} from '@/store/modules/modalSlice';
import {setType} from '@/store/modules/errorSlice';
import {store} from '@/store/store';
import axios, {AxiosError, AxiosResponse} from 'axios';
diff --git a/src/assets/img/close-sidebar.svg b/src/assets/img/close-sidebar.svg
new file mode 100644
index 0000000..d00c116
--- /dev/null
+++ b/src/assets/img/close-sidebar.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/CourseRegister/RegisterFilters.tsx b/src/components/CourseRegister/RegisterFilters.tsx
index 33a4d78..f411590 100644
--- a/src/components/CourseRegister/RegisterFilters.tsx
+++ b/src/components/CourseRegister/RegisterFilters.tsx
@@ -5,7 +5,7 @@ import FilterButton from '../common/FilterButton';
import FilterInput from '../common/FilterInput';
import SelectBox from '../common/SelectBox';
import {term, searchOptions} from '@assets/data/filter';
-import {FilterBox, FilterContainer, FilterWrap} from '../LectureList/Filters';
+import {FilterBox, FilterContainer, FilterWrap} from '@/styles/FilterLayout';
interface FiltersProps {
isRegistrationStarted: boolean;
@@ -139,23 +139,27 @@ function RegisterFilters({onSearch, isRegistrationStarted}: FiltersProps) {
const RegisterFilterContainer = styled(FilterContainer)`
display: flex;
align-items: flex-end;
+ gap: 0.7rem 0;
+
+ @media ${props => props.theme.device.mobile} {
+ flex-wrap: wrap;
+ }
`;
const SearchBox = styled.div`
display: flex;
- gap: 0 3rem;
+ flex-wrap: wrap;
+ gap: 0.7rem 3rem;
`;
const SearchWrap = styled(FilterWrap)`
> div {
margin-right: 0.7rem;
}
- display: flex;
align-items: center;
`;
-const CuriNoWrap = styled.div`
- display: flex;
+const CuriNoWrap = styled(FilterBox)`
align-items: center;
`;
diff --git a/src/components/CourseRegister/index.tsx b/src/components/CourseRegister/index.tsx
index d0d7f75..a6f7262 100644
--- a/src/components/CourseRegister/index.tsx
+++ b/src/components/CourseRegister/index.tsx
@@ -5,12 +5,16 @@ import Table from '../common/Table';
import {TableTitle, TableTitleWrap} from '../LectureList';
import RegisteredList from './RegisteredList';
import {useDispatch} from 'react-redux';
-import {setCourseName, setModalName, setScheduleId} from '@store/modalSlice.ts';
+import {
+ setCourseName,
+ setModalName,
+ setScheduleId,
+} from '@/store/modules/modalSlice';
import StartButton from '@components/CourseRegister/StartButton.tsx';
import {getCourseList, getRegisterdList, getWishlist} from '@/apis/api/course';
import {useAppSelector} from '@/store/hooks';
import {openModalHandler} from '../common/Modal/handlers/handler';
-import {setEndCount} from '@store/courseRegisteredSlice.ts';
+import {setEndCount} from '@/store/modules/courseRegisteredSlice';
const colData = [
{name: 'action', value: '신청', initialWidth: 30, enableFilters: false},
@@ -32,8 +36,10 @@ function CourseRegister() {
const [list, setList] = useState([]);
const [registeredList, setRegisteredList] = useState([]);
const [currentFilter, setCurrentFilter] = useState({});
- const [currentSearchOption, setCurrentSearchOption] = useState('관심과목');
- const [isRegistrationStarted, setIsRegistrationStarted] = useState(false);
+ const [currentSearchOption, setCurrentSearchOption] =
+ useState('관심과목');
+ const [isRegistrationStarted, setIsRegistrationStarted] =
+ useState(false);
const [isFirstSearch, setIsFirstSearch] = useState(true);
const dispatch = useDispatch();
@@ -56,7 +62,11 @@ function CourseRegister() {
setList(searchResult);
}, [currentFilter, currentSearchOption, studentId]);
- const handleSearch = async (newList: CourseTypes[], filter: CourseTypes, searchOption: string) => {
+ const handleSearch = async (
+ newList: CourseTypes[],
+ filter: CourseTypes,
+ searchOption: string,
+ ) => {
if (isRegistrationStarted && isFirstSearch) {
openModalHandler(dispatch, 'waiting');
setIsFirstSearch(false);
@@ -79,7 +89,6 @@ function CourseRegister() {
console.log('35초 지남');
dispatch(setEndCount(true));
}, 35000);
-
};
const handleAction = async (
@@ -96,10 +105,11 @@ function CourseRegister() {
return (
<>
-
+
-
수강대상교과목
@@ -110,10 +120,7 @@ function CourseRegister() {
height='35rem'
onAction={handleAction}
/>
-
+
>
);
}
diff --git a/src/components/Header/TopMenu.tsx b/src/components/Header/TopMenu.tsx
index ed85c77..c7e970c 100644
--- a/src/components/Header/TopMenu.tsx
+++ b/src/components/Header/TopMenu.tsx
@@ -4,7 +4,7 @@ import {useDispatch} from 'react-redux';
import Cookies from 'js-cookie';
import {baseAPI} from '@/apis/utils/instance';
import {useAppSelector} from '@/store/hooks';
-import {clearUserInfo} from '@/store/userSlice';
+import {clearUserInfo} from '@/store/modules/userSlice';
import {deleteAll} from '@/store/modules/tabSlice';
import logout from '@assets/img/logout.png';
import Clock from './Clock';
@@ -41,7 +41,7 @@ const LogoutBtn = styled.button`
background-size: 1.8rem;
width: 1.8rem;
height: 1.8rem;
- margin-right: 1rem;
+ margin-right: 1rem;
&:hover {
filter: brightness(20%);
}
diff --git a/src/components/Header/TopNav.tsx b/src/components/Header/TopNav.tsx
index 56fca4c..a251110 100644
--- a/src/components/Header/TopNav.tsx
+++ b/src/components/Header/TopNav.tsx
@@ -12,6 +12,10 @@ const TopNavContatiner = styled.div`
display: flex;
flex-shrink: 0;
align-items: center;
+
+ @media ${props => props.theme.device.mobile} {
+ display: none;
+ }
`;
const TopNavWrap = styled.div`
diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx
index f0ce012..adf1f40 100644
--- a/src/components/Header/index.tsx
+++ b/src/components/Header/index.tsx
@@ -8,9 +8,9 @@ function Header() {
+
-
@@ -18,30 +18,29 @@ function Header() {
}
const HeaderContainer = styled.div`
- border-top: 0.5rem solid ${props => props.theme.colors.primary};
- max-width: 100%;
- height: 7rem;
- display: flex;
- align-items: center;
- justify-content: space-between;
+ border-top: 0.5rem solid ${props => props.theme.colors.primary};
+ max-width: 100%;
+ height: 7rem;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
`;
const LogoBox = styled.div`
- display: flex;
- justify-content: center;
- align-items: center;
- width: 23rem;
- > img {
- height: 6rem;
- display: block;
- }
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 0 1rem;
+ > img {
+ height: 6rem;
+ display: block;
+ }
`;
const HeaderBox = styled.div`
- display: flex;
- flex-grow: 1;
- height: 100%;
- justify-content: space-between;
+ display: flex;
+ height: 100%;
+ justify-content: space-between;
`;
export default Header;
diff --git a/src/components/LectureList/Filters.tsx b/src/components/LectureList/Filters.tsx
index 2ad888c..ccae9dd 100644
--- a/src/components/LectureList/Filters.tsx
+++ b/src/components/LectureList/Filters.tsx
@@ -5,6 +5,12 @@ import FilterInput from '@components/common/FilterInput';
import SelectBox from '@components/common/SelectBox';
import {completion, major, optional, term} from '@assets/data/filter';
import {CourseTypes} from '@/assets/types/tableType';
+import {
+ FilterArea,
+ FilterBox,
+ FilterContainer,
+ FilterWrap,
+} from '@/styles/FilterLayout';
interface FiltersProps {
onSearch: (newList: CourseTypes[]) => Promise;
@@ -113,35 +119,6 @@ function Filters({onSearch}: FiltersProps) {
);
}
-export const FilterContainer = styled.div`
- border: 0.1rem solid #714656;
- border-radius: 2px;
- padding: 0.5rem 1.5rem;
- margin-bottom: 2rem;
-`;
-
-const FilterArea = styled.div`
- display: flex;
- align-items: flex-end;
- margin-bottom: 1rem;
-`;
-
-export const FilterBox = styled.div`
- display: flex;
- flex-wrap: wrap;
- gap: 0.7rem 3rem;
-`;
-
-export const FilterWrap = styled.div`
- ${props => props.theme.texts.tableTitle};
- > span {
- display: inline-block;
- margin-right: 1rem;
- text-align: right;
- min-width: 4.5rem;
- }
-`;
-
const WarningWrap = styled.div`
${props => props.theme.texts.warning};
color: #c30e2e;
diff --git a/src/components/LoginForm/index.tsx b/src/components/LoginForm/index.tsx
index d8f98f6..6d22923 100644
--- a/src/components/LoginForm/index.tsx
+++ b/src/components/LoginForm/index.tsx
@@ -4,7 +4,7 @@ import FormInput from './FormInput';
import {login} from '@/apis/api/auth';
import {useDispatch} from 'react-redux';
import {useNavigate} from 'react-router-dom';
-import {setUserInfo} from '@/store/userSlice';
+import {setUserInfo} from '@/store/modules/userSlice';
import {baseAPI} from '@/apis/utils/instance';
import Cookies from 'js-cookie';
import {generateRandomStudentId} from '@/utils/randomUtils.ts';
@@ -107,7 +107,6 @@ function LoginForm({isTermsCheck}: {isTermsCheck: boolean}) {
- {/*아이디 찾기 | 비밀번호 찾기*/}
{error && {error}}
로그인
@@ -117,7 +116,9 @@ function LoginForm({isTermsCheck}: {isTermsCheck: boolean}) {
}
const FormContainer = styled.div`
- padding: 1.5rem 4rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
background-color: ${props => props.theme.colors.white};
border-radius: 0.3rem;
margin-bottom: 2rem;
@@ -162,7 +163,7 @@ const LabelWrap = styled.div`
`;
const LoginBtnWrap = styled.button`
- width: 100%;
+ width: 90%;
height: 5rem;
background-color: ${props => props.theme.colors.secondary};
border: none;
diff --git a/src/components/Menubar/BarTitle.tsx b/src/components/Menubar/BarTitle.tsx
index 492ebe5..0c96b06 100644
--- a/src/components/Menubar/BarTitle.tsx
+++ b/src/components/Menubar/BarTitle.tsx
@@ -1,12 +1,17 @@
import styled from 'styled-components';
+import Close from '@assets/img/close-sidebar.svg?react';
-function BarTitle() {
+interface TitleProps {
+ setOpen: React.Dispatch>;
+}
+
+function BarTitle({setOpen}: TitleProps) {
return (
학부생수강시스템
-
-
-
+ setOpen(!prev)}>
+
+
);
}
@@ -16,7 +21,8 @@ const BarTitleContainer = styled.div`
height: 4rem;
display: flex;
align-items: center;
- justify-content: space-around;
+ justify-content: space-between;
+ padding: 0 1.5rem;
`;
const BarTitleWrap = styled.div`
@@ -25,15 +31,11 @@ const BarTitleWrap = styled.div`
color: ${props => props.theme.colors.white};
`;
-const IconBox = styled.div`
- display: flex;
- align-items: center;
- column-gap: 0.5rem;
-`;
-
const CloseBtn = styled.button`
display: flex;
align-items: center;
+ height: 100%;
+ width: 1.5rem;
`;
export default BarTitle;
diff --git a/src/components/Menubar/index.tsx b/src/components/Menubar/index.tsx
index fb482b1..82c7cad 100644
--- a/src/components/Menubar/index.tsx
+++ b/src/components/Menubar/index.tsx
@@ -1,18 +1,50 @@
import styled from 'styled-components';
import BarTitle from './BarTitle';
import Menu from './Menu';
+import Open from '@assets/img/close-sidebar.svg?react';
-function Menubar() {
+interface BarProps {
+ open: boolean;
+ setOpen: React.Dispatch>;
+}
+
+function Menubar({open, setOpen}: BarProps) {
return (
-
-
-
+
+ {open ? (
+
+
+
+
+ ) : (
+ setOpen(true)}>
+
+
+ )}
);
}
-const BarContainer = styled.div`
- width: 23rem;
+const BarContainer = styled.div<{$open: boolean}>`
+ min-width: ${props => (props.$open ? '23rem' : '2rem')};
+ background-color: ${props => props.theme.colors.white};
+
+ @media ${props => props.theme.device.mobile} {
+ position: absolute;
+ z-index: 999;
+ }
+`;
+
+const BarBox = styled.div``;
+
+const OpenBtnWrap = styled.button`
+ background-color: ${props => props.theme.colors.secondary};
+ width: 100%;
+ height: 4rem;
+`;
+
+const OpenBtn = styled(Open)`
+ transform: rotate(180deg);
`;
export default Menubar;
diff --git a/src/components/Wishlist/Filters.tsx b/src/components/Wishlist/Filters.tsx
index 0be5737..fd5f0f3 100644
--- a/src/components/Wishlist/Filters.tsx
+++ b/src/components/Wishlist/Filters.tsx
@@ -7,6 +7,12 @@ import {CourseTypes} from '@/assets/types/tableType';
import {openModalHandler} from '../common/Modal/handlers/handler';
import {useDispatch} from 'react-redux';
import {setField, setType} from '@/store/modules/errorSlice';
+import {
+ FilterArea,
+ FilterBox,
+ FilterContainer,
+ FilterWrap,
+} from '@/styles/FilterLayout';
const searchOptions = [
{id: 0, value: '학수번호 검색'},
@@ -148,7 +154,7 @@ function Filters({setSearchResults}: FiltersProps) {
-
+
조직분류
{}}
/>
-
-
+
+
년도/학기
{}}
/>
-
+
-
+
검색구분
handleInputChange('searchType', value || '')}
/>
-
+
{renderSearchForm()}
검색
@@ -183,31 +189,12 @@ function Filters({setSearchResults}: FiltersProps) {
);
}
-const FilterContainer = styled.div`
- border: 0.1rem solid #714656;
- border-radius: 2px;
- padding: 0.5rem 1.5rem;
- margin-bottom: 2rem;
-`;
-
-const FilterBox = styled.div`
- display: flex;
- flex-wrap: wrap;
- gap: 0.7rem 3rem;
-`;
-
-const FilterArea = styled.div`
- display: flex;
- align-items: flex-end;
- margin-bottom: 1rem;
-`;
-
const FilterBreak = styled.div`
flex-basis: 100%;
height: 0;
`;
-const FilterWrap = styled.div`
+const WishFilterWrap = styled(FilterWrap)`
${props => props.theme.texts.tableTitle};
display: flex;
align-items: center;
diff --git a/src/components/common/FilterInput.tsx b/src/components/common/FilterInput.tsx
index 9044513..5cf0917 100644
--- a/src/components/common/FilterInput.tsx
+++ b/src/components/common/FilterInput.tsx
@@ -1,4 +1,4 @@
-import styled, { css } from 'styled-components';
+import styled, {css} from 'styled-components';
interface InputInterface {
disabled?: boolean;
@@ -6,7 +6,7 @@ interface InputInterface {
onChange: (value: string) => void;
}
-function FilterInput({ disabled, sizes, onChange }: InputInterface) {
+function FilterInput({disabled, sizes, onChange}: InputInterface) {
return (
<>
`
+const InputWrap = styled.input<{sizes: string}>`
${props => props.theme.texts.content};
${props =>
props.sizes === 's' &&
css`
- width: 14rem;
+ max-width: 14rem;
+
+ @media ${props => props.theme.device.mobile} {
+ max-width: 14rem;
+ }
`};
${props =>
props.sizes === 'm' &&
css`
- width: 19.5rem;
+ max-width: 19.5rem;
+
+ @media ${props => props.theme.device.mobile} {
+ max-width: 19.5rem;
+ }
`};
- ${props =>
- props.sizes === 'l' &&
- css`
- width: 25rem;
- `};
${props =>
props.sizes === 'l' &&
css`
- width: 38.5rem;
- `};
- ${props =>
- props.sizes === 'xl' &&
- css`
- width: 48.5rem;
+ max-width: 25rem;
+
+ @media ${props => props.theme.device.mobile} {
+ max-width: 25rem;
+ }
`};
height: 2.4rem;
border: 1px solid ${props => props.theme.colors.neutral5};
padding-left: 0.8rem;
-
- &:disabled {
- background: ${props => props.theme.colors.neutral5};
- }
+
+ &:disabled {
+ background: ${props => props.theme.colors.neutral5};
+ }
`;
export default FilterInput;
diff --git a/src/components/common/Modal/WaitingModal.tsx b/src/components/common/Modal/WaitingModal.tsx
index e608ffb..305fc20 100644
--- a/src/components/common/Modal/WaitingModal.tsx
+++ b/src/components/common/Modal/WaitingModal.tsx
@@ -3,7 +3,7 @@ import logo from '@/assets/img/logo.webp';
import close from '@/assets/img/close-line.png';
import {useEffect, useState} from 'react';
import {useDispatch} from 'react-redux';
-import {clearModalInfo} from '@store/modalSlice.ts';
+import {clearModalInfo} from '@/store/modules/modalSlice';
import {getRandomInt} from '@/utils/randomUtils.ts';
function WaitingModal() {
diff --git a/src/components/common/Modal/handlers/handler.tsx b/src/components/common/Modal/handlers/handler.tsx
index 03724f4..822671d 100644
--- a/src/components/common/Modal/handlers/handler.tsx
+++ b/src/components/common/Modal/handlers/handler.tsx
@@ -1,5 +1,5 @@
import {Dispatch} from 'redux';
-import {clearModalInfo, setModalName} from '@store/modalSlice';
+import {clearModalInfo, setModalName} from '@/store/modules/modalSlice';
export const closeHandler = (dispatch: Dispatch) => {
dispatch(clearModalInfo());
diff --git a/src/components/common/SelectBox.tsx b/src/components/common/SelectBox.tsx
index c07384c..ed8842a 100644
--- a/src/components/common/SelectBox.tsx
+++ b/src/components/common/SelectBox.tsx
@@ -69,7 +69,7 @@ function SelectBox({options, disabled = false, sizes, onSelect}: SelectProps) {
{open && (
-
+
{filtered.map(option => (
`
props.sizes === 's' &&
css`
width: 15rem;
+
+ @media ${props => props.theme.device.mobile} {
+ max-width: 15rem;
+ }
`};
${props =>
props.sizes === 'm' &&
css`
width: 20.5rem;
+
+ @media ${props => props.theme.device.mobile} {
+ max-width: 20.5rem;
+ }
`};
${props =>
props.sizes === 'xl' &&
css`
width: 50rem;
+
+ @media ${props => props.theme.device.mobile} {
+ max-width: 50rem;
+ }
`};
+ min-width: 7rem;
height: 2.4rem;
position: relative;
display: inline-block;
@@ -144,7 +157,7 @@ const ArrowWrap = styled.img`
`;
const SelectWrap = styled.ul`
- width: inherit;
+ min-width: 15rem;
max-height: 12rem;
position: absolute;
top: 100%;
diff --git a/src/components/common/Table/index.tsx b/src/components/common/Table/index.tsx
index eae7404..805103d 100644
--- a/src/components/common/Table/index.tsx
+++ b/src/components/common/Table/index.tsx
@@ -237,6 +237,10 @@ const NoresultWrap = styled.tr<{width: number; height: string}>`
display: flex;
align-items: center;
justify-content: center;
+
+ @media ${props => props.theme.device.mobile} {
+ max-width: auto;
+ }
`;
const Noresult = styled.td`
diff --git a/src/pages/index/Home.tsx b/src/pages/index/Home.tsx
index 5169fe3..b5e3c62 100644
--- a/src/pages/index/Home.tsx
+++ b/src/pages/index/Home.tsx
@@ -1,3 +1,4 @@
+import {useEffect, useState} from 'react';
import styled from 'styled-components';
import Menubar from '@components/Menubar';
import Header from '@components/Header';
@@ -12,12 +13,14 @@ import EnrollmentInfoModal from '@components/common/Modal/EnrollmentInfoModal.ts
import LoadingModal from '@components/common/Modal/LoadingModal.tsx';
import WaitingModal from '@components/common/Modal/WaitingModal.tsx';
import {useDispatch} from 'react-redux';
-import {clearModalInfo} from '@store/modalSlice.ts';
+import {clearModalInfo} from '@/store/modules/modalSlice';
import ErrorModal from '@components/common/Modal/ErrorModal.tsx';
-import {useEffect} from 'react';
+import {useMediaQuery} from 'react-responsive';
function Home() {
+ const isPc = useMediaQuery({query: '(min-width: 1024px)'});
const {tab, focused} = useAppSelector(state => state.tabs);
+ const [barOpen, setBarOpen] = useState(isPc);
const {modalName, scheduleId, courseName} = useAppSelector(
state => state.modalInfo,
@@ -82,8 +85,8 @@ function Home() {
{renderModal()}
-
-
+
+
{focusedTabName}
@@ -101,10 +104,18 @@ const Container = styled.div`
const Box = styled.div`
display: flex;
+ max-width: 100vw;
`;
-const Main = styled.div`
- width: calc(100% - 23rem);
+const Main = styled.div<{$isOpen: boolean}>`
+ width: ${props =>
+ props.$isOpen ? 'calc(100% - 23rem)' : 'calc(100% - 2rem)'};
+
+ @media ${props => props.theme.device.mobile} {
+ width: calc(100% - 2rem);
+ position: absolute;
+ left: 2rem;
+ }
`;
const Article = styled.div`
diff --git a/src/pages/index/Login.tsx b/src/pages/index/Login.tsx
index a5f5f6f..05b939e 100644
--- a/src/pages/index/Login.tsx
+++ b/src/pages/index/Login.tsx
@@ -53,8 +53,14 @@ function Login() {
1. 서비스 목적
- 본 서비스는 실제 수강신청 사이트가 아니며, 학습 목적으로 제공되는 모의 수강신청 시스템입니다. 본 서비스에서 사용하는
- 학번은 실제 학번이 아닌, 11자리 이상의 임의로 생성된 학번입니다.
+
+ 본 서비스는 실제 수강신청 사이트가 아니며
+ , 학습 목적으로 제공되는 모의 수강신청 시스템입니다. 본
+ 서비스에서 사용하는 학번은{' '}
+
+ 실제 학번이 아닌, 11자리 이상의 임의로 생성된 학번
+
+ 입니다.
@@ -62,64 +68,123 @@ function Login() {
2. 개인정보의 수집 및 이용
- 수집하는 개인정보 항목: 본 서비스에서는 사용자가 입력한 임의의 학번, 비밀번호, 관심과목, 수강신청 목록을
- 수집합니다.
- 개인정보 수집 목적: 수집된 정보는 사용자가 저장한 과목 목록을 불러오기 위한 용도로만 사용됩니다. 그 외 다른
- 목적으로는 절대 사용되지 않습니다.
- 개인정보의 보유 및 이용 기간: 수집된 정보는 매일 자정에 자동으로 삭제되며, 추가적인 보관 기간은 없습니다.
- 수집된 정보의 저장 위치: 수집된 정보는 안전한 서버에 저장되며, 외부로 유출되지 않도록 보호됩니다.
+
+ 수집하는 개인정보 항목: 본 서비스에서는 사용자가 입력한 임의의{' '}
+
+ 학번, 비밀번호, 관심과목, 수강신청 목록을 수집
+
+ 합니다.
+
+
+ 개인정보 수집 목적: 수집된 정보는{' '}
+
+ 사용자가 저장한 과목 목록을 불러오기 위한 용도
+
+ 로만 사용됩니다.{' '}
+
+ 그 외 다른 목적으로는 절대 사용되지 않습니다.
+
+
+
+ 개인정보의 보유 및 이용 기간: 수집된 정보는{' '}
+ 매일 자정에 자동으로 삭제되며, 추가적인
+ 보관 기간은 없습니다.
+
+
+ 수집된 정보의 저장 위치: 수집된 정보는{' '}
+ 안전한 서버에 저장되며,{' '}
+ 외부로 유출되지 않도록 보호됩니다.
+
3. 비밀번호 및 보안
- 본 서비스에 입력된 비밀번호는 암호화 알고리즘을 사용하여 안전하게 보호됩니다. 비밀번호는 복호화가 불가능하며, 실제
- 사용하는 비밀번호가 아닌 임의의 비밀번호를 사용하는 것을 권장합니다.
+
+ 본 서비스에 입력된 비밀번호는{' '}
+ 암호화 알고리즘을 사용하여 안전하게 보호
+ 됩니다. 비밀번호는 복호화가 불가능하며,{' '}
+
+ 실제 사용하는 비밀번호가 아닌 임의의 비밀번호를 사용하는 것을
+ 권장
+
+ 합니다.
+
4. 개인정보의 파기
- 수집된 개인정보는 매일 자정에 자동으로 서버에서 삭제됩니다. 만약 자정 전에 정보를 삭제하고 싶으신 경우,
- navigate('/delete')}>https://tutorial-sejong.com/delete 페이지에서 로그인 시 입력한 학번을 입력하여 직접 삭제할 수 있습니다.
- 학번을 기억하지 못할 경우, tutorialsejong@gmail.com으로 메일을 보내주시면 관심과목 목록 및 로그인 시간을 기준으로 삭제를 도와드리겠습니다. 만약 확인이
- 불가능한 경우, 모든 정보를 일괄적으로 삭제 처리하겠습니다.
+
+ 수집된 개인정보는{' '}
+ 매일 자정에 자동으로 서버에서 삭제됩니다.
+ 만약 자정 전에 정보를 삭제하고 싶으신 경우,
+ navigate('/delete')}>
+ https://tutorial-sejong.com/delete
+ {' '}
+ 페이지에서 로그인 시 입력한{' '}
+ 학번을 입력하여 직접 삭제할 수 있습니다.
+
+
+ 학번을 기억하지 못할 경우,{' '}
+ tutorialsejong@gmail.com으로 메일을
+ 보내주시면 관심과목 목록 및 로그인 시간을 기준으로 삭제를
+ 도와드리겠습니다. 만약 확인이 불가능한 경우,{' '}
+ 모든 정보를 일괄적으로 삭제 처리
+ 하겠습니다.
+
5. 개인정보의 파기
- 사용자는 언제든지 본 서비스에 제공된 개인정보의 삭제를 요청할 수 있으며, 삭제 요청은 위의 방법을 통해 처리됩니다.
- 개인정보와 관련된 문의는 tutorialsejong@gmail.com으로 문의하시면 신속히 대응해드리겠습니다.
+
+ 사용자는 언제든지 본 서비스에 제공된 개인정보의 삭제를 요청할 수
+ 있으며, 삭제 요청은 위의 방법을 통해 처리됩니다.
+
+
+ 개인정보와 관련된 문의는{' '}
+ tutorialsejong@gmail.com으로 문의하시면
+ 신속히 대응해드리겠습니다.
+
6. 개인정보의 보호
- 본 서비스는 개인정보 보호법과 정보통신망법에 따라 사용자의 개인정보를 보호하기 위해 최선을 다하고 있습니다. 수집된 개인정보는 불법적인 접근, 유출, 사용을 방지하기 위해 방화벽, 암호화 통신, 접근 통제 등 적절한 보안 조치를 취하고 있습니다.
+
+ 본 서비스는 개인정보 보호법과 정보통신망법에 따라 사용자의
+ 개인정보를 보호하기 위해 최선을 다하고 있습니다. 수집된
+ 개인정보는 불법적인 접근, 유출, 사용을 방지하기 위해 방화벽,
+ 암호화 통신, 접근 통제 등 적절한 보안 조치를 취하고 있습니다.
+
7. 개인정보 처리방침 변경
- 본 서비스의 개인정보 처리방침은 법률 개정이나 서비스 변경에 따라 수정될 수 있으며, 수정된 내용은 이 페이지에서 확인 가능합니다.
+
+ 본 서비스의 개인정보 처리방침은 법률 개정이나 서비스 변경에 따라
+ 수정될 수 있으며, 수정된 내용은 이 페이지에서 확인 가능합니다.
+
-
@@ -129,147 +194,133 @@ function Login() {
}
const Container = styled.div`
- background: url(${Bg}) 50% 50% no-repeat;
- background-size: cover;
- height: 700px;
- background-color: #fafafa;
- width: 100%;
+ background: url(${Bg}) 50% 50% no-repeat;
+ background-size: cover;
+ height: 700px;
+ background-color: #fafafa;
+ width: 100%;
`;
const Box = styled.div`
- display: flex;
- flex-direction: column;
- align-items: center;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
`;
const LogoWrap = styled.div`
- margin: 3rem 0;
+ margin: 3rem 0;
- > img {
- width: 150px;
- }
+ > img {
+ width: 150px;
+ }
`;
const TitleWrap = styled.div`
- color: ${props => props.theme.colors.white};
- text-align: center;
- margin-bottom: 2.5rem;
+ color: ${props => props.theme.colors.white};
+ text-align: center;
+ padding: 0 1rem;
+ margin-bottom: 2.5rem;
- > p {
- line-height: 2.5rem;
- font-weight: 600;
- font-size: 1.35rem;
- }
+ > p {
+ line-height: 2.5rem;
+ font-weight: 600;
+ font-size: 1.35rem;
+ }
- > p > em {
- color: #ffea9b;
- }
+ > p > em {
+ color: #ffea9b;
+ }
`;
const Title = styled.h1`
- font-size: 3.5rem;
- font-weight: 700;
- margin-bottom: 2rem;
+ font-size: 3.5rem;
+ font-weight: 700;
+ margin-bottom: 2rem;
`;
const SubTitle = styled.h2`
- font-size: 2rem;
- font-weight: 700;
- margin-bottom: 2rem;
+ font-size: 2rem;
+ font-weight: 700;
+ margin-bottom: 2rem;
`;
const FormWrap = styled.div`
- margin-bottom: 2.5rem;
-`;
+ width: 46rem;
+ margin-bottom: 2.5rem;
-// const WarningWrap = styled.p`
-// ${props => props.theme.texts.loginContent};
-// margin-bottom: 2.5rem;
-// `;
-
-const FaqWrap = styled.div`
- ${props => props.theme.texts.loginContent};
-
- > img {
- width: 30px;
- cursor: pointer;
- display: block;
- text-align: center;
- margin: 20px auto;
- }
+ @media ${props => props.theme.device.mobile} {
+ width: 100%;
+ }
`;
-/*const FooterWrap = styled.div`
+const FaqWrap = styled.div`
${props => props.theme.texts.loginContent};
- letter-spacing: 0;
- > em {
- color: ${props => props.theme.colors.black};
- }
- > p {
- color: gray;
+
+ > img {
+ width: 30px;
+ cursor: pointer;
+ display: block;
text-align: center;
- font-weight: 500;
- font-size: 1.2rem;
- margin: 0.7rem 0 3rem 0;
+ margin: 20px auto;
}
-`;*/
+`;
const TermsContainer = styled.div`
- max-width: 890px;
- margin: 0 auto 20px;
- padding: 20px;
- background-color: #f9f9f9;
- border-radius: 10px;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+ max-width: 890px;
+ margin: 0 auto 20px;
+ padding: 20px;
+ background-color: #f9f9f9;
+ border-radius: 10px;
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
`;
const CheckboxWrap = styled.div`
- display: flex;
- justify-content: center;
- align-items: center;
- margin-left: -0.5rem;
- margin-top: 1rem;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ margin-left: -0.5rem;
+ margin-top: 1rem;
`;
const TermsTitle = styled.h1`
- font-size: 24px;
- font-weight: bold;
- color: #333;
- margin-bottom: 20px;
+ font-size: 24px;
+ font-weight: bold;
+ color: #333;
+ margin-bottom: 20px;
`;
const List = styled.ul`
- list-style: none;
- padding: 0;
- margin: 0;
+ list-style: none;
+ padding: 0;
+ margin: 0;
`;
const ListTitle = styled.li`
- font-size: 18px;
- font-weight: bold;
- margin-top: 15px;
- margin-bottom: 15px;
+ font-size: 18px;
+ font-weight: bold;
+ margin-top: 15px;
+ margin-bottom: 15px;
`;
const ListItem = styled.li`
- margin-bottom: 5px;
- font-size: 15px;
- color: #555;
- line-height: 2.5rem;
+ margin-bottom: 5px;
+ font-size: 15px;
+ color: #555;
+ line-height: 2.5rem;
- &::before {
- content: '•';
- color: #007bff;
- font-weight: bold;
- display: inline-block;
- width: 1em;
- margin-left: 0.5em;
- }
+ &::before {
+ content: '•';
+ color: #007bff;
+ font-weight: bold;
+ display: inline-block;
+ width: 1em;
+ margin-left: 0.5em;
+ }
`;
const Highlight = styled.span`
- cursor: pointer;
- font-weight: bold;
- color: #007bff;
+ cursor: pointer;
+ font-weight: bold;
+ color: #007bff;
`;
export default Login;
diff --git a/src/store/courseRegisteredSlice.ts b/src/store/modules/courseRegisteredSlice.ts
similarity index 100%
rename from src/store/courseRegisteredSlice.ts
rename to src/store/modules/courseRegisteredSlice.ts
diff --git a/src/store/modalSlice.ts b/src/store/modules/modalSlice.ts
similarity index 100%
rename from src/store/modalSlice.ts
rename to src/store/modules/modalSlice.ts
diff --git a/src/store/userSlice.ts b/src/store/modules/userSlice.ts
similarity index 100%
rename from src/store/userSlice.ts
rename to src/store/modules/userSlice.ts
diff --git a/src/store/store.ts b/src/store/store.ts
index 6564be8..6f05a2e 100644
--- a/src/store/store.ts
+++ b/src/store/store.ts
@@ -2,9 +2,9 @@ import {combineReducers, configureStore} from '@reduxjs/toolkit';
import {persistReducer} from 'redux-persist';
import storage from 'redux-persist/lib/storage';
-import userSlice from '@store/userSlice.ts';
-import modalSlice from '@store/modalSlice.ts';
-import courseRegisteredSlice from '@store/courseRegisteredSlice.ts';
+import userSlice from '@/store/modules/userSlice';
+import modalSlice from '@/store/modules/modalSlice';
+import courseRegisteredSlice from '@/store/modules/courseRegisteredSlice';
import tabSlice from './modules/tabSlice';
import errorSlice from './modules/errorSlice';
diff --git a/src/styles/FilterLayout.tsx b/src/styles/FilterLayout.tsx
new file mode 100644
index 0000000..22e202b
--- /dev/null
+++ b/src/styles/FilterLayout.tsx
@@ -0,0 +1,39 @@
+import styled from 'styled-components';
+
+export const FilterContainer = styled.div`
+ border: 0.1rem solid #714656;
+ border-radius: 2px;
+ padding: 0.5rem 1.5rem;
+ margin-bottom: 2rem;
+`;
+
+export const FilterArea = styled.div`
+ display: flex;
+ align-items: flex-end;
+ margin-bottom: 1rem;
+ gap: 0.7rem 3rem;
+
+ @media ${props => props.theme.device.mobile} {
+ flex-wrap: wrap;
+ }
+`;
+
+export const FilterBox = styled.div`
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.7rem 3rem;
+`;
+
+export const FilterWrap = styled.div`
+ ${props => props.theme.texts.tableTitle};
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.7rem 0;
+ align-items: center;
+
+ > span {
+ margin-right: 1rem;
+ text-align: right;
+ min-width: 4.5rem;
+ }
+`;
diff --git a/src/styles/theme/Theme.ts b/src/styles/theme/Theme.ts
index 0f8db80..213d6b7 100644
--- a/src/styles/theme/Theme.ts
+++ b/src/styles/theme/Theme.ts
@@ -62,10 +62,18 @@ const texts = {
},
};
+const device = {
+ mobile: 'screen and (max-width: 767px)',
+ tablet: 'screen and (min-width: 768px) and (max-width: 1023px)',
+ pc: 'screen and (min-width: 1024px)',
+};
+
export type ColorsType = typeof colors;
export type TextsType = typeof texts;
+export type DeviceType = typeof device;
export const theme: DefaultTheme = {
colors,
texts,
+ device,
};
diff --git a/src/styles/theme/style.d.ts b/src/styles/theme/style.d.ts
index 8dffb0f..389a5b8 100644
--- a/src/styles/theme/style.d.ts
+++ b/src/styles/theme/style.d.ts
@@ -1,9 +1,10 @@
import 'styled-components';
-import { ColorsType, TextsType } from './Theme';
+import {ColorsType, DeviceType, TextsType} from './Theme';
declare module 'styled-components' {
export interface DefaultTheme {
colors: ColorsType;
texts: TextsType;
+ device: DeviceType;
}
-}
\ No newline at end of file
+}