Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/JMarketYard/Front-end in…
Browse files Browse the repository at this point in the history
…to feat/upload-page-#10
  • Loading branch information
devhaeun committed Jan 28, 2025
2 parents e962406 + b7cf4d2 commit dccb2e5
Show file tree
Hide file tree
Showing 45 changed files with 3,105 additions and 2 deletions.
3 changes: 2 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
Expand All @@ -8,6 +8,7 @@
</head>
<body>
<div id="root"></div>
<div id="modal-root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
"preview": "vite preview"
},
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@iconify/react": "^5.2.0",
"@mui/icons-material": "^6.4.1",
"@mui/material": "^6.4.1",
"axios": "^1.7.9",
"react": "^18.3.1",
"react-dom": "^18.3.1",
Expand Down
6 changes: 5 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import './App.css';
import { ModalContextProvider } from './components/Modal/context/ModalContext';
import Router from './routes/router';
// import SearchBox from './components/SearchBox';

function App() {
return (
<>
<Router />
<ModalContextProvider>
<Router />
</ModalContextProvider>
</>
);
}
Expand Down
Binary file added src/assets/SmileVector.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 src/assets/Vector.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 src/assets/logo.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 src/assets/questionVector.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 src/assets/sadVector.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/assets/ticket.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 src/assets/ticketLogo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 57 additions & 0 deletions src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { PropsWithChildren } from 'react';
import ReactDOM from 'react-dom';
import styled from 'styled-components';
import { Icon } from '@iconify/react';
import { useModalContext } from './context/ModalContext';

export default function Modal({
children,
onClose,
}: PropsWithChildren<{ onClose: () => void }>) {
const { clearModals } = useModalContext();

return ReactDOM.createPortal(
<ModalOverlay onClick={clearModals}>
<ModalContent
onClick={(e: React.MouseEvent<HTMLDivElement>) => e.stopPropagation}
>
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
<Icon
icon={'ei:close-o'}
style={{
width: '30px',
height: '30px',
color: '#7D7D7D',
transform: 'translateX(-14px)',
}}
onClick={onClose}
/>
</div>
<div onClick={(e) => e.stopPropagation()}>{children}</div>
</ModalContent>
</ModalOverlay>,
document.getElementById('modal-root') as HTMLElement,
);
}

const ModalOverlay = styled.div`
position: fixed;
inset: 0;
background-color: rgba(0, 0, 0, 0.3);
display: flex;
justify-content: center;
align-items: center;
z-index: 100;
`;

const ModalContent = styled.div`
display: flex;
position: relative;
width: 425px;
height: auto;
flex-direction: column;
background-color: white;
border-radius: 6px;
padding-top: 14px;
padding-bottom: 58px;
`;
60 changes: 60 additions & 0 deletions src/components/Modal/context/ModalContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {
createContext,
FunctionComponent,
ReactNode,
useCallback,
useContext,
useState,
} from 'react';

interface IModalState {
modals: FunctionComponent<{ onClose: () => void }>[];
}

type TModalAction = {
openModal: (modal: FunctionComponent<{ onClose: () => void }>) => void;
closeModal: (index: number) => void;
clearModals: () => void;
};

type ModalContextType = IModalState & TModalAction;

const ModalContext = createContext<ModalContextType | undefined>(undefined);

export const ModalContextProvider: FunctionComponent<{
children: ReactNode;
}> = ({ children }) => {
const [modals, setModals] = useState<IModalState['modals']>([]);

const openModal = (modal: FunctionComponent<{ onClose: () => void }>) => {
setModals((prevModals) => [...prevModals, modal]);
};

const closeModal = (index: number) => {
setModals((prevModals) => prevModals.filter((_, i) => i !== index));
};

const clearModals = useCallback(() => {
setModals([]);
}, []);

return (
<ModalContext.Provider
value={{ modals, openModal, closeModal, clearModals }}
>
{children}
</ModalContext.Provider>
);
};

export const useModalContext = () => {
const context = useContext(ModalContext);

if (!context) {
throw new Error(
'useModalContext must be used within a ModalContextProvider',
);
}

return context;
};
21 changes: 21 additions & 0 deletions src/components/Modal/context/ModalProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React, { useEffect } from 'react';
import { useModalContext } from './ModalContext';
import { useLocation } from 'react-router-dom';

export default function ModalProvider() {
const { modals, closeModal, clearModals } = useModalContext();

const location = useLocation();

useEffect(() => {
clearModals();
}, [location, clearModals]);

return (
<div>
{modals.map((Modal, index) => (
<Modal key={index} onClose={() => closeModal(index)} />
))}
</div>
);
}
108 changes: 108 additions & 0 deletions src/components/Modal/modals/AccountEditModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import React, { useContext, useState } from 'react';
import Modal from '../Modal';
import styled from 'styled-components';
import vector from '../../../assets/Vector.png';
import { useModalContext } from '../context/ModalContext';
import AccountOkModal from './AccountOkModal';

interface ModalProps {
onClose: () => void;
}

const AccountEditModal: React.FC<ModalProps> = ({ onClose }) => {
const [account, setAccount] = useState('');
const { openModal } = useModalContext();

const handleSubmit = () => {
openModal(({ onClose }) => <AccountOkModal onClose={onClose} />);
};

return (
<Modal onClose={onClose}>
<Container>
<Img src={vector} />
<Title>계좌번호 변경하기</Title>
{/* <Error>{isError}</Error> */}
<Input
value={account}
onChange={(event) => setAccount(event.target.value)}
placeholder="변경할 계좌번호를 입력하세요."
// isError={!!isError}
/>
<Button onClick={handleSubmit}>변경하기</Button>
</Container>
</Modal>
);
};

const Error = styled.div`
margin-top: 28px;
width: 234px;
height: 17px;
font-size: 11px;
font-style: normal;
font-weight: 400;
line-height: 150%;
color: #c908ff;
font-family: 'Noto Sans KR';
transform: translateX(-18px);
`;

const Button = styled.button`
width: 302px;
height: 39px;
border-radius: 7px;
background-color: #c908ff;
border: 0;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-size: 14px;
font-style: normal;
font-weight: 700;
`;

const Input = styled.input`
margin-top: 46px;
margin-bottom: 151px;
border-radius: 5px;
border: none;
background: #f7f7f7;
width: 272px;
height: 31px;
display: inline-flex;
padding: 3.2px 14px;
justify-content: center;
align-items: center;
outline: none;
&::placeholder {
font-family: Pretendard;
font-size: 12px;
font-style: normal;
font-weight: 300;
}
`;

const Title = styled.div`
font-size: 18px;
font-style: normal;
font-weight: 600;
font-family: Pretendard;
`;

const Img = styled.img`
margin-top: 64px;
width: 31px;
height: 30px;
margin-bottom: 20px;
`;

const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
`;

export default AccountEditModal;
58 changes: 58 additions & 0 deletions src/components/Modal/modals/AccountOkModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import Modal from '../Modal';
import styled from 'styled-components';
import smileVector from '../../../assets/SmileVector.png';

interface ModalProps {
onClose: () => void;
}
const AccountOkModal: React.FC<ModalProps> = ({ onClose }) => {
return (
<Modal onClose={onClose}>
<Container>
<Img src={smileVector} />
<Title>내 계좌 변경이 완료되었습니다.</Title>
<Button onClick={onClose}>래플로 돌아가기 </Button>
</Container>
</Modal>
);
};

const Button = styled.button`
width: 302px;
height: 39px;
border-radius: 7px;
background-color: #c908ff;
border: 0;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
font-size: 14px;
font-style: normal;
font-weight: 700;
`;

const Title = styled.div`
font-family: Pretendard;
font-size: 18px;
font-style: normal;
font-weight: 600;
margin-bottom: 166px;
`;

const Img = styled.img`
width: 67px;
height: 65px;
margin-top: 75px;
margin-bottom: 41px;
`;

const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
`;

export default AccountOkModal;
Loading

0 comments on commit dccb2e5

Please sign in to comment.