Skip to content

Commit

Permalink
Merge pull request #26 from 4bujak-4bujak/feature/office
Browse files Browse the repository at this point in the history
[feat] 오피스 상세 정보
  • Loading branch information
jiohjung98 authored Jun 1, 2024
2 parents 4f7a5f1 + 09e9458 commit 2fddc31
Show file tree
Hide file tree
Showing 15 changed files with 641 additions and 198 deletions.
24 changes: 24 additions & 0 deletions src/api/map/getSelectedOffice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { SelectedBranch } from '@/api/types/branch';

export const getSelectedOfficeInfo = async (name: string): Promise<{ data: SelectedBranch }> => {
try {
const backendUrl = process.env.NEXT_PUBLIC_BASE_URL;
const token = document.cookie.replace(/(?:(?:^|.*;\s*)token\s*=\s*([^;]*).*$)|^.*$/, "$1");
const response = await fetch(`${backendUrl}branches/${encodeURIComponent(name)}`, {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
cache: 'no-store'
});
if (!response.ok) {
throw new Error('Failed to fetch branch information');
}
const data: { data: SelectedBranch } = await response.json();
return data;
} catch (error) {
console.error('Error fetching branch info:', error);
throw error;
}
};
13 changes: 12 additions & 1 deletion src/api/types/branch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,15 @@ export interface MapSearchResultProps {
export interface OfficeInfoProps {
branchName: string;
branchAddress: string;
}
}

export interface SelectedBranch {
branchName: string;
branchAddress: string;
branchLatitude: number;
branchLongitude: number;
branchPhoneNumber: string;
roadFromStation: string;
stationToBranch: string[];
}

7 changes: 7 additions & 0 deletions src/api/types/notice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

export interface Notice {
title: string;
content: string;
type: string;
}

54 changes: 41 additions & 13 deletions src/components/home/OfficeNotice.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
import React from 'react';
import React, { useState } from 'react';
import { useNotices } from '@/hook/useNotices';

const OfficeNotice = () => {
return (
<div className="w-full h-12 mt-7 bg-gray-200 flex items-center gap-[13px] px-[13px] py-[14px] rounded shadow border border-gray-200">
<div>
<img src="/home/notice.svg" alt="" />
</div>
const OfficeNotice: React.FC = () => {
const { urgentNoticeTitle, urgentNoticeContent } = useNotices();
const [isModalOpen, setIsModalOpen] = useState(false);

<div className="flex-1 flex items-center gap-[22px] justify-between">
<div className="text-sm font-normal flex justify-center text-space-purple-darker">
유저님, 오늘 하루도 화이팅 하세요!
</div>
const handleModalOpen = () => {
setIsModalOpen(true);
};

const handleModalClose = () => {
setIsModalOpen(false);
};

return (
<>
<div className="w-full h-12 mt-7 bg-gray-200 flex items-center gap-[13px] px-[13px] py-[14px] rounded shadow border border-gray-200">
<div>
<img src="/home/toNext.svg" alt="" />
<img src="/home/notice.svg" alt="" />
</div>

<div className="flex-1 flex items-center gap-[22px] justify-between">
<div className="text-sm font-normal flex justify-center text-space-purple-darker">
{urgentNoticeTitle ? urgentNoticeTitle : '긴급 공지가 없습니다.'}
</div>
{urgentNoticeContent && (
<div onClick={handleModalOpen} className="cursor-pointer">
<img src="/home/toNext.svg" alt="" />
</div>
)}
</div>
</div>
</div>
{isModalOpen && (
<div className="fixed w-full inset-0 flex items-center justify-center z-50">
<div className="fixed inset-0 bg-black opacity-50" onClick={handleModalClose}></div>
<div className="bg-white p-6 rounded shadow-lg z-50 max-w-[393px] mx-[20px] px-[20px]">
<h2 className="text-center text-xl font-semibold mb-4">긴급 공지</h2>
<p>{urgentNoticeContent}</p>
<div className='w-full'>
<button onClick={handleModalClose} className="flex mx-auto mt-4 w-[163px] h-[36px] bg-[#EDEBF8] text-[#3B268C] px-4 py-[6px] rounded-md justify-center items-center">닫기</button>
</div>
</div>
</div>
)}
</>
);
};

Expand Down
174 changes: 174 additions & 0 deletions src/components/map/BranchInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect } from 'react';
import Image from 'next/image';
import { useRouter } from 'next/router';
import { Swiper, SwiperSlide } from 'swiper/react';
import 'swiper/css';
import 'swiper/css/pagination';
import { Pagination } from 'swiper/modules';
import { IoIosArrowRoundBack } from 'react-icons/io';
import { OfficeInfoProps } from '@/api/types/branch';
import { subwayLineColors, subwayLineAbbreviations } from '@/constant/station';
import BranchOffice from './BranchOffice';

const BranchInfo: React.FC<OfficeInfoProps> = ({ branchName }) => {
const router = useRouter();

const address = router.query.address as string;
const branchPhoneNumber = router.query.branchPhoneNumber as string;
const roadFromStation = router.query.roadFromStation as string;
const stationToBranch = router.query.stationToBranch as string;

useEffect(() => {
if (address && branchPhoneNumber && roadFromStation && stationToBranch) {
localStorage.setItem('branchInfo', JSON.stringify({
branchName,
address,
branchPhoneNumber,
roadFromStation,
stationToBranch
}));
}
}, [address, branchPhoneNumber, roadFromStation, stationToBranch]);

useEffect(() => {
if (!address || !branchPhoneNumber || !roadFromStation || !stationToBranch) {
const savedBranchInfo = localStorage.getItem('branchInfo');
if (savedBranchInfo) {
const { branchName, address, branchPhoneNumber, roadFromStation, stationToBranch } = JSON.parse(savedBranchInfo);
router.replace({
pathname: router.pathname,
query: {
name: branchName,
address,
branchPhoneNumber,
roadFromStation,
stationToBranch
}
}, undefined, { shallow: true });
}
}
}, []);

const handleBackClick = () => {
router.push('/map');
};


return (
<section className="w-full h-full">
<header className="top-0 left-0 right-0 bg-white z-50 shadow-md py-4 flex items-center">
<IoIosArrowRoundBack size={40} className="ml-[6px]" onClick={handleBackClick} />
<span className="text-lg font-semibold ml-[8px]">
{branchName}
</span>
</header>
<div className="">
<Swiper
slidesPerView={1}
loop={true}
spaceBetween={8}
pagination={{ clickable: true }}
modules={[Pagination]}
>
<SwiperSlide className="flex justify-center items-center h-full">
<Image src="/map/OfficeDefaultImg2.png" alt="Office Image 1" width={500} height={246} className="h-[246px] object-cover" />
</SwiperSlide>
<SwiperSlide className="flex justify-center items-center h-full">
<Image src="/map/OfficeDefaultImg2.png" alt="Office Image 2" width={500} height={246} className="h-[246px] object-cover" />
</SwiperSlide>
<SwiperSlide className="flex justify-center items-center h-full">
<Image src="/map/OfficeDefaultImg2.png" alt="Office Image 3" width={500} height={246} className="h-[246px] object-cover" />
</SwiperSlide>
</Swiper>
</div>
<article className="">
<div className='p-4'>
<div className="text-black/opacity-20 text-lg font-extrabold py-[10px]">찾아오는길</div>
<div className='flex py-[10px]'>
<Image src="/map/OfficeLocationSmall1.svg" className='mb-auto pt-[3px]' alt="OfficeLocationSmall" width={12} height={16} />
<div className='flex flex-col'>
<p className="text-sm text-gray-600 ml-[8px] mb-[5px]">{address}</p>
<div className='flex ml-[8px] space-x-[4px] items-center'>
{stationToBranch && stationToBranch.split(',').map((line) => {
const trimmedLine = line.trim();
const abbreviation = subwayLineAbbreviations[trimmedLine] || trimmedLine;
return (
<div
key={trimmedLine}
className="w-[16px] h-[16px] flex items-center justify-center rounded-full text-white font-bold"
style={{ backgroundColor: subwayLineColors[trimmedLine], fontSize: '12px' }}
>
{abbreviation}
</div>
);
})}
<p className="text-sm text-gray-600 ml-[8px]">{roadFromStation}</p>
</div>
</div>
</div>
<div className='flex py-[10px]'>
<Image src="/map/OfficeCallImg.svg" className='mb-auto pt-[3px]' alt="OfficeCallImg" width={12} height={16} />
<p className="text-sm text-gray-600 ml-[8px]">{branchPhoneNumber}</p>
</div>
<div className='flex py-[10px]'>
<Image src="/map/OfficeParkImg.svg" className='mb-auto pt-[3px]' alt="OfficeParkImg" width={12} height={16} />
<p className="text-sm text-gray-600 ml-[8px]">출차 전 2층 데스크에서 1시간 무료 적용,<br/>이후 10분당 800원 비용 발생</p>
</div>
</div>
<div className="w-full h-1 bg-neutral-200" />
<div className="px-4 py-6">
<div className="text-black/opacity-20 text-lg font-extrabold py-[10px]">공용 공간 리스트</div>
</div>
<div className="w-full h-px bg-neutral-200" />
<div className="px-4 py-6">
<div className="text-black/opacity-20 text-lg font-extrabold py-[10px]">편의시설</div>
<div className="grid grid-cols-4 gap-4 py-[10px]">
<div className="flex flex-col items-center">
<Image src="/map/LoungeImg.svg" alt="LoungeImg" width={12} height={16} className="w-[40px] h-[40px] my-auto"/>
<p className="mt-2">라운지</p>
</div>
<div className="flex flex-col items-center">
<Image src="/map/RechargeImg.svg" alt="RechargeImg" width={12} height={16} className="w-[40px] h-[40px] my-auto"/>
<p className="mt-2">리차징룸</p>
</div>
<div className="flex flex-col items-center">
<Image src="/map/ParcelImg.svg" alt="ParcelImg" width={12} height={16} className="w-[40px] h-[40px] my-auto"/>
<p className="mt-2">무인택배</p>
</div>
<div className="flex flex-col items-center">
<Image src="/map/PhoneBooseImg.svg" alt="PhoneBooseImg" width={12} height={16} className="w-[40px] h-[40px] my-auto"/>
<p className="mt-2">폰부스</p>
</div>
<div className="flex flex-col items-center">
<Image src="/map/PrinterImg.svg" alt="PrinterImg" width={12} height={16} className="w-[40px] h-[40px] my-auto"/>
<p className="mt-2">복합기</p>
</div>
<div className="flex flex-col items-center">
<Image src="/map/SnackBarImg.svg" alt="SnackBarImg" width={12} height={16} className="w-[40px] h-[40px] my-auto"/>
<p className="mt-2">스낵바</p>
</div>
<div className="flex flex-col items-center">
<Image src="/map/SuppliesImg.svg" alt="SuppliesImg" width={12} height={16} className="w-[40px] h-[40px] my-auto"/>
<p className="mt-2">사무용품</p>
</div>
<div className="flex flex-col items-center">
<Image src="/map/CoffeeImg.svg" alt="CoffeeImg" width={12} height={16} className="w-[40px] h-[40px] my-auto"/>
<p className="mt-2">무제한 커피</p>
</div>
</div>
</div>
<div className="w-full h-px bg-neutral-200" />
<div className="px-4 py-6">
<div className="text-black/opacity-20 text-lg font-extrabold">공지사항</div>
</div>
<BranchOffice branchName={branchName}/>
<footer className='w-full text-center py-[30px]'>
<button className='w-[361px] h-12 bg-indigo-700 rounded-lg border border-indigo-700 text-center text-stone-50 text-[15px] font-semibold'>예약하기</button>
</footer>
</article>
</section>
);
};

export default BranchInfo;
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import React, { useEffect, useRef } from 'react';
import Image from 'next/image';
import { ModalProps } from '@/api/types/branch';
import { useRouter } from 'next/router';
import { getSelectedOfficeInfo } from '@/api/map/getSelectedOffice';

const OfficeModal: React.FC<ModalProps> = ({ isOpen, onClose, branchName, branchAddress }) => {

const BranchModal: React.FC<ModalProps> = ({ isOpen, onClose, branchName, branchAddress }) => {
const modalRef = useRef<HTMLDivElement>(null);
const router = useRouter();

Expand Down Expand Up @@ -37,11 +39,25 @@ const OfficeModal: React.FC<ModalProps> = ({ isOpen, onClose, branchName, branch

if (!isOpen) return null;

const handleOfficeInfo = () => {
router.push({
pathname: `/branches/${encodeURIComponent(branchName)}`,
query: { address: branchAddress },
});

const handleOfficeInfo = async () => {
try {
const data = await getSelectedOfficeInfo(branchName);
const officeInfo = data.data;
console.log(officeInfo);
router.push({
pathname: `/branches/${encodeURIComponent(branchName)}`,
query: {
name: branchName,
address: officeInfo.branchAddress,
branchPhoneNumber: officeInfo.branchPhoneNumber,
roadFromStation: officeInfo.roadFromStation,
stationToBranch: officeInfo.stationToBranch.join(',')
}
}, `/branches/${encodeURIComponent(branchName)}`);
} catch (error) {
console.error('Error fetching office info:', error);
}
};

return (
Expand Down Expand Up @@ -87,4 +103,4 @@ const OfficeModal: React.FC<ModalProps> = ({ isOpen, onClose, branchName, branch
);
};

export default OfficeModal;
export default BranchModal;
Loading

0 comments on commit 2fddc31

Please sign in to comment.