Skip to content

Commit

Permalink
Merge pull request #24 from 4bujak-4bujak/feature/office
Browse files Browse the repository at this point in the history
feat: 지점 설정 기능
  • Loading branch information
jiohjung98 authored May 31, 2024
2 parents 74151cd + 3b2e849 commit 4f7a5f1
Show file tree
Hide file tree
Showing 9 changed files with 292 additions and 18 deletions.
39 changes: 39 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"react-id-swiper": "^4.0.0",
"react-markdown": "^9.0.1",
"react-query": "^3.39.3",
"react-router-dom": "^6.23.1",
"react-toastify": "^10.0.5",
"remark-gfm": "^4.0.0",
"swiper": "^11.1.3",
Expand Down
50 changes: 36 additions & 14 deletions src/components/home/CurrentOffice.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,50 @@
'use client';
import React from 'react';
import React, { useState, useEffect } from 'react';
import SearchModal from './SearchModal';
import SelectOfficeMap from './SelectOfficeMap';
import { Branch } from '@/api/types/branch';
import { useBranchStore } from '@/store/branch.store';

const CurrentOffice = () => {
const [showSearchModal, setShowSearchModal] = useState(false);
const [showSelectOfficeMap, setShowSelectOfficeMap] = useState(false);
const selectedBranch = useBranchStore((state) => state.selectedBranch);
const setSelectedBranch = useBranchStore((state) => state.setSelectedBranch);

const handleBranchSelect = (branch: Branch) => {
setSelectedBranch(branch);
setShowSearchModal(false);
setShowSelectOfficeMap(true);
};

const handleSearchClick = () => {
setShowSearchModal(true);
};

const handleCloseSelectOfficeMap = () => {
setShowSelectOfficeMap(false);
};

useEffect(() => {
console.log('Selected Branch Updated:', selectedBranch);
}, [selectedBranch]);

return (
<>
<div className="flex items-center gap-[10px] mt-6 relative">
<div className="flex items-center gap-[10px] mt-6 relative">
<div className="text-white text-lg font-extralight">지금 이용중인 곳은</div>
<div className="flex items-center justify-center gap-1">
<div>
<img src="/home/location.svg" alt="" />
</div>
<div className="text-white text-lg underline font-medium">강남1호점</div>

{/* 현재 선택 지점과 이용중인 지점이 다를 때 */}
{/* <div className="absolute right-[80px] top-[25px] z-50">
<div className="ml-4">
<img src="/home/isRight.svg" alt="" />
</div>
<div className="bg-space-purple-dark-active text-white text-sm font-normal p-2 rounded">
이 지점이 맞나요?
</div>
</div> */}
<div className="text-white text-lg underline font-medium cursor-pointer" onClick={handleSearchClick}>
{selectedBranch ? selectedBranch.branchName : '지점을 설정해주세요'}
</div>
</div>
</div>
{showSearchModal && <SearchModal onClose={() => setShowSearchModal(false)} onBranchSelect={handleBranchSelect} />}
{showSelectOfficeMap && selectedBranch && (
<SelectOfficeMap branch={selectedBranch} onClose={handleCloseSelectOfficeMap} />
)}
</>
);
};
Expand Down
91 changes: 91 additions & 0 deletions src/components/home/SearchModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React, { useState, useEffect, useRef } from 'react';
import { Branch } from '@/api/types/branch';
import Image from 'next/image';
import { getBranchInfo } from '@/api/map/getOffice';
import SelectOfficeMap from './SelectOfficeMap';

interface SearchModalProps {
onClose: () => void;
// eslint-disable-next-line no-unused-vars
onBranchSelect: (branch: Branch) => void;
}

const SearchModal: React.FC<SearchModalProps> = ({ onClose, onBranchSelect }) => {
const [searchTerm, setSearchTerm] = useState('');
const [allBranches, setAllBranches] = useState<Branch[]>([]);
const [selectedBranch, setSelectedBranch] = useState<Branch | null>(null);
const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);

useEffect(() => {
const fetchData = async () => {
try {
const data = await getBranchInfo();
const branchInfo = data.data;
const branchesArray = Array.isArray(branchInfo) ? branchInfo : [];
setAllBranches(branchesArray);
} catch (error) {
console.error('Error fetching branch info:', error);
}
};

fetchData();
}, []);

const filteredResults = allBranches.filter(branch => branch.branchName.includes(searchTerm));

const handleItemClick = (branch: Branch) => {
setSelectedBranch(branch);
onBranchSelect(branch);
};

return (
<div className='fixed inset-0 flex justify-center items-center'>
<section className="w-[393px] mx-auto h-full bg-white" style={{ zIndex: '101' }}>
<div className="relative p-4">
<input
type="text"
placeholder="지점을 검색해보세요."
className="w-full p-3 shadow-lg pl-10 rounded-lg"
style={{ backgroundColor: '#F0F0F0' }}
value={searchTerm}
onChange={e => setSearchTerm(e.target.value)}
ref={inputRef}
/>
<img
src="/map/Search.png"
alt="Search Icon"
className="absolute left-7 top-1/2 transform -translate-y-1/2 w-5 h-5"
/>
<button onClick={onClose} className="absolute top-7 right-8">
X
</button>
</div>
{searchTerm && (
<div className="p-4">
{filteredResults.length === 0 ? (
<p className="text-gray-500">검색 결과가 없습니다.</p>
) : (
<ul className="divide-y divide-gray-200">
{filteredResults.map(branch => (
<li key={branch.branchName} className="flex items-center py-4 cursor-pointer hover:bg-gray-100" onClick={() => handleItemClick(branch)}>
<Image src="/map/OfficeLocationSmall1.svg" alt="Location" width={12} height={16} className="mr-4" />
<span>{branch.branchName}</span>
</li>
))}
</ul>
)}
</div>
)}
</section>
{selectedBranch && <SelectOfficeMap branch={selectedBranch} onClose={onClose} />}
</div>
);
};

export default SearchModal;
98 changes: 98 additions & 0 deletions src/components/home/SelectOfficeMap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { useEffect, useRef } from 'react';
import { Branch } from '@/api/types/branch';
import Image from 'next/image';
import { useBranchStore } from '@/store/branch.store';

interface SelectOfficeMapProps {
branch: Branch;
onClose: () => void;
}

const SelectOfficeMap: React.FC<SelectOfficeMapProps> = ({ branch, onClose }) => {
const mapRef = useRef<HTMLDivElement>(null);
const setSelectedBranch = useBranchStore((state) => state.setSelectedBranch);

const handleBranchSelection = () => {
setSelectedBranch(branch);
onClose();
};

useEffect(() => {
const { naver } = window;
if (naver && branch) {
const mapOptions = {
center: new naver.maps.LatLng(branch.branchLatitude, branch.branchLongitude),
zoom: 16,
};
const map = new naver.maps.Map(mapRef.current!, mapOptions);

new naver.maps.Marker({
position: new naver.maps.LatLng(branch.branchLatitude, branch.branchLongitude),
map,
icon: {
url: '/map/OfficeActive.svg',
size: new naver.maps.Size(48, 48),
scaledSize: new naver.maps.Size(48, 48),
origin: new naver.maps.Point(0, 0),
anchor: new naver.maps.Point(24, 24),
},
});
}
}, [branch]);

useEffect(() => {
console.log('branch', branch);
}, [branch]);

return (
<div className="fixed inset-0 bg-white z-50 flex items-center justify-center">
<div ref={mapRef} className="w-[393px] mx-auto h-full" />
<div className="absolute top-4 right-4">
<aside className="w-[373px] mx-auto fixed bottom-[85px] left-0 right-0 z-50">
<div className="bg-white px-4 py-6 rounded-lg shadow-lg">
<div className='flex'>
<div className="flex-shrink-0 w-[88px] h-[88px] bg-gray-300 rounded-md">
<Image
src="/map/OfficeDefaultImg.png"
alt="Office"
width={88}
height={88}
className="object-cover rounded-md w-full h-full"
/>
</div>
<div className='ml-4 flex-1'>
<h2 className="text-xl font-semibold">{branch.branchName}</h2>
{branch.branchAddress && branch.branchLatitude && branch.branchLongitude && (
<div className="flex items-start">
<Image src="/map/OfficeLocationSmall1.svg" alt="Location" width={12} height={16} className="mt-[4px] mr-2" />
<p className="text-sm break-words">{branch.branchAddress}</p>
</div>
)}
<div className="flex">
<Image src="/map/OfficeInfo.svg" alt="Location" width={12} height={12} className="mr-2" />
<p className="text-sm break-words">회의실 43개 중 현재 22개 사용중</p>
</div>
</div>
</div>
<div className="flex w-full pt-[25px]">
<button
className="flex w-[326px] h-[36px] mx-auto bg-[#EDEBF8] text-[#3B268C] px-4 py-[6px] rounded-md justify-center items-center gap-2"
onClick={handleBranchSelection}
>
지점 설정
</button>
</div>
</div>
</aside>
<button
onClick={onClose}
className="absolute top-4 right-4 w-8 h-8 rounded-full bg-white text-black flex items-center justify-center"
>
X
</button>
</div>
</div>
);
};

export default SelectOfficeMap;
2 changes: 1 addition & 1 deletion src/components/map/OfficeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const OfficeModal: React.FC<ModalProps> = ({ isOpen, onClose, branchName, branch
};

return (
<aside className="w-[373px] mx-auto fixed bottom-[20px] left-0 right-0 z-50">
<aside className="w-[373px] mx-auto fixed bottom-[85px] left-0 right-0 z-50">
<div ref={modalRef} className="bg-white px-4 py-6 rounded-lg shadow-lg">
<div className='flex'>
<div className="flex-shrink-0 w-[88px] h-[88px] bg-gray-300 rounded-md">
Expand Down
6 changes: 3 additions & 3 deletions src/components/map/UseMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,11 @@ const UseMap: React.FC = () => {
<div ref={mapRef} className="w-full h-full" />
{showMessage && (
<>
<div className={`absolute ${isModalOpen ? 'bottom-[285px]' : 'bottom-[110px]'} left-4 bg-white px-3 py-3.5 shadow-lg flex items-center`}>
<div className={`absolute ${isModalOpen ? 'bottom-[355px]' : 'bottom-[180px]'} left-4 bg-white px-3 py-3.5 shadow-lg flex items-center`}>
<span>더 정확한 접속위치를 확인해보세요!</span>
<button id="current-location-text" onClick={handleCurrentLocationTextClick} className="ml-4">X</button>
</div>
<Image src='/map/triangle.svg' alt="Current Location" className={`absolute ${isModalOpen ? 'bottom-[275px]' : 'bottom-[100px]'} left-[40px]`} width={18} height={10} />
<Image src='/map/triangle.svg' alt="Current Location" className={`absolute ${isModalOpen ? 'bottom-[345px]' : 'bottom-[170px]'} left-[40px]`} width={18} height={10} />
</>
)}
<MapSearchBar onFocus={() => setShowSearchResults(true)} onChange={handleSearchQueryChange} />
Expand All @@ -218,7 +218,7 @@ const UseMap: React.FC = () => {
/>
<button
id="current-location-button"
className={`absolute ${isModalOpen ? 'bottom-[210px]' : 'bottom-[35px]'} left-4 p-2 flex items-center justify-center`}
className={`absolute ${isModalOpen ? 'bottom-[280px]' : 'bottom-[105px]'} left-4 p-2 flex items-center justify-center`}
onMouseEnter={() => setImageSrc('/map/MapLocationActive.png')}
onMouseLeave={() => setImageSrc('/map/MapLocation.png')}
onClick={handleCurrentLocationClick}
Expand Down
2 changes: 2 additions & 0 deletions src/pages/map/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import MainContainer from '@/components/shared/MainContainer';
import UseMap from '@/components/map/UseMap';
import Footer from '@/components/footer/Footer';

const MapPage = () => {
return (
<MainContainer>
<div className="flex flex-col justify-center items-center gap-[39px] h-screen">
<div className="w-full h-full">
<UseMap />
<Footer/>
</div>
</div>
</MainContainer>
Expand Down
21 changes: 21 additions & 0 deletions src/store/branch.store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/* eslint-disable no-unused-vars */
import { create } from 'zustand';
import { Branch } from '@/api/types/branch';
import { persist } from 'zustand/middleware';

interface BranchStore {
selectedBranch: Branch | null;
setSelectedBranch: (branch: Branch | null) => void;
}

export const useBranchStore = create(
persist<BranchStore>(
(set) => ({
selectedBranch: null,
setSelectedBranch: (branch: Branch | null) => set({ selectedBranch: branch }),
}),
{
name: 'selectedBranch'
}
)
);

0 comments on commit 4f7a5f1

Please sign in to comment.