Skip to content

Commit

Permalink
[Feat/#31] merge 후 수정사항 (#34)
Browse files Browse the repository at this point in the history
* fix: 주소 복사 알림창 크기 수정

* fix: 결제 금액 단위 표시

* fix:스크롤 맨 위로 이동, 이미지 첨부 후 버튼 활성화

* fix: 모달 데이터 스크롤바 추가, 불필요한 파일 삭제

* design: QR 스캔 버튼 위치 수정

* fix: QR 생성 버튼 한 계좌만 나오도록
  • Loading branch information
alswlfl29 authored Jul 2, 2024
1 parent caaed26 commit 9090b64
Show file tree
Hide file tree
Showing 17 changed files with 217 additions and 121 deletions.
Binary file added public/images/hanaMain/bankbook.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Outlet } from 'react-router-dom';
import './App.css';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ScrollToTop } from './utils/scrollToTop';

const queryClient = new QueryClient({
defaultOptions: {
Expand All @@ -13,6 +14,7 @@ const queryClient = new QueryClient({
function App() {
return (
<>
<ScrollToTop />
<QueryClientProvider client={queryClient}>
<Outlet />
</QueryClientProvider>
Expand Down
1 change: 0 additions & 1 deletion src/components/common/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ const navbarItems = [

export const Navbar = () => {
const location = useLocation();
console.log(location);

return (
<>
Expand Down
6 changes: 3 additions & 3 deletions src/components/molecules/Alarm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ export const Alarm: FC<IProps> = ({ message, showAlarm, onClickShowAlarm }) => {
} else {
timer = setTimeout(() => {
onClickShowAlarm(false);
}, 2000);
}, 1000);
}
return () => {
clearTimeout(timer);
};
}, [showAlarm]);
}, [activeAnimation]);

return (
<div
className={`fixed mx-4 w-[90%] py-2 bg-[#D9E8E6] text-black/70 rounded-xl font-hanaMedium text-center ${activeAnimation ? 'animate-slidedown' : 'animate-slideup'}`}
className={`fixed mx-4 max-w-[351px] w-[90%] py-2 bg-[#D9E8E6] text-black/70 rounded-xl font-hanaMedium text-center ${activeAnimation ? 'animate-slidedown' : 'animate-slideup'}`}
>
{message}
</div>
Expand Down
Empty file removed src/components/molecules/Ex.tsx
Empty file.
2 changes: 1 addition & 1 deletion src/components/molecules/HanaMainCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const HanaMainCard: FC<IProps> = ({ id, Icon, message, color }) => {
<div
className='w-32 h-40 flex flex-col bg-white rounded-2xl cursor-pointer py-5 px-3.5 drop-shadow-[1px_3px_4px_rgba(0,0,0,0.1)]'
onClick={() => {
id === 2 ? navigate('/') : undefined;
id === 2 ? navigate('/login') : undefined;
}}
>
<Icon
Expand Down
54 changes: 29 additions & 25 deletions src/components/molecules/LessonDateChoice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,32 +69,36 @@ export const LessonDateChoice: FC<IProps> = ({ dateList, price }) => {
<div className='w-[95%] border-2 border-black rounded'>
<h2 className='py-4 px-4 font-hanaMedium text-base bg-[#FAFAFA]'>
일정 선택
</h2>
{dateList.map((date, index) => (
<div key={date.lessondate_id}>
<div
className='px-4 py-4 flex flex-col justify-center gap-1 cursor-pointer'
onClick={() =>
clickedChoiceDate(
date.lessondate_id,
formatDate(date.date, date.start_time, date.end_time),
date.quantityLeft
)
}
>
<p className='font-hanaRegular text-sm'>
{formatDate(date.date, date.start_time, date.end_time)}
</p>
<p className='flex items-end gap-1 font-hanaBold text-sm'>
{price.toLocaleString()}
<span className='font-hanaMedium text-xs text-hanaNavGray'>
{date.quantityLeft}개 남음
</span>
</p>
</h2>{' '}
<div className='max-h-56 overflow-y-scroll'>
{dateList.map((date, index) => (
<div key={date.lessondate_id}>
<div
className='px-4 py-4 flex flex-col justify-center gap-1 cursor-pointer'
onClick={() =>
clickedChoiceDate(
date.lessondate_id,
formatDate(date.date, date.start_time, date.end_time),
date.quantityLeft
)
}
>
<p className='font-hanaRegular text-sm'>
{formatDate(date.date, date.start_time, date.end_time)}
</p>
<p className='flex items-end gap-1 font-hanaBold text-sm'>
{price.toLocaleString()}
<span className='font-hanaMedium text-xs text-hanaNavGray'>
{date.quantityLeft}개 남음
</span>
</p>
</div>
{index !== dateList.length && (
<hr className='border-[#EEEEEC]' />
)}
</div>
{index !== dateList.length && <hr className='border-[#EEEEEC]' />}
</div>
))}
))}
</div>
</div>
{choiceDate && (
<div className='w-[95%] p-3 mt-8 bg-[#FAFAFA] border-[1px] border-hanaSilver rounded'>
Expand Down
87 changes: 57 additions & 30 deletions src/components/molecules/QR.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import QRCode from 'qrcode.react';
import { FC, useState } from 'react';
import { QRScanner } from './QRScanner';
import { FC, useEffect, useState } from 'react';
import { ModalBottomContainer } from '../organisms/ModalBottomContainer';
import { useTimer } from '../../hooks/useTimer';
import { VscDebugRestart } from 'react-icons/vsc';

interface IProps {
userId: number;
Expand All @@ -18,41 +19,67 @@ export const QR: FC<IProps> = ({
balance,
onClose,
}) => {
console.log(userId, accountId, accountNumber, balance);
const [isScan, setIsScan] = useState(false);
const [isTimeout, setIsTimeout] = useState<boolean>(false);
const [qrValue, setQrValue] = useState<string>('');
const [minute, second, resetTimer] = useTimer();

useEffect(() => {
setQrValue(
JSON.stringify({
userId,
accountId,
accountNumber,
balance,
})
);
}, [userId, accountId, accountNumber, balance]);

const handleReset = () => {
setQrValue(
JSON.stringify({
userId,
accountId,
accountNumber,
balance,
})
);
resetTimer();
setIsTimeout(false);
};

useEffect(() => {
if (minute === '00' && second === '00') setIsTimeout(true);
}, [minute, second]);

return (
<ModalBottomContainer onClose={onClose} color='#FFFFFF'>
<div
className='mt-12 mb-8 bg-[#D9D9D9] w-52 rounded-[2rem] px-2 py-1 flex justify-center items-center gap-2'
onClick={() => setIsScan(!isScan)}
>
<p
className={`h-10 w-1/2 rounded-[2rem] flex justify-center items-center text-sm font-hanaBold transition-all duration-200 ease-in ${isScan ? 'text-black/50 bg-transparent' : 'text-black bg-white drop-shadow-[0_2px_2px_rgba(0,0,0,0.25)]'}`}
>
QR코드
</p>
<p
className={`h-10 w-1/2 rounded-[2rem] flex justify-center items-center text-sm font-hanaBold transition-all duration-200 ease-in ${isScan ? 'text-black bg-white drop-shadow-[0_2px_2px_rgba(0,0,0,0.25)]' : 'text-black/50 bg-transparent'}`}
>
QR스캔
</p>
</div>
{isScan ? (
<QRScanner onClose={() => setIsScan(false)} />
) : (
<div className='w-80 h-80 border-2 border-hanaSilver rounded-3xl overflow-hidden flex justify-center items-center mb-20'>
<div className='relative flex flex-col w-80 h-80 justify-between items-center mt-16 mb-12'>
<div className='w-72 h-72 flex justify-center items-center rounded-lg border border-hanaSilver p-8'>
<QRCode
value={JSON.stringify({
userId,
accountId,
accountNumber,
balance,
})}
value={qrValue}
size={220}
fgColor={!isTimeout ? 'black' : 'gray'}
/>
</div>
)}
{isTimeout && (
<button
className='absolute mt-32 flex justify-center items-center gap-2 bg-hanaGreen w-10/12 rounded-2xl text-white font-hanaMedium py-1.5'
onClick={handleReset}
>
QR 다시 생성하기
<VscDebugRestart size={18} />
</button>
)}
<div className='flex justify-center items-center font-hanaRegular text-lg mt-5'>
{minute}:{second}
<p
className='absolute right-5 rounded-full border border-hanaSilver p-1 cursor-pointer'
onClick={handleReset}
>
<VscDebugRestart size={18} />
</p>
</div>
</div>
</ModalBottomContainer>
);
};
Empty file removed src/components/organisms/Ex.tsx
Empty file.
Empty file removed src/hooks/ex.ts
Empty file.
24 changes: 24 additions & 0 deletions src/hooks/useTimer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useEffect, useState } from 'react';

export const useTimer = (initialTime: number = 60 * 1000) => {
const [time, setTime] = useState<number>(initialTime);
const minute = String(Math.floor((time / (1000 * 60)) % 60)).padStart(2, '0');
const second = String(Math.floor((time / 1000) % 60)).padStart(2, '0');

const resetTimer = () => {
setTime(initialTime);
};

useEffect(() => {
const timer = setInterval(() => {
setTime((prevTime) => prevTime - 1000);
}, 1000);

if (time <= 0) {
clearInterval(timer);
}
return () => clearInterval(timer);
}, [time]);

return [minute, second, resetTimer] as const;
};
2 changes: 1 addition & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const router = createBrowserRouter([
path: '/',
element: <App />,
children: [
{ path: '/main', element: <HanaMain /> },
{ path: '/hana', element: <HanaMain /> },
{ path: '/login', element: <Login /> },
{ path: '/qr-pay', element: <QRPay /> },
{ path: '/open-lesson/host', element: <RegisterHost /> },
Expand Down
72 changes: 49 additions & 23 deletions src/pages/main/HanaFunMain.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useEffect, useState } from 'react';
import { GoKebabHorizontal } from 'react-icons/go';
import DropdownSingle from '../../components/common/DropdownSingle';
import { InfoCard } from '../../components/molecules/InfoCard';
Expand All @@ -14,6 +14,9 @@ import { QR } from '../../components/molecules/QR';
import { AccountType } from '../../components/organisms/ChoiceAccount';
import { RiQrScan2Line } from 'react-icons/ri';
import { Lessondata } from '../search/LessonSearch';
import { getCookie } from '../../utils/cookie';
import { useNavigate } from 'react-router-dom';
import { QRScanner } from '../../components/molecules/QRScanner';

export const userDummyData = {
userId: 1,
Expand Down Expand Up @@ -61,9 +64,11 @@ const infoCardSliderSettings = {
};

export const HanaFunMain = () => {
const [showDropdown, setShowDropdown] = useState<boolean>(false);
const navigate = useNavigate();
const [showKeypad, setShowKeypad] = useState<boolean>(false);
const [showQr, setShowQr] = useState<boolean>(false);
const [isScan, setIsScan] = useState(false);
const [active, setActive] = useState<number | null>(null);

const [selectedAccount, setSelectedAccount] = useState<AccountType>({
accountId: -1,
Expand All @@ -76,12 +81,12 @@ export const HanaFunMain = () => {
console.log('비밀번호>>', password);
console.log('로그인');
setShowKeypad(false);
setShowDropdown(false);
setActive(null);
setShowQr(true);
};

const clickedAccount = (account: AccountType) => {
setShowDropdown((showDropdown) => !showDropdown);
const clickedAccount = (account: AccountType, index: number) => {
handleModalOpen(index);
setSelectedAccount({
accountId: account.accountId,
accountNumber: account.accountNumber,
Expand All @@ -90,14 +95,38 @@ export const HanaFunMain = () => {
});
};

const handleModalOpen = (index: number) => {
setActive(active === index ? null : index);
};

// useEffect(() => {
// const token = getCookie('token');
// if (!token) navigate('/hana');
// }, []);

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
const target = event.target as HTMLElement;
if (!target.closest('.lesson-card') && active !== null) {
setActive(null);
}
};

document.addEventListener('click', handleClickOutside);
return () => {
document.removeEventListener('click', handleClickOutside);
};
}, [active]);

return (
<>
{isScan && <QRScanner onClose={() => setIsScan(false)} />}
{showKeypad && (
<AccountPwKeypad
handleClickedPassword={(pw: string) => sendAccountPassword(pw)}
onClose={() => {
setShowKeypad(false);
setShowDropdown(false);
setActive(null);
}}
/>
)}
Expand All @@ -110,41 +139,38 @@ export const HanaFunMain = () => {
onClose={() => setShowQr(false)}
/>
)}
<div className='pt-5 px-5 mb-32'>
<div className='flex items-end justify-between'>
<p className='flex items-end font-hanaBold text-2xl'>
<img src='/images/logo.svg' alt='logo' className='w-12 mr-2' />
하나
<span className='text-xl text-hanaGreen'>F</span>
<span className='text-xl text-hanaRed'>u</span>
<span className='text-xl text-hanaGold'>n</span>!
</p>
<div className='pt-8 px-5 mb-32'>
<div className='flex items-center justify-between'>
<p className='font-hanaBold text-xl text-hanaGreen'>
{userDummyData.name} <span className='text-black'></span>
</p>
<button
className='flex justify-center items-center font-hanaMedium gap-1.5 text-base text-black/80'
onClick={() => setIsScan(true)}
>
<RiQrScan2Line size={20} />
QR스캔
</button>
</div>
{/* <button className='mt-6 flex justify-center items-center w-full bg-hanaNavGreen rounded-2xl py-2 font-hanaMedium gap-1.5 text-white'>
<RiQrScan2Line size={20} />
QR 스캔
</button> */}

<div className='mt-6 flex items-center justify-center'>
<Slide settings={accountSliderSettings} cssName='custom-slider'>
{userDummyData.accounts.map((account) => (
{userDummyData.accounts.map((account, index) => (
<div
key={account.accountId}
className='relative w-full bg-white rounded-2xl py-5 px-7 font-hanaBold'
>
<div className='flex items-center justify-between'>
<div className='lesson-card flex items-center justify-between'>
<span className='text-black text-lg'>
{account.accountName}
</span>
<GoKebabHorizontal
color='#B5B5B5'
size={16}
className='rotate-90 cursor-pointer'
onClick={() => clickedAccount(account)}
onClick={() => clickedAccount(account, index)}
/>
{showDropdown && (
{active === index && (
<div className='absolute right-0 mr-11'>
<DropdownSingle
image='/images/qr.svg'
Expand Down
Loading

0 comments on commit 9090b64

Please sign in to comment.