Skip to content

Commit

Permalink
[FE][Feat] : Merge Frontend Branch
Browse files Browse the repository at this point in the history
  • Loading branch information
effozen committed Nov 26, 2024
2 parents 3da9bb5 + b3f79c1 commit 67e7de7
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 85 deletions.
10 changes: 7 additions & 3 deletions frontend/src/api/dto/auth.dto.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
export class LoginResEntity {
token: string | undefined;

userId: string | undefined;
data: {
token: string | undefined;
userId: string | undefined;
} = {
token: undefined,
userId: undefined,
};
}

export class RegisterResEntity {
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/api/dto/channel.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export class channelListEntity {
name: string | undefined;

generated_at: string | undefined;

guest_count: number | undefined;
}

export class getUserChannelsResEntity {
Expand Down
24 changes: 16 additions & 8 deletions frontend/src/component/authmodal/AuthModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const AuthModal = (props: IAuthModalProps) => {
});

const [modalType, setModalType] = useState<'login' | 'register'>(props.type);
const [error, setError] = useState('');

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
Expand All @@ -46,42 +47,46 @@ export const AuthModal = (props: IAuthModalProps) => {
};

const switchToRegister = () => {
setError('');
setModalType('register');
};

const switchToLogin = () => {
setError('');
setModalType('login');
};

const handleLoginClick = () => {
doLogin(loginData.id, loginData.pw)
.then(el => {
if (el.data?.token && el.data?.userId) {
saveLocalData(AppConfig.KEYS.LOGIN_TOKEN, el.data.token);
saveLocalData(AppConfig.KEYS.LOGIN_USER, el.data.userId);
if (el.data?.data.token && el.data?.data.userId) {
saveLocalData(AppConfig.KEYS.LOGIN_TOKEN, el.data?.data.token);
saveLocalData(AppConfig.KEYS.LOGIN_USER, el.data?.data.userId);
}
setError('');
props.onClose();

window.location.reload();
})
.catch(() => {
alert('์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•ด์ฃผ์„ธ์š”.');
setError('์•„์ด๋”” ํ˜น์€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋‹ค์‹œ ํ™•์ธํ•ด์ฃผ์„ธ์š”.');
});
};

const handleSignUpClick = () => {
if (registerData.pw !== registerData.confirmPw) {
alert('๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.');
setError('๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.');
return;
}
doRegister(registerData.id, registerData.name, registerData.pw, registerData.email)
.then(el => {
if (el.data) {
alert('ํšŒ์›๊ฐ€์ž…์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ์ธํ•ด์ฃผ์„ธ์š”.');
switchToLogin();
}
})
.catch(() => {
alert(
'ํšŒ์›๊ฐ€์ž…์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ™•์ธํ•ด์ฃผ์„ธ์š”.\nid๋Š” 4์ž ์ด์ƒ, ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 6์ž๋ฆฌ ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.',
setError(
`ํšŒ์›๊ฐ€์ž…์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ํ™•์ธํ•ด์ฃผ์„ธ์š”.\nid๋Š” 4์ž ์ด์ƒ, ๋น„๋ฐ€๋ฒˆํ˜ธ๋Š” 6์ž๋ฆฌ ์ด์ƒ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.`,
);
});
};
Expand All @@ -105,6 +110,7 @@ export const AuthModal = (props: IAuthModalProps) => {
value={loginData.pw}
onChange={handleChange}
/>
{error ? <p className="pt-2 text-sm font-normal text-red-500">{error}</p> : ''}
<Modal.Footer
text="๋กœ๊ทธ์ธ"
onClick={handleLoginClick}
Expand Down Expand Up @@ -150,6 +156,8 @@ export const AuthModal = (props: IAuthModalProps) => {
value={registerData.confirmPw}
onChange={handleChange}
/>
{error ? <p className="pt-2 text-sm font-normal text-red-500">{error}</p> : ''}

<Modal.Footer
text="ํšŒ์›๊ฐ€์ž…"
onClick={handleSignUpClick}
Expand Down
101 changes: 67 additions & 34 deletions frontend/src/component/bottomsheet/BottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,86 @@
import React from 'react';
import { useBottomSheet } from '@/hooks/useBottomSheet';
import React, { useState, useRef } from 'react';

interface IBottomSheetProps {
minHeight: number;
maxHeight: number;
backgroundColor: string;
children: React.ReactNode;
}

/**
* `BottomSheet` ์ปดํฌ๋„ŒํŠธ๋Š” ํ•˜๋‹จ์—์„œ ์˜ฌ๋ผ์˜ค๋Š” ์‹œํŠธ ํ˜•ํƒœ์˜ UI๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
*
* @param {IBottomSheetProps} props - `children`์„ ํฌํ•จํ•œ ์ปดํฌ๋„ŒํŠธ ์†์„ฑ
* @param {number} props.minHeight - Bottom Sheet์˜ ์ตœ์†Œ ๋†’์ด๋ฅผ ํ™”๋ฉด ๋น„์œจ๋กœ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค (0.0 - 1.0).
* @param {number} props.maxHeight - Bottom Sheet์˜ ์ตœ๋Œ€ ๋†’์ด๋ฅผ ํ™”๋ฉด ๋น„์œจ๋กœ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค (0.0 - 1.0).
* @param {ReactNode} props.children - Bottom Sheet ๋‚ด๋ถ€์— ๋ Œ๋”๋งํ•  ์ฝ˜ํ…์ธ ์ž…๋‹ˆ๋‹ค.
* @returns {ReactNode} - ํ•˜๋‹จ ์‹œํŠธ๋ฅผ ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
*
* @remarks
* - ๋“œ๋ž˜๊ทธ ๋™์ž‘์„ ํ†ตํ•ด ์‹œํŠธ๋ฅผ ์—ด๊ณ  ๋‹ซ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
* - `useBottomSheet` ํ›…์„ ์‚ฌ์šฉํ•˜์—ฌ ์œ„์น˜ ๋ฐ ๋“œ๋ž˜๊ทธ ๋™์ž‘์„ ๊ด€๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
* - `minHeight`๋Š” Bottom Sheet๊ฐ€ ๋‹ซํžŒ ์ƒํƒœ์˜ ๋†’์ด ๋น„์œจ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
* - `maxHeight`๋Š” Bottom Sheet๊ฐ€ ์—ด๋ฆฐ ์ƒํƒœ์˜ ์ตœ๋Œ€ ๋†’์ด ๋น„์œจ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
*
* @example
* ```tsx
* <BottomSheet minHeight={0.5} maxHeight={0.85}>
* <div className="p-4">
* <h2>์˜ˆ์‹œ ์ฝ˜ํ…์ธ </h2>
* <p>BottomSheet์˜ children</p>
* </div>
* </BottomSheet>
* ```
*/

export const BottomSheet = (props: IBottomSheetProps) => {
const { sheet } = useBottomSheet({ minHeight: props.minHeight, maxHeight: props.maxHeight });
export const BottomSheet = ({
minHeight,
maxHeight,
backgroundColor,
children,
}: IBottomSheetProps) => {
const [sheetHeight, setSheetHeight] = useState(minHeight);
const startY = useRef(0);
const startHeight = useRef(minHeight);

const handleStart = (y: number) => {
startY.current = y;
startHeight.current = sheetHeight;
};

const handleMove = (y: number) => {
const deltaY = startY.current - y;
const newHeight = startHeight.current + deltaY / window.innerHeight;
setSheetHeight(Math.max(minHeight, Math.min(maxHeight, newHeight)));
};

const handleTouchStart = (e: React.TouchEvent) => {
handleStart(e.touches[0].clientY);
};

const handleTouchMove = (e: React.TouchEvent) => {
handleMove(e.touches[0].clientY);
};

const handleMouseMove = (e: MouseEvent) => {
handleMove(e.clientY);
};

const handleMouseUp = () => {
window.removeEventListener('mousemove', handleMouseMove);
window.removeEventListener('mouseup', handleMouseUp);
};

const handleMouseDown = (e: React.MouseEvent) => {
handleStart(e.clientY);
window.addEventListener('mousemove', handleMouseMove);
window.addEventListener('mouseup', handleMouseUp);
};

const handleClose = () => {
setSheetHeight(minHeight);
};

return (
<div
ref={sheet}
className="bg-grayscale-25 shadow-dark fixed left-0 right-0 z-[1000] flex h-full flex-col rounded-t-lg transition-transform duration-700"
className="fixed bottom-0 left-0 right-0 z-50 rounded-t-2xl bg-white shadow-lg transition-transform duration-700 ease-out"
style={{
top: `calc(100% - ${props.minHeight * 100}%)`,
backgroundColor: `${backgroundColor}`,
height: `${sheetHeight * 100}vh`,
transform: `translateY(${(1 - sheetHeight) * 100}%)`,
}}
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onMouseDown={handleMouseDown}
>
<div className="flex items-center justify-center pb-1 pt-2">
<div className="h-1.5 w-12 rounded-full bg-gray-300" />
</div>
{props.children}
<div className="flex items-center justify-end pb-1 pr-5 pt-2">
<button
type="button"
className="bg-grayscale-180 h-[30px] w-[30px] rounded-full text-lg font-semibold text-gray-500"
onClick={handleClose}
>
<p className="text-grayscale-850">โœ•</p>
</button>
</div>

<div className="h-full overflow-auto">{children}</div>
</div>
);
};
17 changes: 14 additions & 3 deletions frontend/src/component/content/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { useNavigate } from 'react-router-dom';

interface IContentProps {
title: string;
time: string;
person: number;
link: string;
time: string;
}

/**
Expand All @@ -30,6 +30,16 @@ interface IContentProps {
*/

export const Content = (props: IContentProps) => {
const formattedDate = new Date(props.time).toLocaleDateString('ko-KR', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
});

const formattedTime = new Date(props.time).toLocaleTimeString('ko-KR', {
hour: '2-digit',
minute: '2-digit',
});
const navigate = useNavigate();
return (
<div
Expand All @@ -41,8 +51,9 @@ export const Content = (props: IContentProps) => {
<div>
<header className="border-gray-200 pb-1 text-lg">{props.title}</header>
<section className="flex items-center text-sm leading-5 text-gray-500">
<time className="mr-4">์‹œ๊ฐ„</time>
<span className="mr-6">{props.time}</span>
<time className="mr-4">
{formattedDate} {formattedTime}
</time>
{props.person > 0 && (
<>
<MdGroup className="mr-2 h-5 w-5" aria-label="์ธ์›์ˆ˜ ์•„์ด์ฝ˜" />
Expand Down
Loading

0 comments on commit 67e7de7

Please sign in to comment.