Skip to content

Commit

Permalink
Merge pull request #78 from 9oormthonUniv-seoultech/develop
Browse files Browse the repository at this point in the history
4차배포: 신규 API 연결 및 컴포넌트 스타일 수정하여 배포
  • Loading branch information
ej070961 authored Nov 8, 2024
2 parents 5e3f7de + 7f6ca65 commit 906d718
Show file tree
Hide file tree
Showing 13 changed files with 225 additions and 110 deletions.
1 change: 1 addition & 0 deletions src/@types/review.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type Review = {
features: string[];
imageUrl: string;
imageCount: number;
profileUrl: string | null;
};

export type MyReview = {
Expand Down
28 changes: 27 additions & 1 deletion src/api/my.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Get, Post } from ".";
import { Delete, Get, Post } from ".";
import { MyLikedBooth } from "../@types/my";
import { MyReview } from "../@types/review";

Expand Down Expand Up @@ -56,6 +56,32 @@ export const postboothLike = async (accessToken: string, boothId: string) => {
} catch (error) {}
};

export const deleteboothLike = async (accessToken: string, boothId: string) => {
try {
const res = await Delete(`/api/v1/photobooth/like/${boothId}`, {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});
return res.data.payload;
} catch (error) {}
};

export const checkBoothLike = async (accessToken: string, boothId: string) => {
try {
const res = await Get<boolean>(
`/api/v1/photobooth/like/check/${boothId}`,

{
headers: {
Authorization: `Bearer ${accessToken}`,
},
}
);
return res.data.payload;
} catch (error) {}
};

export const getPhotoLikes = async (accessToken: string) => {
try {
const res = await Get<{ albumId: number; photoUrl: string; like: boolean }[]>("/api/v1/album/favorite", {
Expand Down
24 changes: 12 additions & 12 deletions src/components/Album/BoothFilterModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import styled from "styled-components";
import CloseIcon from "../../assets/icons/close-icon";
import OptionButton from "../Common/OptionButton.tsx";
import NextButton from "../Common/NextButton.tsx";
import {BoothCategories} from "../../data/booth-categories.ts";
import { BoothCategories } from "../../data/booth-categories.ts";

type BoothFilterProps = {
photoBooth: string;
Expand All @@ -13,8 +13,8 @@ type BoothFilterProps = {
};

export default function BoothFilterModal({ photoBooth, setPhotoBooth, setIsBoothFilterModalOpen }: BoothFilterProps) {
const photoBoothOptions = BoothCategories.map((item) => (item.label));
const photoBoothOptions = BoothCategories.map((item) => item.label);

return (
<Overlay>
<Container>
Expand All @@ -27,28 +27,28 @@ export default function BoothFilterModal({ photoBooth, setPhotoBooth, setIsBooth
</div>
<hr className="h-[1.5px] w-full bg-gray200 " />
</header>

<OptionContainer>
{photoBoothOptions.map((booth) => (
<OptionButton
key={booth}
onClick={() => setPhotoBooth(booth)}
isActive={photoBooth === booth}
label={booth}
size={"small"}
// size={"small"}
/>
))}
</OptionContainer>
<div className="mt-4">
<NextButton text={"확인"} onClick={() => setIsBoothFilterModalOpen(false)}/>
<NextButton text={"확인"} onClick={() => setIsBoothFilterModalOpen(false)} />
</div>
</Container>
</Overlay>
);
}

const Overlay = styled.div`
${tw`
${tw`
w-full h-full bg-[black] bg-opacity-40
fixed top-[50%] left-[50%] transform translate-x-[-50%] translate-y-[-50%]
flex justify-center items-center
Expand All @@ -57,14 +57,14 @@ const Overlay = styled.div`
`;

const Container = styled.div`
${tw`bg-background flex flex-col items-center min-h-screen w-full max-w-[480px] m-auto`}
overflow-x: hidden;
${tw`bg-background flex flex-col items-center min-h-screen w-full max-w-[480px] m-auto`}
overflow-x: hidden;
`;

const OptionContainer = styled.div`
${tw`grid grid-cols-2 gap-4`}
${tw`grid grid-cols-2 gap-4`}
`;

const CloseButton = styled.button`
${tw`absolute right-[10px]`}
`;
${tw`absolute right-[10px]`}
`;
72 changes: 58 additions & 14 deletions src/components/Album/DateModal.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,81 @@
import styled from "styled-components";
import tw from "twin.macro";
import X from "../../assets/images/X.svg?react";
import { useState } from "react";
import { useEffect, useState } from "react";

type ModalProps = {
closeModal: () => void;
year:number;
month:number;
year: number;
month: number;
setYear: React.Dispatch<React.SetStateAction<number>>;
setMonth: React.Dispatch<React.SetStateAction<number>>;
}
};

export default function DateModal({ closeModal, year, month, setYear, setMonth }: ModalProps) {
const [tempYear, setTempYear] = useState<number>(year);
const [tempMonth, setTempMonth] = useState<number>(month);

const [keyboardHeight, setKeyboardHeight] = useState(0);

const confirm = () => {
setYear(tempYear);
setMonth(tempMonth);
closeModal();
};

useEffect(() => {
// 키보드가 열릴 때 visualViewport 이벤트 리스너 추가
const handleResize = () => {
const viewportHeight = window.innerHeight;
const visualViewport = window.visualViewport;

if (visualViewport) {
const visualViewportHeight = visualViewport.height;

// 키보드가 나타날 때 높이를 계산하여 모달 위치 조정
if (visualViewportHeight < viewportHeight) {
setKeyboardHeight(viewportHeight - visualViewportHeight);
} else {
setKeyboardHeight(0);
}
}
};

// visualViewport가 존재할 경우에만 리스너 등록
if (window.visualViewport) {
window.visualViewport.addEventListener("resize", handleResize);
}

return () => {
// visualViewport가 존재할 경우에만 리스너 제거
if (window.visualViewport) {
window.visualViewport.removeEventListener("resize", handleResize);
}
};
}, []);

return (
<ModalOverlay>
<ModalContent>
<ModalContent style={{ transform: `translateY(-${keyboardHeight}px)` }}>
<Title>날짜 입력</Title>
<SubText>사진을 찍은 날짜를 선택해주세요!</SubText>
<CloseButton onClick={closeModal}>
<X />
</CloseButton>
<DateContainer>
<div className="h-[49px] p-[5px] bg-background rounded-lg flex items-center gap-[10px]">
<StyledInput placeholder="0000" value={tempYear} maxLength={4} onChange={(e) => setTempYear(Number(e.target.value))} />
<StyledInput
placeholder="0000"
value={tempYear}
maxLength={4}
onChange={(e) => setTempYear(Number(e.target.value))}
/>
<p className="text-gray400 font-bold"></p>
<StyledInput placeholder="00" value={tempMonth} maxLength={2} onChange={(e) => setTempMonth(Number(e.target.value))} />
<StyledInput
placeholder="00"
value={tempMonth}
maxLength={2}
onChange={(e) => setTempMonth(Number(e.target.value))}
/>
<p className="text-gray400 font-bold"></p>
</div>
</DateContainer>
Expand All @@ -50,28 +92,30 @@ const ModalOverlay = styled.div`

const ModalContent = styled.div`
${tw`w-[390px] h-auto relative bg-background rounded-tl-[26px] rounded-tr-[26px] p-8 flex flex-col items-center`}
position: fixed;
bottom: 0;
`;

const Title = styled.h2`
${tw`text-center text-[#171c24] text-[22px] font-semibold mb-2`}
${tw`text-center text-[#171c24] text-[22px] font-semibold mb-2`}
`;

const SubText = styled.p`
${tw`text-center text-[#676f7b] text-xs font-medium mb-2`}
${tw`text-center text-[#676f7b] text-xs font-medium mb-2`}
`;

const CloseButton = styled.button`
${tw`absolute top-4 right-4 w-[26px] h-[26px] bg-[#e9eaee] rounded-full`}
${tw`absolute top-4 right-4 w-[26px] h-[26px] bg-[#e9eaee] rounded-full`}
`;

const DateContainer = styled.div`
${tw`space-y-4 my-4 flex flex-col items-start`}
${tw`space-y-4 my-4 flex flex-col items-start`}
`;

const ConfirmButton = styled.button`
${tw`w-[225.81px] h-[50px] bg-[#5453ee] rounded-md text-[#FFFFFF] text-[22px] font-medium mt-3`}
${tw`w-[225.81px] h-[50px] bg-[#5453ee] rounded-md text-[#FFFFFF] text-[22px] font-medium mt-3`}
`;

const StyledInput = styled.input`
${tw`w-full h-full rounded-lg text-center text-gray400 bg-gray100`}
`;
`;
31 changes: 19 additions & 12 deletions src/components/Album/HashtagSearchModal.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, {useState} from "react";
import React, { useState } from "react";
import tw from "twin.macro";
import styled from "styled-components";
import CloseIcon from "../../assets/icons/close-icon";
import {Get} from "../../api";
import { Get } from "../../api";
import Search from "../../assets/images/search.svg?react";
import {useAuthStore} from "../../store/useAuthStore.ts";
import { useAuthStore } from "../../store/useAuthStore.ts";
import ImageCard from "./ImageCard.tsx";
import NoImage from "../../assets/images/no-images.svg?react";

Expand Down Expand Up @@ -66,9 +66,14 @@ export default function HashtagSearchModal({ setIsModalOpen }: BoothFilterProps)
</SearchIcon>
<input
className="w-full bg-gray100 pl-2 text-gray400"
placeholder="해시태그를 입력하고 왼쪽에 있는 돋보기 클릭!"
placeholder="해시태그를 검색해보세요!"
value={hashTag}
onChange={(e) => setHashTag(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter") {
handleSearchPhotos(hashTag, accessToken);
}
}}
/>
</InputContainer>

Expand All @@ -80,7 +85,9 @@ export default function HashtagSearchModal({ setIsModalOpen }: BoothFilterProps)
) : (
<>
<div className="flex-col justify-start items-start gap-[5px] inline-flex">
<div className="text-[#171d24] text-lg font-semibold font-['Pretendard']">{imageList.length}장의 추억</div>
<div className="text-[#171d24] text-lg font-semibold font-['Pretendard']">
{imageList.length}장의 추억
</div>
</div>
<ImageContainer>
<ImageDiv>
Expand Down Expand Up @@ -144,16 +151,16 @@ const Overlay = styled.div`
`;

const CloseButton = styled.button`
${tw`absolute right-[10px]`}
${tw`absolute right-[10px]`}
`;

const InputContainer = styled.div`
${tw`w-10/12 p-2.5 bg-[#e9eaee] rounded-lg flex justify-end items-center `}
&:focus {
outline: none;
}
${tw`w-10/12 p-2.5 bg-[#e9eaee] rounded-lg flex justify-end items-center `}
&:focus {
outline: none;
}
`;

const SearchIcon = styled.button`
${tw`w-6 p-px flex justify-center items-center`}
`;
${tw`w-6 p-px flex justify-center items-center`}
`;
28 changes: 22 additions & 6 deletions src/components/Booth/BoothInfoSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,41 @@ import { getDistance } from "../../hooks/getLocation";
import useBoothFilterStore from "../../store/useBoothFilterStore";
import { SpecificBoothInfo } from "../../@types/booth";
import { FaHeart } from "react-icons/fa";
import { useState } from "react";
import { postboothLike } from "../../api/my";
import { useEffect, useState } from "react";
import { checkBoothLike, deleteboothLike, postboothLike } from "../../api/my";
import { useParams } from "react-router-dom";
import { useAuthStore } from "../../store/useAuthStore";
import LikeFilledIcon from "../../assets/icons/like-filled-icon";
import LikeNotFilledIcon from "../../assets/icons/like-not-filled-icon";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
function BoothInfoSection({ name, road, x, y }: SpecificBoothInfo) {
const { lat, lng } = useBoothFilterStore();

const { boothId } = useParams() as { boothId: string };
const { accessToken } = useAuthStore();
const [like, setLike] = useState(false);

const [like, setLike] = useState<boolean>(false);
// 좋아요 여부 조회 api 호출
const { data } = useQuery({
queryKey: ["checkLike", boothId],
queryFn: () => checkBoothLike(accessToken!, boothId).then((res) => setLike(res!)),
});

// 좋아요 버튼 클릭 핸들러
const handleLike = async () => {
const res = await postboothLike(accessToken!, boothId);
if (res === "success") {
setLike(!like);
if (like) {
const res = await deleteboothLike(accessToken!, boothId);
if (res) {
setLike(false);
}
} else {
const res = await postboothLike(accessToken!, boothId);
if (res) {
setLike(true);
}
}
};

return (
<Container>
<ColBox>
Expand Down
8 changes: 4 additions & 4 deletions src/components/Booth/ReviewItem.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import tw from "twin.macro";
import styled from "styled-components";
import { Review } from "../../@types/review";

function ReviewItem({ name, year, month, date, contents, features, imageUrl, imageCount }: Review) {
import DefaultImg from "../../assets/images/default-profile.svg?url";
function ReviewItem({ name, year, month, date, contents, features, imageUrl, imageCount, profileUrl }: Review) {
return (
<Container>
<div className="flex gap-[10px]">
<div className="flex flex-col w-full gap-[10px]">
<div className="flex gap-[8px] items-center">
<div className="profile-icon"></div>
<img className="profile-icon" src={profileUrl ? profileUrl : DefaultImg} />
<div className="flex flex-col">
<span className="nickname">{`@${name}`}</span>
<span className="date">{`${year}.${month}.${date} 작성`}</span>
Expand Down Expand Up @@ -39,7 +39,7 @@ export default ReviewItem;
const Container = styled.div`
${tw`w-full flex flex-col font-display my-[20px] gap-[10px]`}
.profile-icon {
${tw`w-[33px] h-[33px] rounded-[50%] bg-gray200`}
${tw`w-[33px] h-[33px] rounded-[50%]`}
}
.nickname {
${tw`font-semibold text-[16px] text-gray700`}
Expand Down
Loading

0 comments on commit 906d718

Please sign in to comment.