Skip to content

Commit

Permalink
Merge pull request #41 from 4bujak-4bujak/feature/meetingroomQA
Browse files Browse the repository at this point in the history
[feat] 지도, 미팅룸 예약 추가 작업
  • Loading branch information
jiohjung98 authored Jun 9, 2024
2 parents e05882c + b201865 commit f8f32f9
Show file tree
Hide file tree
Showing 42 changed files with 297 additions and 145 deletions.
Binary file added public/branch/branch1-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/branch/branch1-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/branch/branch1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/branch/branch2-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/branch/branch2-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/branch/branch2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/branch/branch3-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/branch/branch3-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/branch/branch3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions public/office/check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/focus.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/medium1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/medium2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/medium3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/mini1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/mini2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/mini3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions public/office/people.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/recharge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/standard1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/standard2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/standard3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/state1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/state2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/office/state3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 15 additions & 19 deletions src/components/map/BranchInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,22 @@ const BranchInfo: React.FC = () => {
const [urgentNotice, setUrgentNotice] = useState<{ title: string; content: string } | null>(null);

const [currentSlide, setCurrentSlide] = useState(1);
const totalSlides = 3;
const totalSlides = 2;

const branchName = router.query.name as string;
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;
const branchId = router.query.branchId;
const branchImage = router.query.image as string;

const numericBranchId = Array.isArray(branchId) ? parseInt(branchId[0], 10) : parseInt(branchId as string, 10);

const [activeTab, setActiveTab] = useState('meetingRoom');

const imagePrefix = (branchImage || '').replace('.png', '');

console.log(branchId);
console.log(numericBranchId)

Expand Down Expand Up @@ -103,7 +108,10 @@ const BranchInfo: React.FC = () => {
const data = await getSelectedOfficeInfo(branchName);
if (data.data) {
setReservedBranch(data?.data, Date.now());
router.push('/reservation');
router.push({
pathname: '/reservation',
query: { tab: activeTab },
});
}
} catch (error) {
console.error('Error updating selected branch:', error);
Expand Down Expand Up @@ -147,7 +155,7 @@ const BranchInfo: React.FC = () => {
onSlideChange={(swiper) => setCurrentSlide(swiper.realIndex + 1)}>
<SwiperSlide className="flex justify-center items-center h-full relative">
<Image
src="/map/OfficeDefaultImg2.png"
src={`${imagePrefix}-1.png`}
alt="Office Image 1"
width={500}
height={246}
Expand All @@ -159,7 +167,7 @@ const BranchInfo: React.FC = () => {
</SwiperSlide>
<SwiperSlide className="flex justify-center items-center h-full relative">
<Image
src="/map/OfficeDefaultImg2.png"
src={`${imagePrefix}-2.png`}
alt="Office Image 2"
width={500}
height={246}
Expand All @@ -169,18 +177,6 @@ const BranchInfo: React.FC = () => {
{currentSlide} / {totalSlides}
</div>
</SwiperSlide>
<SwiperSlide className="flex justify-center items-center h-full relative">
<Image
src="/map/OfficeDefaultImg2.png"
alt="Office Image 3"
width={500}
height={246}
className="h-[246px] object-cover"
/>
<div className="w-[50px] absolute bottom-2 right-2 bg-black bg-opacity-60 text-white px-2 py-1 rounded text-center">
{currentSlide} / {totalSlides}
</div>
</SwiperSlide>
</Swiper>
</div>
<article className="">
Expand Down Expand Up @@ -250,7 +246,7 @@ const BranchInfo: React.FC = () => {
<div className="text-black/opacity-20 text-lg font-extrabold py-[10px]">
공용 공간 리스트
</div>
<TabSection branchId={numericBranchId} />
<TabSection branchId={numericBranchId} activeTab={activeTab} setActiveTab={setActiveTab} />
</div>
<div className="w-full h-px bg-neutral-200" />
<div className="px-4 py-6">
Expand Down Expand Up @@ -345,9 +341,9 @@ const BranchInfo: React.FC = () => {
<div className="text-black/opacity-20 text-lg font-extrabold">공지사항</div>
</div>
<BranchOffice branchName={branchName} setUrgentNotice={setUrgentNotice} />
<footer className="fixed bottom-0 w-full text-center pb-[30px] bg-white no-box-shadow">
<footer className="fixed bottom-0 left-1/2 transform -translate-x-1/2 w-full max-w-[393px] px-4 text-center pb-[30px] bg-white no-box-shadow">
<button
className="reserveBtn w-[90%] h-12 rounded-lg border border-indigo-700 text-center text-stone-50 text-[15px] font-semibold"
className="reserveBtn w-[100%] mx-auto h-12 rounded-lg border border-indigo-700 text-center text-stone-50 text-[15px] font-semibold"
onClick={handleGoToReservation}>
예약하기
</button>
Expand Down
24 changes: 14 additions & 10 deletions src/components/map/BranchModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { useRouter } from 'next/router';
import { getSelectedOfficeInfo } from '@/api/map/getSelectedOffice';
import { useBranchStore2 } from '@/store/reserve.store';

const getBranchImage = (branchName: string): string => {
const hash = Array.from(branchName).reduce((acc: number, char: string) => acc + char.charCodeAt(0), 0);
const imageIndex = (hash % 3) + 1;
return `/branch/branch${imageIndex}.png`;
};

const BranchModal: React.FC<ModalProps> = ({ isOpen, onClose, branchName, branchAddress, branchActiveMeetingRoomCount, branchTotalMeetingRoomCount }) => {
const modalRef = useRef<HTMLDivElement>(null);
Expand All @@ -27,36 +32,35 @@ const BranchModal: React.FC<ModalProps> = ({ isOpen, onClose, branchName, branch
onClose();
}
};

if (isOpen) {
document.addEventListener('mousedown', handleClickOutside);
} else {
document.removeEventListener('mousedown', handleClickOutside);
}

return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, [isOpen, onClose]);


if (!isOpen) return null;


const handleOfficeInfo = async () => {
try {
const data = await getSelectedOfficeInfo(branchName);
const officeInfo = data.data;
const data = await getSelectedOfficeInfo(branchName);
const officeInfo = data.data;
console.log(officeInfo);
router.push({
pathname: `/branches/${encodeURIComponent(branchName)}`,
query: {
name: branchName,
query: {
name: branchName,
address: officeInfo.branchAddress,
branchPhoneNumber: officeInfo.branchPhoneNumber,
roadFromStation: officeInfo.roadFromStation,
stationToBranch: officeInfo.stationToBranch.join(','),
branchId: officeInfo.branchId as number,
image: getBranchImage(branchName),
}
}, `/branches/${encodeURIComponent(branchName)}`);
} catch (error) {
Expand All @@ -66,7 +70,7 @@ const BranchModal: React.FC<ModalProps> = ({ isOpen, onClose, branchName, branch

const handleGoToReservation = async () => {
try {
const data = await getSelectedOfficeInfo(branchName);
const data = await getSelectedOfficeInfo(branchName);
if (data.data) {
setReservedBranch(data?.data, Date.now());
router.push('/reservation/');
Expand All @@ -82,7 +86,7 @@ const BranchModal: React.FC<ModalProps> = ({ isOpen, onClose, branchName, branch
<div className='flex'>
<div className="flex-shrink-0 w-[88px] h-[88px] bg-gray-300 rounded-md">
<Image
src="/map/OfficeDefaultImg.png"
src={getBranchImage(branchName)}
alt="Office"
width={88}
height={88}
Expand Down
151 changes: 133 additions & 18 deletions src/components/map/TapSection.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,53 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, SetStateAction, Dispatch } from 'react';
import { getOfficeMeetingRoomCount } from '@/api/map/getAvailableOffice';
import { OfficeRoomCounts } from '@/api/types/branch';
import Image from 'next/image';

const TabSection = ({ branchId }: { branchId: number }) => {
const [activeTab, setActiveTab] = useState('meetingRoom');
const imagePairs = [
{
mini: '/office/mini1.png',
standard: '/office/standard1.png',
medium: '/office/medium1.png',
state: '/office/state1.png',
},
{
mini: '/office/mini2.png',
standard: '/office/standard2.png',
medium: '/office/medium2.png',
state: '/office/state2.png',
},
{
mini: '/office/mini3.png',
standard: '/office/standard3.png',
medium: '/office/medium3.png',
state: '/office/state3.png',
},
];

const hashCode = (str: string): number => {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash |= 0;
}
return hash;
};

const seededRandom = (seed: number) => {
const x = Math.sin(seed++) * 10000;
return x - Math.floor(x);
};

interface TabSectionProps {
branchId: number;
activeTab: string;
setActiveTab: Dispatch<SetStateAction<string>>;
}

const TabSection: React.FC<TabSectionProps> = ({ branchId, activeTab, setActiveTab }) => {
const [data, setData] = useState<OfficeRoomCounts | null>(null);
const [selectedImages, setSelectedImages] = useState(imagePairs[0]);

useEffect(() => {
const fetchData = async () => {
Expand All @@ -22,25 +65,97 @@ const TabSection = ({ branchId }: { branchId: number }) => {
}
}, [branchId]);

useEffect(() => {
if (branchId) {
const seed = hashCode(branchId.toString());
const randomIndex = Math.floor(seededRandom(seed) * imagePairs.length);
setSelectedImages(imagePairs[randomIndex]);
}
}, [branchId]);

const renderContent = () => {
if (!data) return <div></div>;

switch (activeTab) {
case 'meetingRoom':
return (
<div>
<p>Mini Room Count: {data.miniRoomCount}</p>
<p>Standard Room Count: {data.standardRoomCount}</p>
<p>Medium Room Count: {data.mediumRoomCount}</p>
<p>State Room Count: {data.stateRoomCount}</p>
const meetingRooms = [
{ type: 'mini', label: '미니', capacity: '1~4명', description: '적은 인원 수가 빠르게 회의 진행할 수 있는 공간', count: data.miniRoomCount },
{ type: 'standard', label: '스탠다드', capacity: '5~8명', description: '적은 인원 수가 빠르게 회의 진행할 수 있는 공간', count: data.standardRoomCount },
{ type: 'medium', label: '미디움', capacity: '9~12명', description: '적은 인원 수가 빠르게 회의 진행할 수 있는 공간', count: data.mediumRoomCount },
{ type: 'state', label: '스테이트', capacity: '13~15명', description: '여러 팀의 협업 또는 화상회의가 편한 공간', count: data.stateRoomCount },
] as const;

if (activeTab === 'meetingRoom') {
return (
<div>
{meetingRooms.map((room, index) => (
<div key={index} className="relative flex flex-col h-full rounded mb-[12px]">
<Image src={selectedImages[room.type]} width={361} height={120} alt={`${room.label} Room`} className="object-cover rounded" />
<div className="absolute top-0 left-0 w-full h-full flex flex-col justify-between bg-black bg-opacity-50 text-white p-4 rounded">
<div className='h-full'>
<div className='flex flex-row justify-between'>
<p className="text-white text-base font-semibold font-['Pretendard']">{room.label}</p>
<p className="text-white text-base font-normal font-['Pretendard']">{room.count}</p>
</div>
<div className='flex flex-row mt-[10px]'>
<Image src="/office/people.svg" alt="people" width={14} height={10} className="" />
<p className="text-white text-xs font-normal font-['Pretendard'] ml-[5px] pt-[2px]">{room.capacity} 수용 가능</p>
</div>
<p className="absolute bottom-0 pb-4 mt-auto text-white text-xs font-normal font-['Pretendard']">{room.description}</p>
</div>
</div>
</div>
))}
</div>
);
}

if (activeTab === 'rechargingRoom') {
return (
<div className="relative flex flex-col h-full rounded mb-[12px]">
<Image src='/office/recharge.png' width={361} height={120} alt="Recharge Room" className="object-cover rounded" />
<div className="absolute top-0 left-0 w-full h-full flex flex-col justify-between bg-black bg-opacity-50 text-white p-4 rounded">
<div className='h-full'>
<div className='flex flex-row justify-between'>
<p className="text-white text-base font-semibold font-['Pretendard']">리차징룸</p>
<p className="text-white text-base font-normal font-['Pretendard']">{data.rechargingRoomCount}</p>
</div>
<div className='flex flex-row items-center mt-[10px]'>
<Image src="/office/people.svg" alt="people" width={14} height={10} className="" />
<p className="text-white text-xs font-normal font-['Pretendard'] ml-[5px] pt-[2px]">예약 후 이용가능</p>
</div>
<div className='flex flex-row mt-[5px] items-center'>
<Image src="/office/check.svg" alt="check" width={11} height={11} className="" />
<p className="text-white text-xs font-normal font-['Pretendard'] ml-[5px] pt-[2px]">리클라이너</p>
</div>
<p className="absolute bottom-0 pb-4 mt-auto text-white text-xs font-normal font-['Pretendard'] leading-[18px]">휴대폰 고속 충전기 및 리클라이너가 구비되어 있어<br/>업무 중 휴식이 필요할 때 편리하게 이용할 수 있습니다.</p>
</div>
</div>
);
case 'rechargingRoom':
return <div>Recharging Room Count: {data.rechargingRoomCount}</div>;
case 'focusZone':
return <div>Focus Desk Count: {data.focusDeskCount}</div>;
default:
return null;
</div>
);
}

if (activeTab === 'focusZone') {
return (
<div className="relative flex flex-col h-full rounded mb-[12px]">
<Image src='/office/focus.png' width={361} height={120} alt="Focus Zone" className="object-cover rounded" />
<div className="absolute top-0 left-0 w-full h-full flex flex-col justify-between bg-black bg-opacity-50 text-white p-4 rounded">
<div className='h-full'>
<div className='flex flex-row justify-between'>
<p className="text-white text-base font-semibold font-['Pretendard']">포커스존</p>
<p className="text-white text-base font-normal font-['Pretendard']">{data.focusDeskCount}</p>
</div>
<div className='flex flex-row mt-[10px]'>
<Image src="/office/people.svg" alt="people" width={14} height={10} className="" />
<p className="text-white text-xs font-normal font-['Pretendard'] ml-[5px] pt-[2px]">단독 사용</p>
</div>
<div className='flex flex-row mt-[5px]'>
<Image src="/office/check.svg" alt="check" width={11} height={11} className="" />
<p className="text-white text-xs font-normal font-['Pretendard'] ml-[5px] pt-[2px]">고속 충전기</p>
</div>
<p className="absolute bottom-0 pb-4 mt-auto text-white text-xs font-normal font-['Pretendard'] leading-[18px]">개인 오피스 안에서 업무를 효율적으로 볼 수 있습니다.</p>
</div>
</div>
</div>
);
}
};

Expand Down
19 changes: 17 additions & 2 deletions src/components/reservation/ReservationIndex.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import CurrentRoom from './shared/CurrentRoom';
import ChangeRoomType from './shared/ChangeRoomType';
import FocuszoneIndex from './focuszone/FocuszoneIndex';
import MeetingRoomIndex from './meetingRoom/MeetingRoomIndex';
import RechargingRoomIndex from './rechargingRoom/RechargingRoomIndex';

const ReservationIndex = () => {
interface ReservationIndexProps {
initialTab: string;
}

const ReservationIndex: React.FC<ReservationIndexProps> = ({ initialTab }) => {
const [currentRoom, setCurrentRoom] = useState('meeting');

useEffect(() => {
if (initialTab) {
const tabMapping: { [key: string]: string } = {
meetingRoom: 'meeting',
rechargingRoom: 'recharging',
focusZone: 'focus'
};
setCurrentRoom(tabMapping[initialTab] || 'meeting');
}
}, [initialTab]);

return (
<div className="mt-[80px] mb-[100px] ">
{/* 현재 지정된 오피스 */}
Expand Down
Loading

0 comments on commit f8f32f9

Please sign in to comment.