diff --git a/BE/error/Dockerfile b/BE/error/Dockerfile index dc25ddf9..9ccd2edf 100644 --- a/BE/error/Dockerfile +++ b/BE/error/Dockerfile @@ -1,4 +1,5 @@ -FROM openjdk:17-oracle +#FROM openjdk:17-oracle +FROM --platform=linux/amd64 openjdk:17-oracle RUN mkdir -p /logs ENV PROFILE defaultgi @@ -11,4 +12,4 @@ ENV DD_VERSION=${RELEASE_VERSION} ARG JAR_FILE="./build/libs/*.jar" COPY ${JAR_FILE} app.jar -ENTRYPOINT ["java", "-jar", "/app.jar"] +ENTRYPOINT ["java", "-jar", "/app.jar"] \ No newline at end of file diff --git a/BE/error/src/main/java/com/example/demo/config/SwaggerConfig.java b/BE/error/src/main/java/com/example/demo/config/SwaggerConfig.java new file mode 100644 index 00000000..3101329c --- /dev/null +++ b/BE/error/src/main/java/com/example/demo/config/SwaggerConfig.java @@ -0,0 +1,21 @@ +package com.example.demo.config; + + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI openAPI() { + return new OpenAPI().components(new Components()).info(apiInfo()); + } + + private Info apiInfo() { + return new Info().title("ERROR API").description("ERROR Swagger").version("2.0.0"); + } +} \ No newline at end of file diff --git a/FE/error/public/image80.png b/FE/error/public/image80.png new file mode 100644 index 00000000..a14c83cf Binary files /dev/null and b/FE/error/public/image80.png differ diff --git a/FE/error/src/components/EconoCalendar.jsx b/FE/error/src/components/EconoCalendar.jsx index 8e52858e..01c14271 100644 --- a/FE/error/src/components/EconoCalendar.jsx +++ b/FE/error/src/components/EconoCalendar.jsx @@ -1,48 +1,23 @@ -import { useEffect, useState } from "react"; +import { useState } from "react"; import toast, { Toaster } from "react-hot-toast"; import FullCalendar from "@fullcalendar/react"; import dayGridPlugin from "@fullcalendar/daygrid"; import styled from "styled-components"; import interactionPlugin from "@fullcalendar/interaction"; -import axios from "axios"; import CreateModal from "./scheduleCreate/CreateModal"; import CheckCalendar from "./scheduleCheck/CheckCalendar"; -const EconoCalendar = ({ isLoggedIn, setIsLoggedIn }) => { - const [events, setEvents] = useState([]); +const EconoCalendar = ({ + isLoggedIn, + setIsLoggedIn, + setEvents, + events, + setToken, +}) => { const [selectID, setSelectID] = useState(""); const [checkModalIsOpen, setCheckModalIsOpen] = useState(false); const [createModalIsOpen, setCreateModalIsOpen] = useState(false); const [selectedDate, setSelectedDate] = useState(""); - const [token, setToken] = useState(null); - - useEffect(() => { - const storedToken = localStorage.getItem("slackToken"); - setToken(storedToken); - - const isUserLoggedIn = !!storedToken; - setIsLoggedIn(isUserLoggedIn); - - const uri = isUserLoggedIn - ? "/api/calendar/all" - : "/api/calendar/all/public"; - - axios - .get(uri, { headers: { Authorization: `Bearer ${storedToken}` } }) - .then((res) => { - const fetchedEvents = res.data.data.map((event) => ({ - title: event.eventName, - id: event.eventId, - start: event.eventStartDate.split("T")[0], - end: event.eventEndDate.split("T")[0], - color: "#FFC0CB", - })); - setEvents(fetchedEvents); - }) - .catch((error) => { - console.error("Error fetching events:", error); - }); - }, []); const handleDelete = () => { toast("일정이 삭제되었습니다", { @@ -86,6 +61,7 @@ const EconoCalendar = ({ isLoggedIn, setIsLoggedIn }) => { localStorage.removeItem("slackToken"); setIsLoggedIn(false); setToken(null); + window.location.reload(); // } else { // const newToken = "dummyToken" + Math.random().toString(36).substr(2, 9); // 임의의 토큰 생성 // localStorage.setItem("slackToken", newToken); @@ -93,6 +69,7 @@ const EconoCalendar = ({ isLoggedIn, setIsLoggedIn }) => { // setIsLoggedIn(true); // } //TODO: 추후 아래 코드로 변경 + //} } else { window.location.href = "/login"; } diff --git a/FE/error/src/components/SideBar/individualFilter/IndividualFilter.jsx b/FE/error/src/components/SideBar/individualFilter/IndividualFilter.jsx index c31c60b8..c32be69d 100644 --- a/FE/error/src/components/SideBar/individualFilter/IndividualFilter.jsx +++ b/FE/error/src/components/SideBar/individualFilter/IndividualFilter.jsx @@ -10,6 +10,7 @@ const IndividualFilter = ({ filterLists, addNewFilter, updateDeleteFilter, + onFilterChange, }) => { const [individualFilterIsOpen, setindividualFilterIsOpen] = useState(false); const [filterListsIsOpen, setFilterListsIsOpen] = useState(true); @@ -69,6 +70,7 @@ const IndividualFilter = ({ )} diff --git a/FE/error/src/components/SideBar/publicFilter/PublicFilter.jsx b/FE/error/src/components/SideBar/publicFilter/PublicFilter.jsx index cc8797b3..0c1a20a1 100644 --- a/FE/error/src/components/SideBar/publicFilter/PublicFilter.jsx +++ b/FE/error/src/components/SideBar/publicFilter/PublicFilter.jsx @@ -13,11 +13,11 @@ const PublicFilter = () => {
에코노 캘린더
- + 공식행사 - + 주간발표 diff --git a/FE/error/src/components/scheduleCheck/CheckCalendar.jsx b/FE/error/src/components/scheduleCheck/CheckCalendar.jsx index 2424f0b8..0610dac0 100644 --- a/FE/error/src/components/scheduleCheck/CheckCalendar.jsx +++ b/FE/error/src/components/scheduleCheck/CheckCalendar.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState, useRef } from "react"; +import { useEffect, useState } from "react"; import { GoPencil } from "react-icons/go"; import { IoClose } from "react-icons/io5"; import { MdOutlineLocationOn } from "react-icons/md"; @@ -36,29 +36,27 @@ const CheckCalendar = ({ setEvent(specificEvent); } - const isMount = useRef(false); useEffect(() => { - if (!isMount.current) { - isMount.current = true; - return; - } + if (isOpen && selectID) { + setEvent({}); // 새로운 데이터 로딩 전에 event 상태 초기화 - axios - .get("/api/calendar/" + selectID, { - headers: { Authorization: `Bearer ${storedToken}` }, - }) - .then((res) => { - createDate( - res.data.data.eventName, - res.data.data.eventStartDate, - res.data.data.eventEndDate, - res.data.data.eventPlace, - res.data.data.eventInfo, - res.data.data.eventType, - res.data.data.filterColor - ); - }); - }, [selectID]); + axios + .get("/api/calendar/" + selectID, { + headers: { Authorization: `Bearer ${storedToken}` }, + }) + .then((res) => { + createDate( + res.data.data.eventName, + res.data.data.eventStartDate, + res.data.data.eventEndDate, + res.data.data.eventPlace, + res.data.data.eventInfo, + res.data.data.eventType, + res.data.data.filterColor + ); + }); + } + }, [selectID, isOpen, storedToken]); function date(startDate, endDate) { if (!startDate && !endDate) return "날짜 정보 없음"; @@ -75,15 +73,20 @@ const CheckCalendar = ({ } ${endDate.split("T")[1]}`; } + const handleRequestClose = () => { + setEvent({}); + onRequestClose(); + }; + return ( - @@ -97,7 +100,7 @@ const CheckCalendar = ({ events={events} selectID={selectID} handleDelete={handleDelete} - onRequestClose={onRequestClose} + onRequestClose={handleRequestClose} handleUpdateDeleteData={handleUpdateDeleteData} /> diff --git a/FE/error/src/components/scheduleCreate/CreateModal.jsx b/FE/error/src/components/scheduleCreate/CreateModal.jsx index cfa40859..e0b306ad 100644 --- a/FE/error/src/components/scheduleCreate/CreateModal.jsx +++ b/FE/error/src/components/scheduleCreate/CreateModal.jsx @@ -1,5 +1,5 @@ import { useState, useEffect } from "react"; -import { format, addDays, compareAsc, parseISO } from "date-fns"; +import { format, addDays } from "date-fns"; import axios from "axios"; import Modal from "react-modal"; import styled from "styled-components"; @@ -66,7 +66,7 @@ const CreateModal = ({ }; const isFilterSelected = () => { - return selectedFilter && selectedFilter.category && selectedFilter.filter; + return selectedFilter && selectedFilter.category && selectedFilter.filterId; }; const handleTitleChange = (event) => { @@ -128,13 +128,13 @@ const CreateModal = ({ }; const handleFilterSelect = (category, filter) => { - setSelectedFilter({ category, filter }); + setSelectedFilter({ category, ...filter }); setActiveDropdown(null); }; const getButtonContent = (category) => { if (selectedFilter && selectedFilter.category === category) { - return selectedFilter.filter; + return selectedFilter.filterName; } switch (category) { case "public": @@ -170,18 +170,16 @@ const CreateModal = ({ eventEndDate: eventEndDate, eventPlace: eventPlace, eventInfo: eventMemo, - scheduleType: selectedFilter.category, - filterName: selectedFilter.filter, + scheduleType: selectedFilter.category.toUpperCase(), + filter: { + filterId: selectedFilter.filterId, + }, }; axios - .post( - "/api/calendar", - { - headers: { Authorization: `Bearer ${storedToken}` }, - }, - data - ) + .post("/api/calendar", data, { + headers: { Authorization: `Bearer ${storedToken}` }, + }) .then((res) => { createDate( eventName, @@ -190,6 +188,7 @@ const CreateModal = ({ eventEndDate ); onRequestClose(); + window.location.reload(); }); }; @@ -227,12 +226,22 @@ const CreateModal = ({ {category === "public" && ( <> handleFilterSelect(category, "공식행사")} + onClick={() => + handleFilterSelect(category, { + filterId: "public1", + filterName: "공식행사", + }) + } > 공식행사 handleFilterSelect(category, "주간발표")} + onClick={() => + handleFilterSelect(category, { + filterId: "public2", + filterName: "주간발표", + }) + } > 주간발표 @@ -242,13 +251,21 @@ const CreateModal = ({ <> - handleFilterSelect(category, "28기 신입모집 TF") + handleFilterSelect(category, { + filterId: "group1", + filterName: "28기 신입모집 TF", + }) } > 28기 신입모집 TF handleFilterSelect(category, "행사부")} + onClick={() => + handleFilterSelect(category, { + filterId: "group2", + filterName: "행사부", + }) + } > 행사부 @@ -258,9 +275,7 @@ const CreateModal = ({ privateFilters.map((filter) => ( - handleFilterSelect(category, filter.filterName) - } + onClick={() => handleFilterSelect(category, filter)} > {filter.filterName} @@ -355,6 +370,9 @@ const SaveButton = styled.button` &:disabled { cursor: default; } + &:hover { + background-color: #f5f5f5; + } `; const EditorBox = styled.div` diff --git a/FE/error/src/pages/LoginPage.jsx b/FE/error/src/pages/LoginPage.jsx index e9e0cf0b..3c8cf821 100644 --- a/FE/error/src/pages/LoginPage.jsx +++ b/FE/error/src/pages/LoginPage.jsx @@ -49,7 +49,11 @@ const LoginPage = () => { }; if (isLoading) { - return
로그인 중...
; + return ( + + + + ); } return ( @@ -128,3 +132,20 @@ const StyledCharacter = styled.img` top: 25%; left: 60%; `; + +const LoadingContainer = styled.div` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + background-color: rgba(255, 255, 255, 0.8); +`; + +const LoadingImage = styled.img` + width: 100px; + height: auto; +`; diff --git a/FE/error/src/pages/MainPage.jsx b/FE/error/src/pages/MainPage.jsx index 5fa8b0d3..b25bee61 100644 --- a/FE/error/src/pages/MainPage.jsx +++ b/FE/error/src/pages/MainPage.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, useMemo } from "react"; import styled from "styled-components"; import EconoCalendar from "../components/EconoCalendar"; import ProfileBar from "../components/SideBar/ProfileBar"; @@ -11,6 +11,59 @@ const MainPage = () => { const [filterIndividualLists, setFilterIndividualLists] = useState([]); const [filterGroupLists, setFilterGroupLists] = useState([]); const [isLoggedIn, setIsLoggedIn] = useState(false); + const [events, setEvents] = useState([]); + const [activeFilters, setActiveFilters] = useState(new Set()); + const [token, setToken] = useState(null); + + // 필터링된 이벤트를 계산 + const filteredEvents = useMemo(() => { + if (activeFilters.size === 0) return events; + return events.filter((event) => activeFilters.has(event.filterId)); + }, [events, activeFilters]); + + useEffect(() => { + const storedToken = localStorage.getItem("slackToken"); + setToken(storedToken); + + const isUserLoggedIn = !!storedToken; + setIsLoggedIn(isUserLoggedIn); + + const uri = isUserLoggedIn + ? "/api/calendar/all/private" + : "/api/calendar/all/public"; + + axios + .get(uri, { headers: { Authorization: `Bearer ${storedToken}` } }) + .then((res) => { + const fetchedEvents = res.data.data.map((event) => ({ + title: event.eventName, + id: event.eventId, + start: event.eventStartDate.split("T")[0], + end: event.eventEndDate.split("T")[0], + color: event.filterColor, + filterId: event.filterId, + })); + setEvents(fetchedEvents); + // 모든 필터를 초기에 활성화 + setActiveFilters(new Set(fetchedEvents.map((event) => event.filterId))); + }) + .catch((error) => { + console.error("Error fetching events:", error); + }); + }, []); + + const handleFilterChange = (filterId, isChecked) => { + setActiveFilters((prevFilters) => { + const newFilters = new Set(prevFilters); + if (isChecked) { + newFilters.add(filterId); + } else { + newFilters.delete(filterId); + } + return newFilters; + }); + }; + useEffect(() => { const token = localStorage.getItem("slackToken"); setIsLoggedIn(!!token); @@ -23,29 +76,39 @@ const MainPage = () => { const addNewGroupFilter = (newGroupFilter) => { setFilterGroupLists([...filterGroupLists, newGroupFilter]); }; + const updateDeleteFilter = (newFilter) => { setFilterIndividualLists( filterIndividualLists.filter((filter) => filter.filterId !== newFilter) ); + // 삭제된 필터를 activeFilters에서도 제거 + setActiveFilters((prevFilters) => { + const newFilters = new Set(prevFilters); + newFilters.delete(newFilter); + return newFilters; + }); }; - const storedToken = localStorage.getItem("slackToken"); useEffect(() => { + const storedToken = localStorage.getItem("slackToken"); axios .get("/api/filter", { headers: { Authorization: `Bearer ${storedToken}` }, }) .then((res) => { - console.log(res); const fetchedFilter = res.data.data.map((filter) => ({ filterId: filter.filterId, filterName: filter.filterName, filterColor: filter.filterColor, })); setFilterIndividualLists(fetchedFilter); + // 모든 개인 필터를 초기에 활성화 + setActiveFilters( + new Set(fetchedFilter.map((filter) => filter.filterId)) + ); }) .catch((err) => { - console.log("Error fetching events:", err); + console.log("Error fetching filters:", err); }); }, []); @@ -58,7 +121,10 @@ const MainPage = () => { - + {isLoggedIn && ( <> { )} - + ); @@ -82,6 +156,8 @@ const MainPage = () => { export default MainPage; +// ... 나머지 styled-components 코드는 그대로 유지 + const SideBar = styled.div` width: 15.625rem; height: 98.1vh; @@ -97,7 +173,7 @@ const CalendarPage = styled.div` const LineBox = styled.div` width: 100%; - height: 1.5rem; + height: 1.25rem; border: 1px solid #ddd; border-right: none; margin-top: 0.65rem; diff --git a/FE/error/src/pages/ProfilePage.jsx b/FE/error/src/pages/ProfilePage.jsx index d6b6d803..bf9bd618 100644 --- a/FE/error/src/pages/ProfilePage.jsx +++ b/FE/error/src/pages/ProfilePage.jsx @@ -1,7 +1,7 @@ import { useState, useEffect } from "react"; -import styled from "styled-components"; import { FaRandom } from "react-icons/fa"; import { useNavigate } from "react-router-dom"; +import * as S from "../styles/ProfilePage.js"; const ProfilePage = () => { const [selectedImage, setSelectedImage] = useState(null); @@ -40,14 +40,14 @@ const ProfilePage = () => { if (selectedImage !== null) { localStorage.setItem("profileImage", images[selectedImage]); } - navigate("/"); // MainPage로 이동 + navigate("/"); }; return ( <> -
- 프로필 선택 - + 프로필 선택 + { } alt="Profile" /> -
- - + + + - 랜덤 이미지 생성 - - + 랜덤 이미지 생성 + + {images.map((image, index) => ( - selectImage(index)} selected={selectedImage === index} > - {`option-${index}`} - + + ))} - - - navigate("/")}>취소 - 저장 - - + + + navigate("/")}>취소 + 저장 + + ); }; export default ProfilePage; - -const Container = styled.div` - display: flex; - flex-direction: column; - align-items: center; - padding: 0 4rem; -`; - -const Header = styled.div` - display: flex; - width: 52%; - padding: 2rem 4rem 0 4rem; - justify-content: space-between; -`; - -const Title = styled.h1` - font-size: 2rem; - margin-right: 2rem; /* Space between title and profile picture */ -`; - -const ProfilePicture = styled.img` - display: flex; - justify-content: center; - width: 13rem; - height: 13rem; - border-radius: 50%; - margin-bottom: 1rem; -`; - -const RandomButton = styled.div` - padding: 0 0.5rem; - cursor: pointer; - align-self: flex-start; -`; - -const ImageGrid = styled.div` - display: grid; - grid-template-columns: repeat(8, 1fr); - gap: 0.5rem; - margin-bottom: 1rem; -`; - -const ImageContainer = styled.div` - width: 9.8rem; - height: 9.8rem; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; -`; - -const Image = styled.img` - max-width: 100%; - max-height: 100%; -`; - -const SaveButton = styled.button` - padding: 0.5rem 4rem; - align-self: flex-end; - background-color: white; - border: 1px solid #cbcbcb; - border-radius: 4px; -`; - -const ImageShuffle = styled.div` - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 1rem; - align-self: flex-start; -`; - -const ButtonContainer = styled.div` - display: flex; - align-self: flex-end; - gap: 0.8rem; - margin-top: 0.5rem; -`; - -const CancleButton = styled.button` - padding: 0.5rem 4rem; - background-color: white; - border: 1px solid #cbcbcb; - border-radius: 4px; -`; diff --git a/FE/error/src/styles/ProfilePage.js b/FE/error/src/styles/ProfilePage.js new file mode 100644 index 00000000..13125d9a --- /dev/null +++ b/FE/error/src/styles/ProfilePage.js @@ -0,0 +1,86 @@ +import styled from "styled-components"; + +export const Container = styled.div` + display: flex; + flex-direction: column; + align-items: center; + padding: 0 4rem; +`; + +export const HeaderContainer = styled.div` + display: flex; + width: 52%; + padding: 2rem 4rem 0 4rem; + justify-content: space-between; +`; + +export const TitleBox = styled.h1` + font-size: 2rem; + margin-right: 2rem; +`; + +export const ProfilePicture = styled.img` + display: flex; + justify-content: center; + width: 13rem; + height: 13rem; + border-radius: 50%; + margin-bottom: 1rem; +`; + +export const RandomButton = styled.div` + padding: 0 0.5rem; + cursor: pointer; + align-self: flex-start; +`; + +export const ImageGridItem = styled.div` + display: grid; + grid-template-columns: repeat(8, 1fr); + gap: 0.5rem; + margin-bottom: 1rem; +`; + +export const ImageContainer = styled.div` + width: 9.8rem; + height: 9.8rem; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; +`; + +export const Image = styled.img` + max-width: 100%; + max-height: 100%; +`; + +export const SaveButton = styled.button` + padding: 0.5rem 4rem; + align-self: flex-end; + background-color: white; + border: 1px solid #cbcbcb; + border-radius: 4px; +`; + +export const ImageShuffle = styled.div` + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 1rem; + align-self: flex-start; +`; + +export const ButtonContainer = styled.div` + display: flex; + align-self: flex-end; + gap: 0.8rem; + margin-top: 0.5rem; +`; + +export const CancleButton = styled.button` + padding: 0.5rem 4rem; + background-color: white; + border: 1px solid #cbcbcb; + border-radius: 4px; +`; diff --git a/FE/error/src/utils/TimeSelect.jsx b/FE/error/src/utils/TimeSelect.jsx index 19199495..e9fd49dd 100644 --- a/FE/error/src/utils/TimeSelect.jsx +++ b/FE/error/src/utils/TimeSelect.jsx @@ -1,8 +1,7 @@ -import { useState } from "react"; import Select from "react-select"; let hour = []; -for (let i = 0; i < 24; i++) { +for (let i = 0; i < 48; i++) { let op = {}; let hourPart = i / 2; let minutePart = i % 2 === 0 ? "00" : "30"; diff --git a/FE/error/src/utils/filterUtils/FilterColorSelect.jsx b/FE/error/src/utils/filterUtils/FilterColorSelect.jsx index 3f2a3ed4..0aadcae2 100644 --- a/FE/error/src/utils/filterUtils/FilterColorSelect.jsx +++ b/FE/error/src/utils/filterUtils/FilterColorSelect.jsx @@ -12,11 +12,11 @@ const FilterColorSelect = ({ setFilterColor }) => { "#CBAACB", "#FED7C3", "#789BDE", - "#55CBCD", - "#FFC0CB", + "#DEAC80", + "#D6EFD8", "#FF968A", - "#7367F0", - "#FFC8A2", + "#D4BDAC", + "#ffd4b5", "#AAEF98", ]; diff --git a/FE/error/src/utils/filterUtils/FilterList.jsx b/FE/error/src/utils/filterUtils/FilterList.jsx index 33b72f4a..c17782a7 100644 --- a/FE/error/src/utils/filterUtils/FilterList.jsx +++ b/FE/error/src/utils/filterUtils/FilterList.jsx @@ -3,13 +3,18 @@ import ScheduleToggle from "./ScheduleToggle"; import FilterModify from "./FilterModify"; import FilterDelete from "./FilterDelete"; -const FilterList = ({ filterLists, updateDeleteFilter }) => { +const FilterList = ({ filterLists, updateDeleteFilter, onFilterChange }) => { return ( {filterLists.map((filterList, index) => ( - + {filterList.filterName} diff --git a/FE/error/src/utils/filterUtils/FilterModify.jsx b/FE/error/src/utils/filterUtils/FilterModify.jsx index df6a961b..17c7d50b 100644 --- a/FE/error/src/utils/filterUtils/FilterModify.jsx +++ b/FE/error/src/utils/filterUtils/FilterModify.jsx @@ -28,8 +28,8 @@ const FilterModify = ({ filterName, filterID }) => { filterColor: filterColor, }; axios - .post( - "/api/calendar/filter/" + filterID, + .put( + "/api/filter/" + filterID, { headers: { Authorization: `Bearer ${storedToken}` }, }, diff --git a/FE/error/src/utils/filterUtils/ScheduleToggle.jsx b/FE/error/src/utils/filterUtils/ScheduleToggle.jsx index fe7127cd..4c31c270 100644 --- a/FE/error/src/utils/filterUtils/ScheduleToggle.jsx +++ b/FE/error/src/utils/filterUtils/ScheduleToggle.jsx @@ -1,11 +1,13 @@ import { useState } from "react"; import styled from "styled-components"; -const ScheduleToggle = ({ color }) => { +const ScheduleToggle = ({ color, id, onToggle }) => { const [clicked, setClicked] = useState(true); - const handleOnClick = () => { - setClicked(!clicked); + const newClickedState = !clicked; + setClicked(newClickedState); + + onToggle(id, newClickedState); }; return ( @@ -27,12 +29,10 @@ const StyledClickedBox = styled.input` width: 1.15rem; height: 1.15rem; border: 1.5px solid ${(props) => props.color}; - opacity: 0.7; border-radius: 0.2rem; &:checked { background-image: url("data:image/svg+xml,%3Csvg viewBox='-2 -2 25 25' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M18 7.2C18 7.2 8.55 16.65 8.1 17.1C7.65 17.55 3.15 12.15 2.7 11.7C2.25 11.25 4.5 9.9 4.5 9.9L8.1 13.5L16.2 5.4C16.2 5.4 17.55 6.3 18 7.2Z' fill='white' stroke='white' stroke-width='0.63' stroke-linejoin='round' stroke-linecap='round'/%3E%3C/svg%3E"); background-color: ${(props) => props.color}; - opacity: 0.7; } margin-right: 0.5rem; `;