Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

6주차 4차 배포 #424

Merged
merged 31 commits into from
Dec 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a345af6
[FE][Feat] QA : title 작성 안되면 footer passive
leedongyull Dec 3, 2024
6ddb80f
[FE][Fix] #407 : Alert를 길게 눌렀을 때 로딩 멈추는 문제 해결
effozen Dec 4, 2024
d885f41
[FE][Fix] #410 : 로그인 -> 회원가입 후 닫기, 다시 로그인 창 올 시 회원가입 상태가 유지되는 문제 수정
effozen Dec 4, 2024
a884be0
[FE][Feat] #411 : 채널을 새로 만들면 바텀시트에 업데이트
juwon5272 Dec 4, 2024
a0a4b70
[FE][Fix] #411 : 한국 시간과 시간이 안 맞는 이슈 해결
juwon5272 Dec 4, 2024
5ce0fdc
[FE][Fix] #413 : 로그인 -> 회원가입 후 닫기, 다시 로그인 창 올 시 회원가입 상태가 유지되는 문제 수정
effozen Dec 4, 2024
c7a5180
[FE][Fix] #413 : 로그인, 회원가입 버튼 포커스 수정
effozen Dec 4, 2024
0c15083
Merge remote-tracking branch 'origin/feature/fe/#407-alert-error' int…
effozen Dec 4, 2024
f903fac
Merge pull request #412 from boostcampwm-2024/feature/fe/#411-bottoms…
juwon5272 Dec 4, 2024
6c09ecd
Merge pull request #414 from boostcampwm-2024/feature/fe/#407-alert-e…
happyhyep Dec 4, 2024
7a8cf90
[FE][Feat] QA : 출발지, 도착지 마커 클러스터 구현
leedongyull Dec 4, 2024
f10baa6
[FE] : Development Merge
effozen Dec 4, 2024
69b54fb
[FE][Feat] frontend merge
leedongyull Dec 4, 2024
ad7e530
[FE][Feat] #416 : 채널 삭제 로직 구현
effozen Dec 4, 2024
b01eed3
[FE][Feat] animation 대신 setInterval로 관리
leedongyull Dec 4, 2024
42889e7
[FE][Feat] frontend 머지
leedongyull Dec 4, 2024
8067ff3
[FE][Fix] vite 파일 설정 되돌리기
leedongyull Dec 4, 2024
c25dad5
Merge pull request #420 from boostcampwm-2024/feature/fe/QA
leedongyull Dec 4, 2024
d6d6dcd
[FE][Feat] QA : 검색 결과 크기 조절 및 왼쪽 정렬
leedongyull Dec 4, 2024
e097f2b
[FE][Fix] #416 : 채널 삭제 로직 재랜더링 안되는 문제 수정
effozen Dec 4, 2024
84e45c4
[FE][Feat] : zoomslider 색상 변경
juwon5272 Dec 4, 2024
94b6603
[FE][Feat] 사용자 name 입력 가능하도록 구현
leedongyull Dec 4, 2024
8a19858
[FE][Feat] Header key값 오류 해결
leedongyull Dec 4, 2024
bbfc0e6
[FE][Feat] Alert 사용자 명으로 수정
leedongyull Dec 4, 2024
b08aaea
[FE][Feat] : 경로 발자국 걷는 형태로 구현
juwon5272 Dec 4, 2024
3208330
[FE][Feat] 아이콘 변경 및 출발지 도착지 순서 변경
leedongyull Dec 4, 2024
45e7ad0
[FE][Feat] #416 : 채널 삭제 화면 구현
effozen Dec 4, 2024
86825cc
Merge branch 'frontend' into feature/fe/#411-bottomsheet-channel
juwon5272 Dec 4, 2024
3b8ecab
Merge pull request #423 from boostcampwm-2024/feature/fe/#411-bottoms…
juwon5272 Dec 4, 2024
3d7f4fe
Merge pull request #419 from boostcampwm-2024/feature/fe/#416-Channel…
effozen Dec 4, 2024
565efcf
Merge pull request #422 from boostcampwm-2024/feature/fe/QA
leedongyull Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions frontend/src/api/channel.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getChannelResEntity,
getUserChannelsResEntity,
getGuestResEntity,
deleteChannelResEntity,
} from '@/api/dto/channel.dto.ts';
import { getApiClient } from '@/api/client.api.ts';

Expand Down Expand Up @@ -136,3 +137,28 @@ export const getGuestInfo = (
};
return new Promise(promiseFn);
};

export const deleteChannel = (channelId: string): Promise<ResponseDto<deleteChannelResEntity>> => {
const promiseFn = (
fnResolve: (value: ResponseDto<deleteChannelResEntity>) => void,
fnReject: (reason?: any) => void,
) => {
const apiClient = getApiClient();
apiClient
.delete(`/channel/${channelId}`)
.then(res => {
if (res.status !== 200) {
console.error(res);
fnReject(`msg.${res}`);
} else {
fnResolve(new ResponseDto<deleteChannelResEntity>(res.data));
}
})
.catch(err => {
console.log(channelId);
console.error(err);
fnReject('msg.RESULT_FAILED');
});
};
return new Promise(promiseFn);
};
4 changes: 4 additions & 0 deletions frontend/src/api/dto/channel.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,7 @@ export class getGuestResEntity {

guest: guestEntity | undefined;
}

export class deleteChannelResEntity {
id: string | undefined;
}
6 changes: 5 additions & 1 deletion frontend/src/assets/footprint.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 5 additions & 1 deletion frontend/src/component/authmodal/AuthModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Modal } from '@/component/common/modal/Modal';
import { doLogin, doRegister } from '@/api/auth.api.ts';
import { saveLocalData } from '@/utils/common/manageLocalData.ts';
Expand Down Expand Up @@ -91,6 +91,10 @@ export const AuthModal = (props: IAuthModalProps) => {
});
};

useEffect(() => {
if (!props.isOpen) switchToLogin();
}, [props.isOpen]);

return (
<Modal isOpen={props.isOpen}>
{modalType === 'login' ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ import { ICanvasPoint, IMapCanvasViewProps, IPoint } from '@/lib/types/canvasInt
import { useCanvasInteraction } from '@/hooks/useCanvasInteraction';
import { useRedrawCanvas } from '@/hooks/useRedraw';
import { ZoomSlider } from '@/component/zoomslider/ZoomSlider';
import { ICluster, useCluster } from '@/hooks/useCluster';

export const MapCanvasForView = forwardRef<naver.maps.Map | null, IMapCanvasViewProps>(
({ lat, lng, alpha, otherLocations, guests, width, height }: IMapCanvasViewProps, ref) => {
const mapRef = useRef<HTMLDivElement>(null);
const canvasRef = useRef<HTMLCanvasElement>(null);
const [projection, setProjection] = useState<naver.maps.MapSystemProjection | null>(null);
const [map, setMap] = useState<naver.maps.Map | null>(null);
const { createClusters } = useCluster();
const [clusters, setClusters] = useState<ICluster[] | null>(null);

useImperativeHandle(ref, () => map as naver.maps.Map);

Expand Down Expand Up @@ -66,6 +69,7 @@ export const MapCanvasForView = forwardRef<naver.maps.Map | null, IMapCanvasView
lat,
lng,
alpha,
clusters,
});

const {
Expand Down Expand Up @@ -95,9 +99,33 @@ export const MapCanvasForView = forwardRef<naver.maps.Map | null, IMapCanvasView
updateCanvasSize();
}, [map]);

// guests나 map이 변경될 때마다 클러스터를 다시 생성하고 상태를 업데이트
useEffect(() => {
const updateClusters = () => {
if (map && guests && guests.length > 0) {
const createdClusters = guests
.map(guest =>
createClusters([guest.startPoint, guest.endPoint], guest.markerStyle, map),
)
.flat();

setClusters(createdClusters);
}
};

// 컴포넌트가 처음 마운트될 때 즉시 실행
updateClusters();

const intervalId = setInterval(() => {
updateClusters();
}, 100);

return () => clearInterval(intervalId); // 컴포넌트 언마운트 시 인터벌 클리어
}, [guests, map]);

useEffect(() => {
redrawCanvas();
}, [guests, otherLocations, lat, lng, alpha, mapRef, handleWheel]);
}, [guests, otherLocations, lat, lng, alpha, clusters, handleWheel]);

return (
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { useCanvasInteraction } from '@/hooks/useCanvasInteraction';
import { ZoomSlider } from '@/component/zoomslider/ZoomSlider';
import { useRedrawCanvas } from '@/hooks/useRedraw';
import { zoomMapView } from '@/utils/map/mapUtils';
import { ICluster, useCluster } from '@/hooks/useCluster';

export const MapCanvasForDraw = ({
width,
Expand All @@ -34,6 +35,9 @@ export const MapCanvasForDraw = ({

const { setCurrentUser } = useContext(CurrentUserContext);

const { createClusters } = useCluster();
const [clusters, setClusters] = useState<ICluster[]>([]);

useEffect(() => {
const updateUser = () => {
setCurrentUser(prevUser => {
Expand Down Expand Up @@ -138,6 +142,7 @@ export const MapCanvasForDraw = ({
startMarker,
endMarker,
pathPoints,
clusters,
});

const handleCanvasClick = (e: React.MouseEvent<HTMLCanvasElement>) => {
Expand Down Expand Up @@ -238,11 +243,11 @@ export const MapCanvasForDraw = ({
}, [map]);

useEffect(() => {
if (startMarker && endMarker) {
const markers = [];

if (startMarker) markers.push(startMarker);
if (endMarker) markers.push(endMarker);
if (startMarker && endMarker && map) {
const markers = [
{ lat: startMarker.lat, lng: startMarker.lng },
{ lat: endMarker.lat, lng: endMarker.lng },
];

zoomMapView(map, markers);
} else {
Expand All @@ -257,9 +262,24 @@ export const MapCanvasForDraw = ({
}
}, [startMarker, endMarker]);

useEffect(() => {
const intervalId = setInterval(() => {
if (startMarker && endMarker && map) {
const markers = [
{ lat: startMarker.lat, lng: startMarker.lng },
{ lat: endMarker.lat, lng: endMarker.lng },
];

const createdClusters = createClusters(markers, { color: '#333C4A' }, map);
setClusters(createdClusters);
}
}, 100);

return () => clearInterval(intervalId); // 컴포넌트 언마운트 시 인터벌 클리어
}, [startMarker, endMarker, map]);
useEffect(() => {
redrawCanvas();
}, [startMarker, endMarker, pathPoints, map, undoStack, redoStack]);
}, [startMarker, endMarker, clusters, pathPoints, map, undoStack, redoStack]);

return (
<div
Expand Down
37 changes: 17 additions & 20 deletions frontend/src/component/common/alert/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,41 +8,38 @@ interface IAlertProps {
}

export const AlertUI = ({ message, duration = 3000, autoClose = true, onClose }: IAlertProps) => {
const [progress, setProgress] = useState(100);
const [animateProgress, setAnimateProgress] = useState(false);

useEffect(() => {
if (!autoClose) return;

const start = performance.now();
const timeout = setTimeout(() => {
setAnimateProgress(true);
}, 50);

const updateProgress = (current: number) => {
const elapsed = current - start;
const newProgress = Math.max(0, 100 - (elapsed / duration) * 100);
const timer = setTimeout(() => {
onClose?.();
}, duration);

setProgress(newProgress);

if (elapsed < duration) {
requestAnimationFrame(updateProgress);
} else {
onClose?.();
}
return () => {
clearTimeout(timeout);
clearTimeout(timer);
};

const animationFrame = requestAnimationFrame(updateProgress);

return () => cancelAnimationFrame(animationFrame);
}, [duration, autoClose, onClose]);

return (
<>
<div className="fixed inset-0 z-[5000] flex items-center justify-center bg-black bg-opacity-20" />
<div className="pointer-events-none fixed inset-0 z-[5000] flex items-center justify-center bg-black bg-opacity-20" />
<div className="bg-blueGray-800 absolute left-1/2 top-1/2 z-[6000] mx-auto flex w-[22rem] max-w-md -translate-x-1/2 flex-col items-center justify-center rounded-md p-6 text-white shadow-lg">
<div className="whitespace-pre text-center text-sm font-medium">{message}</div>
{autoClose ? (
<div className="bg-blueGray-800 mt-4 h-1 w-full">
<div className="bg-blueGray-800 mt-4 h-1 w-full overflow-hidden">
<div
className="h-1 rounded-full bg-white transition-all ease-linear"
style={{ width: `${progress}%` }}
className="linear transition-all` h-1 rounded-full bg-white"
style={{
width: animateProgress ? '0%' : '100%',
transitionDuration: `${duration}ms`,
}}
/>
</div>
) : (
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/component/common/modal/ModalFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const ModalFooter = (props: IModalFooterProps) => (
<div className="flex w-full flex-row-reverse items-center justify-start gap-5 rounded-lg bg-white py-4 shadow-sm">
<button
type="button"
className="bg-blueGray-800 hover:bg-blueGray-600 h-[40px] rounded-lg px-4 py-2 text-sm font-semibold text-white"
className="bg-blueGray-800 h-[40px] rounded-lg px-4 py-2 text-sm font-semibold text-white"
onClick={props.onClick}
>
{props.text}
Expand Down
15 changes: 8 additions & 7 deletions frontend/src/component/common/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FaPaintBrush } from 'react-icons/fa';
import { HiLocationMarker, HiOutlineDotsHorizontal, HiOutlineLocationMarker } from 'react-icons/hi';
import { HiLocationMarker, HiOutlineDotsHorizontal } from 'react-icons/hi';
import { SlLayers } from 'react-icons/sl';
import { RiFlag2Fill } from 'react-icons/ri';
import { ButtonState } from './enums';

/**
Expand All @@ -11,7 +12,7 @@ export const IconType = {
CLOSE: SlLayers, // 닫기 버튼 아이콘
OPEN: HiOutlineDotsHorizontal, // 열기 버튼 아이콘
START_MARKER: HiLocationMarker, // 출발지 설정 아이콘
DESTINATION_MARKER: HiOutlineLocationMarker, // 도착지 설정 아이콘
DESTINATION_MARKER: RiFlag2Fill, // 도착지 설정 아이콘
LINE_DRAWING: FaPaintBrush, // 경로 그리기 아이콘
};
/**
Expand All @@ -29,14 +30,14 @@ export const ToolCategory = [
description: '경로 그리기', // 툴 설명
icon: IconType.LINE_DRAWING, // 툴 아이콘
},
{
type: ButtonState.START_MARKER, // 출발지 설정 툴
description: '출발지 설정', // 툴 설명
icon: IconType.START_MARKER, // 툴 아이콘
},
{
type: ButtonState.DESTINATION_MARKER, // 도착지 설정 툴
description: '도착지 설정', // 툴 설명
icon: IconType.DESTINATION_MARKER, // 툴 아이콘
},
{
type: ButtonState.START_MARKER, // 출발지 설정 툴
description: '출발지 설정', // 툴 설명
icon: IconType.START_MARKER, // 툴 아이콘
},
];
45 changes: 45 additions & 0 deletions frontend/src/component/confirm/Confirm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
interface IConfirmProps {
message: string;
onConfirm: () => void;
onCancel: () => void;
type: 'confirm' | 'alert';
confirmText?: string;
cancelText?: string;
}

export const Confirm = (props: IConfirmProps) => {
return (
<div className="fixed inset-0 z-[5000] flex items-center justify-center bg-black bg-opacity-70">
<div className="absolute left-1/2 top-1/2 z-[6000] mx-auto flex w-[22rem] max-w-md -translate-x-1/2 flex-col items-center justify-center gap-6 rounded-md bg-gray-50 p-6 text-white shadow-lg">
<div className="text-blueGray-800 whitespace-pre py-2 text-center text-lg font-medium">
{props.message}
</div>
{props.type === 'alert' ? (
<div className="flex w-full items-center justify-between gap-4">
<button
className="bg-blueGray-800 w-full cursor-pointer rounded-md border-none px-2.5 py-2.5 text-sm font-medium text-white"
onClick={props.onConfirm}
>
{props.confirmText || '확인'}
</button>
</div>
) : (
<div className="flex w-full items-center justify-between gap-4">
<button
className="bg-blueGray-800 w-full cursor-pointer rounded-md border-none px-2.5 py-2.5 text-sm font-medium text-white"
onClick={props.onConfirm}
>
{props.confirmText || '확인'}
</button>
<button
className="w-full cursor-pointer rounded-md border-none bg-gray-400 px-2.5 py-2.5 text-sm font-medium text-white"
onClick={props.onCancel}
>
{props.cancelText || '취소'}
</button>
</div>
)}
</div>
</div>
);
};
Loading
Loading