diff --git a/public/png/mood_BAD.png b/public/png/mood_BAD.png
new file mode 100644
index 0000000..0926ec9
Binary files /dev/null and b/public/png/mood_BAD.png differ
diff --git a/public/png/mood_GOOD.png b/public/png/mood_GOOD.png
new file mode 100644
index 0000000..ccdb080
Binary files /dev/null and b/public/png/mood_GOOD.png differ
diff --git a/public/svg/add.svg b/public/svg/add.svg
new file mode 100644
index 0000000..9f98254
--- /dev/null
+++ b/public/svg/add.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/features/setting/Container.tsx b/src/features/setting/Container.tsx
index 35df6c2..530abf1 100644
--- a/src/features/setting/Container.tsx
+++ b/src/features/setting/Container.tsx
@@ -1,54 +1,34 @@
-import { Controller } from 'react-hook-form';
+import { useAtom } from 'jotai';
+import { useLayoutEffect } from 'react';
+
+import { bottomBtnAtom, titleAtom } from '../shared/layout/atom';
-import './style/index.scss';
-import { colorset } from './constants';
import useSetting from './hooks/useSetting';
+import './style/index.scss';
+import PreviewSection from './components/PreviewSection';
+import SubmitForm from './components/SubmitForm';
const Container = () => {
- const { register, handleSubmit, control, onSubmit } = useSetting();
+ const [, setTitle] = useAtom(titleAtom);
+ const [, setBottomBtn] = useAtom(bottomBtnAtom);
- return (
-
-
+ return (
+
);
};
diff --git a/src/features/setting/components/PreviewSection.tsx b/src/features/setting/components/PreviewSection.tsx
new file mode 100644
index 0000000..3ae1db0
--- /dev/null
+++ b/src/features/setting/components/PreviewSection.tsx
@@ -0,0 +1,23 @@
+import { FunctionComponent } from 'react';
+
+import { previewSubText, previewTitleText } from '../constants';
+
+type PreviewSectionProps = {
+ handlePreviewClick: () => void;
+};
+
+const PreviewSection: FunctionComponent
= ({
+ handlePreviewClick,
+}) => {
+ return (
+
+
{previewTitleText}
+
{previewSubText}
+
+
+ );
+};
+
+export default PreviewSection;
diff --git a/src/features/setting/components/SubmitForm/DailySticker.tsx b/src/features/setting/components/SubmitForm/DailySticker.tsx
new file mode 100644
index 0000000..29614e7
--- /dev/null
+++ b/src/features/setting/components/SubmitForm/DailySticker.tsx
@@ -0,0 +1,54 @@
+import { FunctionComponent } from 'react';
+import { Controller } from 'react-hook-form';
+import { Control } from 'react-hook-form';
+
+import { Inputs } from '../../types';
+import { stickerList, wordStickerText } from '../../constants';
+
+import '../../style/index.scss';
+
+type DailyStickerProps = {
+ control: Control;
+};
+
+const DailySticker: FunctionComponent = ({ control }) => {
+ return (
+
+
{wordStickerText}
+
(
+
+ )}
+ />
+
+ );
+};
+
+export default DailySticker;
diff --git a/src/features/setting/components/SubmitForm/DailyWord.tsx b/src/features/setting/components/SubmitForm/DailyWord.tsx
new file mode 100644
index 0000000..cf61dc9
--- /dev/null
+++ b/src/features/setting/components/SubmitForm/DailyWord.tsx
@@ -0,0 +1,21 @@
+import { FunctionComponent } from 'react';
+import { UseFormRegister } from 'react-hook-form';
+
+import { Inputs } from '../../types';
+import { wordTitleText } from '../../constants';
+import '../../style/index.scss';
+
+type DailyWordProps = {
+ register: UseFormRegister;
+};
+
+const DailyWord: FunctionComponent = ({ register }) => {
+ return (
+
+ {wordTitleText}
+
+
+ );
+};
+
+export default DailyWord;
diff --git a/src/features/setting/components/SubmitForm/index.tsx b/src/features/setting/components/SubmitForm/index.tsx
new file mode 100644
index 0000000..509a008
--- /dev/null
+++ b/src/features/setting/components/SubmitForm/index.tsx
@@ -0,0 +1,48 @@
+import { useAtom } from 'jotai';
+import { FunctionComponent, useEffect, useRef } from 'react';
+import {
+ UseFormHandleSubmit,
+ SubmitHandler,
+ UseFormRegister,
+ Control,
+} from 'react-hook-form';
+
+import { activeSaveAtom } from '../../../shared/layout/atom';
+import { Inputs } from '../../types';
+
+import DailySticker from './DailySticker';
+import DailyWord from './DailyWord';
+
+type SubmitFormProps = {
+ handleSubmit: UseFormHandleSubmit;
+ onSubmit: SubmitHandler;
+ register: UseFormRegister;
+ control: Control;
+};
+
+const SubmitForm: FunctionComponent = ({
+ handleSubmit,
+ onSubmit,
+ register,
+ control,
+}) => {
+ const [activeSave, setActiveSave] = useAtom(activeSaveAtom);
+
+ const inputRef = useRef(null);
+
+ useEffect(() => {
+ if (!activeSave) return;
+ setActiveSave(false);
+ inputRef.current?.click();
+ }, [activeSave]);
+
+ return (
+
+ );
+};
+
+export default SubmitForm;
diff --git a/src/features/setting/constants.ts b/src/features/setting/constants.ts
index b4ca5bd..d957670 100644
--- a/src/features/setting/constants.ts
+++ b/src/features/setting/constants.ts
@@ -1 +1,9 @@
export const colorset = ['red', 'yellow', 'green'];
+export const stickerList = ['mood_BAD', 'mood_GOOD'];
+
+export const previewTitleText = 'What is the Active Setting?';
+export const previewSubText =
+ 'Congratulations on winning! Press the button to get a giftCongratulations on winning! Press the button to get a giftCongratulations on winning!';
+
+export const wordTitleText = 'Word of the day';
+export const wordStickerText = 'Word of the Sticker';
diff --git a/src/features/setting/hooks/useSetting.ts b/src/features/setting/hooks/useSetting.ts
index f739f74..a90b551 100644
--- a/src/features/setting/hooks/useSetting.ts
+++ b/src/features/setting/hooks/useSetting.ts
@@ -1,21 +1,29 @@
import { useForm, SubmitHandler } from 'react-hook-form';
+import { useNavigate } from 'react-router-dom';
import { Inputs } from '../types';
+import { URL } from '../../shared/constants/url';
const useSetting = () => {
const { register, handleSubmit, control } = useForm({
defaultValues: {
- mude: 'green',
- comment: '퇴근!',
+ mude: '',
+ comment: '',
},
});
+ const navigate = useNavigate();
const onSubmit: SubmitHandler = (data) => console.log(data);
+ const handlePreviewClick = () => {
+ navigate(URL.preview);
+ };
+
return {
register,
handleSubmit,
control,
onSubmit,
+ handlePreviewClick,
};
};
diff --git a/src/features/setting/style/index.scss b/src/features/setting/style/index.scss
index c81079f..40cc527 100644
--- a/src/features/setting/style/index.scss
+++ b/src/features/setting/style/index.scss
@@ -1,5 +1,124 @@
.setting {
&-container {
width: 100%;
+ height: calc(100% - 159px);
+ background: #F7F7F7;
}
+
+ &-preview-container {
+ display: flex;
+ padding: 24px 16px;
+ flex-direction: column;
+ align-items: center;
+ align-self: stretch;
+ background-color: #FFFFFF;
+ }
+
+ &-preview-title-text {
+ height: fit-content;
+ margin-bottom: 4px;
+ color: #191919;
+ text-align: center;
+ font-size: 24px;
+ font-style: normal;
+ font-weight: 700;
+ line-height: 36px; /* 150% */
+ }
+
+ &-preview-sub-text {
+ margin-bottom: 16px;
+ color: #9797AE;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: 24px; /* 171.429% */
+ }
+
+ &-preview-btn {
+ display: flex;
+ width: 100%;
+ height: 48px;
+ padding: 0px 14px;
+ justify-content: center;
+ align-items: center;
+ align-self: stretch;
+ border: 1px solid #191919;
+ color: #191919;
+ background-color: #FFFFFF;
+ cursor: pointer;
+ }
+
+ &-word-container {
+ height: 68px;
+ display: flex;
+ gap: 4px;
+ padding: 16px;
+ margin: 12px 0;
+ flex-direction: column;
+ align-items: flex-start;
+ align-self: stretch;
+ background: #FFFFFF;
+ }
+
+ &-word-title {
+ color: #000;
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px; /* 171.429% */
+ }
+
+ &-word-input {
+ display: flex;
+ align-items: center;
+ align-self: stretch;
+ border: 1px solid #191919;
+ height: 40px;
+ }
+
+ &-sticker-container {
+ display: flex;
+ padding: 16px;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 8px;
+ flex: 1 0 0;
+ align-self: stretch;
+ background: #FFF;
+ }
+
+ &-sticker-title {
+ color: #000;
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 500;
+ line-height: 24px; /* 150% */
+ margin-bottom: 8px;
+ }
+
+ &-sticker-box {
+ display: flex;
+ height: 100%;
+ width: 100%;
+ justify-content: space-between;
+ align-items: flex-start;
+ align-content: flex-start;
+ gap: 8px;
+ flex-wrap: wrap;
+
+ input {
+ appearance: none;
+ -webkit-appearance: none;
+ }
+ input:checked {
+ outline: 1px solid #000;
+ }
+ }
+
+ &-sticker-width {
+ width: 48%;
+ img {
+ width: 100%;
+ }
+ }
}
\ No newline at end of file
diff --git a/src/features/shared/layout/Container.tsx b/src/features/shared/layout/Container.tsx
index 454dc1c..988a84f 100644
--- a/src/features/shared/layout/Container.tsx
+++ b/src/features/shared/layout/Container.tsx
@@ -4,6 +4,7 @@ import { Outlet } from 'react-router-dom';
import './layout.scss';
import useLayout from './hooks/useLayout';
import LayoutTitle from './components/Title';
+import LayoutBottomBtn from './components/BottomBtn';
const LayoutContainer: FunctionComponent = () => {
useLayout();
@@ -11,6 +12,7 @@ const LayoutContainer: FunctionComponent = () => {
+
);
};
diff --git a/src/features/shared/layout/atom.ts b/src/features/shared/layout/atom.ts
index 95c96dd..b2c99d0 100644
--- a/src/features/shared/layout/atom.ts
+++ b/src/features/shared/layout/atom.ts
@@ -6,3 +6,11 @@ type TitleAtom = {
};
export const titleAtom = atom({});
+
+type BottomBtnAtom = {
+ text?: string;
+ add?: boolean;
+};
+export const bottomBtnAtom = atom({});
+
+export const activeSaveAtom = atom(false);
diff --git a/src/features/shared/layout/components/BottomBtn.tsx b/src/features/shared/layout/components/BottomBtn.tsx
new file mode 100644
index 0000000..39926f0
--- /dev/null
+++ b/src/features/shared/layout/components/BottomBtn.tsx
@@ -0,0 +1,27 @@
+import { useAtom } from 'jotai';
+import { FunctionComponent } from 'react';
+
+import { activeSaveAtom, bottomBtnAtom } from '../atom';
+
+import addLogo from '/svg/add.svg';
+
+const LayoutBottomBtn: FunctionComponent = () => {
+ const [{ text, add }] = useAtom(bottomBtnAtom);
+ const [, setActiveSave] = useAtom(activeSaveAtom);
+
+ if (!text) return ;
+
+ return (
+
+
setActiveSave(true)}>
+
+ {add &&
}
+
+
{text}
+
+
+
+ );
+};
+
+export default LayoutBottomBtn;
diff --git a/src/features/shared/layout/layout.scss b/src/features/shared/layout/layout.scss
index 7c75d0e..03af1c6 100644
--- a/src/features/shared/layout/layout.scss
+++ b/src/features/shared/layout/layout.scss
@@ -3,11 +3,13 @@
.layout-container {
min-width: 320px;
max-width: 480px;
+ height: 100%;
background-color: $container-color;
}
.layout-title {
display: flex;
+ justify-content: space-between;
align-items: center;
height: 61px;
padding: 8px;
@@ -18,7 +20,7 @@
}
.left {
- width: 48px;
+ width: 20px;
height: 48px;
padding: 0px 14px;
display: flex;
@@ -30,8 +32,6 @@
display: flex;
align-items: center;
justify-content: center;
-
- width: 247px;
height: 36px;
padding: 6px 8px;
gap: 10px;
@@ -39,4 +39,30 @@
font-size: 24px;
line-height: 24px;
}
+}
+
+.layout-bottom {
+ display: flex;
+ padding: 16px;
+ align-items: flex-start;
+ gap: 8px;
+ align-self: stretch;
+ border-top: 1px solid #E9E9F1;
+ background: #FFF;
+ position: sticky;
+ bottom: 0;
+ width: 100%;
+ box-sizing: border-box;
+}
+.layout-bottom-btn {
+ display: flex;
+ height: 48px;
+ padding: 0px 14px;
+ justify-content: center;
+ align-items: center;
+ flex: 1 0 0;
+ gap: 8px;
+ background: #191919;
+ color: #FFF;
+ cursor: pointer;
}
\ No newline at end of file
diff --git a/src/features/shared/style/global.scss b/src/features/shared/style/global.scss
index 2cce1b9..cdaa48b 100644
--- a/src/features/shared/style/global.scss
+++ b/src/features/shared/style/global.scss
@@ -10,3 +10,8 @@ body {
min-height: 100vh;
background-color: $other-area-color;
}
+#root {
+ width: 100%;
+ display: flex;
+ justify-content: center;
+}
\ No newline at end of file