Skip to content

Commit

Permalink
Merge pull request #139 from Kusitms-29th-ASAP/feat/#138
Browse files Browse the repository at this point in the history
[Feat] 홈, 소식 번역 기능
  • Loading branch information
yyypearl authored Aug 31, 2024
2 parents 4985035 + 5b52739 commit ffe5437
Show file tree
Hide file tree
Showing 15 changed files with 506 additions and 57 deletions.
7 changes: 6 additions & 1 deletion src/components/common/ListBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,12 @@ const Time = styled.div`
${(props) => props.theme.fonts.caption2_m};
border-radius: 0px 8px 8px 0px;
background: rgba(255, 135, 0, 0.15);
white-space: nowrap;
white-space: normal;
overflow-wrap: break-word;
word-break: break-word;
-webkit-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
&.mint {
color: ${theme.colors.sub_mint};
background: rgba(5, 206, 194, 0.15);
Expand Down
4 changes: 3 additions & 1 deletion src/components/common/Popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,13 @@ const Title = styled.div`
position: sticky;
top: 0;
background: ${theme.colors.white};
z-index: 1;
z-index: 100;
`;

const TitleBox = styled.div`
width: 100%;
background: ${theme.colors.white};
z-index: 100;
`;

const ImageBox = styled.div`
Expand Down
46 changes: 31 additions & 15 deletions src/components/home/AddTodoPopup.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { theme } from "@/styles/theme";
import styled from "styled-components";
import { useState } from "react";
import { useEffect, useState } from "react";
import Button from "../common/Button";
import CustomInput from "../common/CustomInput";
import Popup from "../common/Popup";
import Calendar from "../common/Calendar";
import Axios from "@/apis/axios";

export const categories = [
{ value: "SCHOOL_ANNOUNCEMENT", label: "가정통신문" },
{ value: "HOMEWORK", label: "숙제" },
{ value: "SUPPLY", label: "준비물" },
{ value: "ETC", label: "기타" },
{ value: "NONE", label: "없음" },
];
import {
addTodoMessage,
calendarPlaceHolder,
categories,
LanguageKeys,
submitMessage,
todoPlaceHolder,
whenTodoMessage,
} from "@/data/todoData";

interface AddTodoPopupProps {
onClose: () => void;
Expand All @@ -32,6 +33,11 @@ const AddTodoPopup = ({
const [category, setCategory] = useState("");
const [selectedDate, setSelectedDate] = useState("");
const isButtonEnabled = todo !== "" && category !== "" && selectedDate !== "";
const [language, setLanguage] = useState<string>("ko");

useEffect(() => {
setLanguage(localStorage.getItem("language") || "ko");
}, []);

const handleCategoryChange = (value: string) => {
setCategory(value);
Expand Down Expand Up @@ -70,10 +76,14 @@ const AddTodoPopup = ({

return (
<>
<Popup onClose={onClose} title="할 일 직접 추가하기" height="435px">
<Popup
onClose={onClose}
title={`${addTodoMessage[language as keyof typeof addTodoMessage]}`}
height="435px"
>
<CustomInput
value={todo}
placeholder="할 일을 입력해주세요"
placeholder={`${todoPlaceHolder[language as keyof typeof todoPlaceHolder]}`}
onChange={(value: string) => setTodo(value)}
/>
<RadioButtonGroup>
Expand All @@ -83,16 +93,20 @@ const AddTodoPopup = ({
selected={category === categoryItem.value}
onClick={() => handleCategoryChange(categoryItem.value)}
>
{categoryItem.label}
{categoryItem.label[language as LanguageKeys]}
</RadioButton>
))}
</RadioButtonGroup>
<SubTitle>
언제까지 할 일인가요?
<Calendar value={selectedDate} onChange={handleDateChange} />
{whenTodoMessage[language as keyof typeof whenTodoMessage]}
<Calendar
value={selectedDate}
onChange={handleDateChange}
placeholder={`${calendarPlaceHolder[language as keyof typeof calendarPlaceHolder]}`}
/>
</SubTitle>
<Button
text="등록하기"
text={`${submitMessage[language as keyof typeof submitMessage]}`}
onClick={handleButtonClick}
disabled={!isButtonEnabled}
/>
Expand All @@ -116,6 +130,7 @@ const RadioButtonGroup = styled.div`
display: flex;
margin: 12px 0px 24px 0px;
gap: 8px;
overflow-x: scroll;
`;

const RadioButton = styled.label<{ selected: boolean }>`
Expand All @@ -131,5 +146,6 @@ const RadioButton = styled.label<{ selected: boolean }>`
color: ${(props) =>
props.selected ? theme.colors.primary500 : theme.colors.b500};
cursor: pointer;
white-space: nowrap;
${(props) => props.theme.fonts.body3_m};
`;
12 changes: 10 additions & 2 deletions src/components/home/MealTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import MealTablePopup from "./MealTablePopup";
import More from "../common/More";
import Axios from "@/apis/axios";
import Image from "next/image";
import { cautionMessage, noDataMessage } from "@/data/mealData";

interface Food {
food: string;
Expand All @@ -18,6 +19,7 @@ interface Meal {
const MealTable = () => {
const [mealToday, setMealToday] = useState<Meal>({ foods: [] });
const [mealTable, setMealTable] = useState(false);
const [language, setLanguage] = useState<string>("ko");

const handleOpenMealTable = () => {
setMealTable(true);
Expand All @@ -27,6 +29,10 @@ const MealTable = () => {
setMealTable(false);
};

useEffect(() => {
setLanguage(localStorage.getItem("language") || "ko");
}, []);

useEffect(() => {
Axios.get(`/api/v1/menus/today`)
.then((response) => {
Expand All @@ -49,7 +55,7 @@ const MealTable = () => {
{data.food}
{data.warning && (
<Caution>
자녀가 주의해야 할 메뉴예요
{cautionMessage[language as keyof typeof cautionMessage]}
<Image
src="/assets/icons/ic_alert.svg"
width={16}
Expand All @@ -61,7 +67,9 @@ const MealTable = () => {
</List>
))
) : (
<NoData>급식 정보가 없어요 :(</NoData>
<NoData>
{noDataMessage[language as keyof typeof noDataMessage]}
</NoData>
)}
</TableContainer>
{mealTable && <MealTablePopup onClose={handleCloseMealTable} />}
Expand Down
24 changes: 19 additions & 5 deletions src/components/home/MealTablePopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import styled from "styled-components";
import Popup from "../common/Popup";
import { useEffect, useState } from "react";
import Axios from "@/apis/axios";
import { dayText, monthText, weekText } from "@/data/mealData";

interface MealTable {
date: string;
Expand All @@ -21,9 +22,15 @@ const MenuCard = ({
day = day[1];
}

const [language, setLanguage] = useState<string>("ko");

useEffect(() => {
setLanguage(localStorage.getItem("language") || "ko");
}, []);

return (
<Card>
<DateBox>{day}</DateBox>
<DateBox>{dayText(day, language)}</DateBox>
<Menus>
{foods.map((item, index) => (
<MenuItem key={index} $warning={item.warning}>
Expand All @@ -41,6 +48,11 @@ const MealTablePopup = ({ onClose }: { onClose: () => void }) => {
/* 주간별 급식 데이터 */
const [weeklyMealTable, setWeeklyMealTable] = useState<MealTable[][]>([]);
const [month, setMonth] = useState<string>("");
const [language, setLanguage] = useState<string>("ko");

useEffect(() => {
setLanguage(localStorage.getItem("language") || "ko");
}, []);

useEffect(() => {
Axios.get(`/api/v1/menus/month`)
Expand Down Expand Up @@ -92,13 +104,15 @@ const MealTablePopup = ({ onClose }: { onClose: () => void }) => {
}, []);

return (
<Popup onClose={onClose} title={`${month}월 급식표`} height="716px">
<Popup
onClose={onClose}
title={`${monthText(month, language)}`}
height="716px"
>
<StyledTable>
{weeklyMealTable.map((week, weekIndex) => (
<>
<Title>
{month}{weekIndex + 1}주차
</Title>
<Title>{weekText(month, weekIndex + 1, language)}</Title>
<Week key={weekIndex}>
{week.map((data, index) => (
<MenuCard key={index} date={data.date} foods={data.foods} />
Expand Down
2 changes: 1 addition & 1 deletion src/components/home/Notification.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const NotiContainer = styled.div`
${(props) => props.theme.fonts.body2_b};
color: ${theme.colors.b700};
letter-spacing: -0.28px;
z-index: -10;
z-index: 100;
`;

const Title = styled.div`
Expand Down
11 changes: 10 additions & 1 deletion src/components/home/TimeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import styled from "styled-components";
import Card, { CardProps } from "../common/Card";
import Axios from "@/apis/axios";
import { useEffect, useState } from "react";
import { noDataMessage } from "@/data/timeTableData";

interface Timetable {
time: number;
Expand All @@ -14,6 +15,12 @@ const TimeTable = () => {
let now = new Date();
const week = ["일", "월", "화", "수", "목", "금", "토"];

const [language, setLanguage] = useState<string>("ko");

useEffect(() => {
setLanguage(localStorage.getItem("language") || "ko");
}, []);

useEffect(() => {
Axios.get(`/api/v1/timetables/today`)
.then((response) => {
Expand All @@ -38,7 +45,9 @@ const TimeTable = () => {
/>
))
) : (
<NoData>시간표 정보가 없어요 :(</NoData>
<NoData>
{noDataMessage[language as keyof typeof noDataMessage]}
</NoData>
)}
</TableContainer>
</TimeContainer>
Expand Down
52 changes: 34 additions & 18 deletions src/components/home/Todo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,20 @@ import { theme } from "@/styles/theme";
import Image from "next/image";
import ListBox from "../common/ListBox";
import { useEffect, useRef, useState } from "react";
import AddTodoPopup, { categories } from "./AddTodoPopup";
import AddTodoPopup from "./AddTodoPopup";
import Toast from "../common/Toast";
import Axios from "@/apis/axios";
import { setAudio } from "@/redux/slices/audioSlice";
import { useDispatch } from "react-redux";
import { RootState } from "@/redux/store";
import { useSelector } from "react-redux";
import { getSpeech } from "@/utils/getSpeech";
import {
addTodoMessage,
categories,
dayOfWeekText,
LanguageKeys,
noTodoMessage,
} from "@/data/todoData";
import { addTodoToast } from "@/data/toastMessagesData";

interface Todo {
todoId: number;
Expand All @@ -29,12 +35,17 @@ const Todo = () => {
/* useEffect에서 의존성 배열로 넘기는, 렌더링 알림 역할 */
const [render, setRenderData] = useState(false);
const week = ["일", "월", "화", "수", "목", "금", "토"];
const [language, setLanguage] = useState<string>("ko");

/* 날짜를 yyyy-mm-dd 형식으로 변환하는 함수 */
const formatDate = (date: Date) => {
return date.toISOString().split("T")[0];
};

useEffect(() => {
setLanguage(localStorage.getItem("language") || "ko");
}, []);

useEffect(() => {
let formattedDate = formatDate(currentDate);
Axios.get(`/api/v1/todos?date=${formattedDate}`)
Expand Down Expand Up @@ -142,8 +153,9 @@ const Todo = () => {
const text =
date +
`. ${getDateString(currentDate)} ${getDateString(currentDate) === "오늘" ? "해야할" : "했어야 할"} 일은. ` +
unassignedTodos +
"입니다.";
(unassignedTodos.length > 0
? `${unassignedTodos.join(" ")} 입니다.`
: "없습니다.");

getSpeech(text, () => {
dispatch(setAudio(false));
Expand Down Expand Up @@ -210,14 +222,16 @@ const Todo = () => {
}}
/>
</DateLine>
<Image
src="/assets/icons/ic_volumn.svg"
alt="sound"
width={21}
height={21}
onClick={handleVoiceConversion}
style={{ cursor: "pointer" }}
/>
{language === "ko" && (
<Image
src="/assets/icons/ic_volumn.svg"
alt="sound"
width={21}
height={21}
onClick={handleVoiceConversion}
style={{ cursor: "pointer" }}
/>
)}
</Row>
<TodoLists>
{todoData && todoData.length > 0 ? (
Expand All @@ -230,19 +244,21 @@ const Todo = () => {
type={
categories.find(
(category) => category.value === data.todoType
)?.label || data.todoType
)?.label[language as LanguageKeys] || data.todoType
}
onClick={() => {
changeTodo(data.todoId);
}}
text={data.description}
time={`${getDayOfWeek(data.deadline)}까지`}
time={`${dayOfWeekText(getDayOfWeek(data.deadline))[language as keyof typeof dayOfWeekText]}`}
checked={data.status === "COMPLETE"}
onDelete={() => deleteTodo(data.todoId)}
/>
))
) : (
<NoData>할 일이 없어요!</NoData>
<NoData>
{noTodoMessage[language as keyof typeof noTodoMessage]}
</NoData>
)}
</TodoLists>
<Plus>
Expand All @@ -253,7 +269,7 @@ const Todo = () => {
width={20}
height={20}
/>
할 일 직접 추가하기
{addTodoMessage[language as keyof typeof addTodoMessage]}
</PlusButton>
</Plus>
{addTodo && (
Expand All @@ -266,7 +282,7 @@ const Todo = () => {
)}
{showToast && (
<Toast
message="할 일이 추가되었어요!"
message={`${addTodoToast[language as keyof typeof addTodoToast]}`}
type="basic"
duration={2000}
onClose={() => setShowToast(false)}
Expand Down
Loading

0 comments on commit ffe5437

Please sign in to comment.