Skip to content

Commit

Permalink
Merge pull request #192 from TEAM-FLASH/Feat/#135
Browse files Browse the repository at this point in the history
[S4] 딤 모달 내 스와이퍼 기능 작업중
  • Loading branch information
s0zzang authored Dec 27, 2024
2 parents e868068 + d3d855a commit fd31c2f
Show file tree
Hide file tree
Showing 12 changed files with 135 additions and 23 deletions.
5 changes: 4 additions & 1 deletion src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import Button from '@components/Button/Button';
import styled from '@emotion/styled';
import useModal from '@hooks/useModal';
import { useModalStore } from '@store/useModalStore';
import { Hidden, TypoBodyMdR, TypoTitleSmS } from '@styles/Common';
import variables from '@styles/Variables';

Expand Down Expand Up @@ -40,7 +41,9 @@ interface IContentStyle {
* - 모달 내 버튼 : {text: string, event: MouseEventHandler<HTMLButtonElement>}[]
*/
const Modal = ({ modalId = 1, type = 'default', title, children, withBtn = true, buttons = [] }: ModalProp) => {
const { isOpen, close } = useModal(modalId);
const modals = useModalStore((state) => state.modals);
const isOpen = modals[modalId];
const { close } = useModal(modalId);
const handleClose = () => close();

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/Studio/StudioItem.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @jsxImportSource @emotion/react */
import Bookmark from '@components/Bookmark/Bookmark';
import ImageSwiper from '@components/ImageSwiper/ImageSwiper';
import ImageSwiper from '@components/Swiper/ImageSwiper';
import styled from '@emotion/styled';
import { TypoTitleSmS } from '@styles/Common';
import variables from '@styles/Variables';
Expand Down
53 changes: 53 additions & 0 deletions src/components/Swiper/DimSwiper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { useDimSwiperStore } from '@store/useDimSwiper';
import { Dispatch, ReactNode, SetStateAction, useEffect, useState } from 'react';
import { Navigation, Pagination, Virtual } from 'swiper/modules';
import { Swiper, SwiperClass } from 'swiper/react';
import { IPortfolio } from 'types/types';

import 'swiper/css';
import 'swiper/css/pagination';

interface IDimSwiper {
children: ReactNode;
data: IPortfolio[];
setSlideSet: Dispatch<SetStateAction<IPortfolio[]>>;
}

const DimSwiper = ({ children, data, setSlideSet }: IDimSwiper) => {
const [swiperRef, setSwiperRef] = useState<SwiperClass>();
const { selectedId, setSelectedId } = useDimSwiperStore();
const isFirstSlide = data[0].id === selectedId;

const getNewSlideSet = (clickedId: number) => {
return data.filter(({ id }: { id: number }) => id === clickedId || id === clickedId - 1 || id === clickedId + 1);
};

const handleChange = () => {
if (!swiperRef) return null;

const direction = swiperRef.swipeDirection === 'next' ? 1 : -1;
setSelectedId(selectedId, direction);
swiperRef.slideTo(isFirstSlide ? 0 : 1, 0, false);
};

const swiperOption = {
modules: [Virtual, Pagination, Navigation],
onSwiper: (e: SwiperClass) => setSwiperRef(e),
onTransitionEnd: handleChange,
slidesPerView: 1,
initialSlide: isFirstSlide ? 0 : 1,
pagination: {
type: 'fraction' as 'fraction',
},
centeredSlides: true,
};

useEffect(() => {
// console.log(isFirstSlide);
setSlideSet(getNewSlideSet(selectedId));
}, [selectedId]);

return <Swiper {...swiperOption}>{children}</Swiper>;
};

export default DimSwiper;
File renamed without changes.
5 changes: 2 additions & 3 deletions src/hooks/useModal.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { useModalStore } from '@store/useModalStore';

const useModal = (modalId = 1) => {
const { modals, setOpen } = useModalStore((state) => state);
const isOpen = modals[modalId] || false;
const setOpen = useModalStore((state) => state.setOpen);
const open = () => setOpen(modalId, true);
const close = () => setOpen(modalId, false);

return { isOpen, open, close };
return { open, close };
};

export default useModal;
2 changes: 1 addition & 1 deletion src/pages/Studio/StudioMenu/StudioMenuDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import StudioMenuDetailInfo from './StudioMenuDetailInfo';
import { useEffect, useState } from 'react';
import StudioMenuDetailReview from './StudioMenuDetailReview';
import { IMenuListRes } from 'types/types';
import ImageSwiper from '@components/ImageSwiper/ImageSwiper';
import ImageSwiper from '@components/Swiper/ImageSwiper';
import Button from '@components/Button/Button';

const StudioMenuDetail = () => {
Expand Down
25 changes: 25 additions & 0 deletions src/pages/Studio/StudioPortfolio/PortfolioSwiper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/** @jsxImportSource @emotion/react */

import DimSwiper from '@components/Swiper/DimSwiper';
import { TypoBodyMdR } from '@styles/Common';
import { useState } from 'react';
import { SwiperSlide } from 'swiper/react';
import { IPortfolio } from 'types/types';

const PortfolioSwiper = ({ data, studioName }: { data: IPortfolio[]; studioName: string }) => {
const [slideSet, setSlideSet] = useState<IPortfolio[]>([]);

return (
<DimSwiper data={data} setSlideSet={setSlideSet}>
{slideSet &&
slideSet.map(({ id, url, description }) => (
<SwiperSlide key={id} virtualIndex={id}>
<img src={url} alt={`${studioName}-${id}`} />
<p css={TypoBodyMdR}>{description}</p>
</SwiperSlide>
))}
</DimSwiper>
);
};

export default PortfolioSwiper;
37 changes: 31 additions & 6 deletions src/pages/Studio/StudioPortfolio/StudioPortfolio.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
/** @jsxImportSource @emotion/react */

import Button from '@components/Button/Button';
import Header from '@components/Header/Header';
import MasonryList from '@components/Masonry/Masonry';
import EmptyMessage from '@components/Message/EmptyMessage';
import StudioNavigator from '@components/Navigator/StudioNavigator';
import styled from '@emotion/styled';
import useModal from '@hooks/useModal';
import { useDimSwiperStore } from '@store/useDimSwiper';
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { IPortfolio } from 'types/types';
import DimmedModal from '../components/DimmedModal';
import PortfolioSwiper from './PortfolioSwiper';

const StudioPortfolio = () => {
const { _id } = useParams() as { _id: string };
const { open } = useModal(1);

const [data, setData] = useState<IPortfolio[]>([]);
const [studioName, setStudioName] = useState('');
const { _id } = useParams() as { _id: string };
const handleClick = () => {
console.log('click');
const [menuNames, setMenuNames] = useState<string[]>();

const setSelectedId = useDimSwiperStore((state) => state.setSelectedId);

const handleClick = (clickedId: number) => {
setSelectedId(clickedId);
open();
};

const fetchPortfolio = async () => {
Expand All @@ -25,7 +38,8 @@ const StudioPortfolio = () => {
},
});
const data = await response.json();
setData(data.content);
setData(data.portfolioDtos.content);
setMenuNames(data.menuNameList);
} catch (err) {
console.error('Failed to fetch data');
}
Expand All @@ -45,13 +59,19 @@ const StudioPortfolio = () => {
<li>
<Button text="전체" width="fit" size="small" variant="white" />
</li>
{menuNames &&
menuNames.map((menu) => (
<li key={menu}>
<Button text={menu} width="fit" size="small" variant="white" />
</li>
))}
</FilterBoxStyle>

<ListStyle>
{data && data.length ? (
{data.length ? (
<MasonryList>
{data.map(({ url, studio, id }) => (
<div key={`${studio}-${id}`} onClick={handleClick}>
<div key={`${studio}-${id}`} onClick={() => handleClick(id)}>
<img src={url} alt={`${studio}-${id}`} />
</div>
))}
Expand All @@ -60,6 +80,10 @@ const StudioPortfolio = () => {
<EmptyMessage message="포트폴리오가 없습니다." />
)}
</ListStyle>

<DimmedModal>
<PortfolioSwiper data={data} studioName={studioName} />
</DimmedModal>
</>
);
};
Expand All @@ -68,6 +92,7 @@ export default StudioPortfolio;

const FilterBoxStyle = styled.ul`
display: flex;
gap: 0.6rem;
margin: 1.2rem 0;
`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import variables from '@styles/Variables';
import StarRating from './StarRating';
import ReviewContent from './ReviewContent';
import { useState } from 'react';
import ImageSwiper from '@components/ImageSwiper/ImageSwiper';
import ImageSwiper from '@components/Swiper/ImageSwiper';
import { formatTimeAgo } from '@utils/formatTimeAgo';
import { IReviewImages } from 'types/types';
import { css } from '@emotion/react';
Expand Down
15 changes: 5 additions & 10 deletions src/pages/Studio/components/DimmedModal.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
/** @jsxImportSource @emotion/react */
import Modal from '@components/Modal/Modal';
import { css } from '@emotion/react';
// import { css } from '@emotion/react';
import styled from '@emotion/styled';
import { Swiper } from 'swiper/react';

const DimmedModal = ({ children }: { children: React.ReactNode }) => {
return (
<>
<Modal type="dimmed" title={`3/20`} withBtn={false}>
<DimmedModalStyle>
<Swiper css={swiperStyle} slidesPerView={1}>
{children}
</Swiper>
</DimmedModalStyle>
<DimmedModalStyle>{children}</DimmedModalStyle>
</Modal>
</>
);
Expand All @@ -23,8 +18,8 @@ const DimmedModalStyle = styled.div`
display: flex;
`;

const swiperStyle = css`
color: white;
`;
// const swiperStyle = css`
// color: white;
// `;

export default DimmedModal;
11 changes: 11 additions & 0 deletions src/store/useDimSwiper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { create } from 'zustand';

interface DimSwiperState {
selectedId: number;
setSelectedId: (id: number, direction?: number) => void;
}

export const useDimSwiperStore = create<DimSwiperState>((set) => ({
selectedId: 0,
setSelectedId: (id, direction) => set((state) => ({ selectedId: (id || state.selectedId) + (direction || 1) })),
}));
1 change: 1 addition & 0 deletions src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface IPortfolio {
vibe: string;
name: string;
url: string;
menuId: number;
description: string;
created_at: string;
updated_at: null | string;
Expand Down

0 comments on commit fd31c2f

Please sign in to comment.