Skip to content

Commit

Permalink
Merge pull request #177 from choco-team/175-fe-qrcode-page
Browse files Browse the repository at this point in the history
175 fe qrcode page
  • Loading branch information
nlom0218 authored Mar 8, 2024
2 parents b2a1f4e + 5da0931 commit 67017b6
Show file tree
Hide file tree
Showing 12 changed files with 582 additions and 811 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,19 @@
"-": "^0.0.1",
"@tanstack/react-query": "^4.35.7",
"@tanstack/react-query-devtools": "^4.36.1",
"D": "^1.0.0",
"ag-grid-community": "^30.2.0",
"ag-grid-react": "^30.2.0",
"axios": "^1.5.1",
"calendar-in-react": "^1.0.5",
"chalk": "^5.3.0",
"D": "^1.0.0",
"date-fns": "^2.30.0",
"qrcode.react": "^3.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-icons": "^4.11.0",
"react-router-dom": "^6.16.0",
"react-to-print": "^2.15.1",
"styled-components": "^6.0.8",
"xlsx": "^0.18.5",
"zustand": "^4.4.7"
Expand Down
1 change: 1 addition & 0 deletions src/pages/Qrcode/QrcodeBlock/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const Storage = styled.div`
&:hover {
background-color: #fee3e2;
border: 1px solid #fe6f61;
}
`;

Expand Down
26 changes: 21 additions & 5 deletions src/pages/Qrcode/QrcodeInput/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import QRCode from 'qrcode.react';
import { useState } from 'react';
import React, { useState } from 'react';

import useModal from '@Hooks/useModal';

import * as S from './style';
import QrcodeName from '../QrcodeName';
import QrcodePrintOption from '../QrcodePrintOption';

function QrcodeInput() {
const [inputValue, setInputValue] = useState('');
const [inputValue, setInputValue] = useState<string>('');

const { isOpen, openModal, closeModal } = useModal();

const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(event.target.value);
};

const handleClearClick = () => {
setInputValue('');
};
Expand All @@ -24,7 +26,9 @@ function QrcodeInput() {
const link = document.createElement('a');
link.href = url;
link.download = `qrcode.png`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};

const handleViewLarger = () => {
Expand All @@ -40,27 +44,39 @@ function QrcodeInput() {
}
};

const handleGoToLink = () => {
if (inputValue) {
const url =
inputValue.startsWith('http://') || inputValue.startsWith('https://')
? inputValue
: `https://${inputValue}`;
window.open(url, '_blank');
}
};

const isButtonVisible = inputValue.trim() !== '';

return (
<S.Container>
{/* <h1>URL 주소를 입력해주세요.</h1> */}
<S.InputContainer>
<S.Input
type="url"
placeholder="www.teachercan.com"
value={inputValue}
onChange={handleInputChange}
/>
<S.ClearButton onClick={handleClearClick}>새QR생성</S.ClearButton>
<S.ClearButton onClick={handleClearClick}>새 QR 생성</S.ClearButton>
</S.InputContainer>

{isButtonVisible && <QRCode value={inputValue} size={400} />}
{isButtonVisible && (
<S.ButtonContainer>
<S.Button onClick={handleViewLarger}>크게보기</S.Button>
<S.Button>인쇄하기</S.Button>
<S.Button onClick={() => openModal(<QrcodePrintOption />)}>
인쇄하기
</S.Button>
<S.Button onClick={handleDownload}>다운로드</S.Button>
<S.Button onClick={handleGoToLink}>바로가기</S.Button>
<S.Button onClick={() => openModal(<QrcodeName />)}>
보관함에 저장
</S.Button>
Expand Down
4 changes: 2 additions & 2 deletions src/pages/Qrcode/QrcodeInput/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const Container = styled.div`
display: flex;
flex-direction: column;
align-items: center;
margin-top: 30px;
/* margin-top: 30px; */
padding: 10px;
width: 100%;
`;
Expand Down Expand Up @@ -45,7 +45,7 @@ export const Input = styled.input`
export const ClearButton = styled.div`
padding: 10px 20px;
height: 35px;
width: 100px;
width: fit-content;
text-align: center;
font-size: 14px;
background-color: #f48d8d;
Expand Down
3 changes: 1 addition & 2 deletions src/pages/Qrcode/QrcodePage/style.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import styled from 'styled-components';

// import Button from '@Components/Button';
// import theme from '@Styles/theme';
import theme from '@Styles/theme';

export const Container = styled.div`
display: flex;
Expand Down
85 changes: 85 additions & 0 deletions src/pages/Qrcode/QrcodePrintOption/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React, { useState, useRef } from 'react';
import { FaSquare } from 'react-icons/fa';
import {
TfiLayoutGrid4Alt,
TfiLayoutGrid2Alt,
TfiLayoutGrid3Alt,
} from 'react-icons/tfi';
import { useReactToPrint } from 'react-to-print';

import useModal from '@Hooks/useModal';

import Button from '@Components/Button';

import * as S from './style';
import QrcodePrintPage from '../QrcodePrintPage';

const QrcodePrintOption: React.FC = () => {
const [selectedSize, setSelectedSize] = useState<string>('');
const { closeModal } = useModal();
const [number, setNumber] = useState<number>(0);
const componentRef = useRef();

const handleChangeNumber = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = parseInt(e.target.value, 10);

if (!isNaN(newValue) && newValue >= 0) {
setNumber(newValue);
}
};
const increment = () => setNumber((prevNumber) => prevNumber + 1);
const decrement = () => {
setNumber((prevNumber) => (prevNumber > 0 ? prevNumber - 1 : 0));
};

const handleSizeSelect = (size: string) => {
setSelectedSize(size);
};

const handleCancelBtn = () => {
closeModal();
};

const handlePrintBtn = useReactToPrint({
content: () => componentRef.current,
});
return (
<S.Container>
<S.NumberSelectContainer>
<S.NameSpan>개수 선택</S.NameSpan>
<S.NumberContainer>
<S.NumberInput
type="number"
value={number}
onChange={handleChangeNumber}
/>
</S.NumberContainer>
</S.NumberSelectContainer>

<S.SizeSelectContainer>
<S.NameSpan>크기 선택</S.NameSpan>
{['5x8', '4x4', '2x2', '1x1'].map((size) => (
<S.SizeSelectButton
key={size}
onClick={() => handleSizeSelect(size)}
isSelected={selectedSize === size}
>
{size === '5x8' && <TfiLayoutGrid4Alt />}
{size === '4x4' && <TfiLayoutGrid3Alt />}
{size === '2x2' && <TfiLayoutGrid2Alt />}
{size === '1x1' && <FaSquare />}
</S.SizeSelectButton>
))}
</S.SizeSelectContainer>
<S.SmallButtonWrapper>
<Button concept="text" variant="gray" onClick={handleCancelBtn}>
취소
</Button>
<Button onClick={handlePrintBtn}>인쇄</Button>
<QrcodePrintPage ref={componentRef} />
</S.SmallButtonWrapper>
</S.Container>
);
};

export default QrcodePrintOption;
90 changes: 90 additions & 0 deletions src/pages/Qrcode/QrcodePrintOption/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import styled from 'styled-components';

export const Container = styled.div`
display: flex;
flex-direction: column;
/* align-items: center; */
margin-top: 30px;
padding: 20px;
width: 100%;
gap: 30px;
`;

export const NameSpan = styled.span`
margin: 5px;
border-radius: 2px;
min-height: 24px;
min-width: 96px;
padding: 8px;
color: black;
align-self: flex-start;
`;

export const SizeSelectContainer = styled.div`
display: flex;
align-items: center;
gap: 10px;
`;
export const NumberSelectContainer = styled.div`
display: flex;
align-items: center;
gap: 10px;
`;

export const NumberContainer = styled.div`
display: flex;
align-items: center;
border: solid 1px #ccc;
border-radius: 2px;
`;

export const NumberInput = styled.input`
width: 60px;
text-align: center;
`;

export const NumberUpdownButton = styled.div`
width: 20px;
height: 20px;
cursor: pointer;
user-select: none;
text-align: center;
color: #f48d8d;
`;

export const SizeSelectButton = styled.div<{ isSelected: boolean }>`
border: solid 1px ${(props) => (props.isSelected ? '#F17071' : '#ccc')};
background-color: ${(props) =>
props.isSelected ? '#fee3e2' : 'transparent'};
border-radius: 2px;
display: flex;
justify-content: center;
align-items: center;
width: 40px;
height: 40px;
cursor: pointer;
&:hover {
background-color: #fee3e2;
border: 1px solid #fe6f61;
}
`;

export const ListSpan = styled.span`
margin: 5px;
border-radius: 2px;
min-height: 24px;
min-width: 96px;
padding: 8px;
color: 'black';
`;
export const SmallButtonWrapper = styled.div`
display: flex;
padding: 0;
margin-top: 24px;
align-items: flex-end;
justify-content: flex-end;
button {
margin-right: 5px;
}
`;
9 changes: 9 additions & 0 deletions src/pages/Qrcode/QrcodePrintPage/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React, { useState } from 'react';

import * as S from './style';

function QrcodePrintPage() {
return;
}

export default QrcodePrintPage;
Empty file.
50 changes: 43 additions & 7 deletions src/pages/Qrcode/QrcodeStorage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,44 @@ function QrcodeStorage() {
);
};

const handleDownload = () => {
function handleDownload() {
// 다운로드 로직 구현
};
}

// const handleViewLarger = () => {
// const qrCodeDataURL = "www.google.com"
// const newWindow = window.open(qrCodeDataURL, 'qrcodePopup');
// if (newWindow) {
// newWindow.document.write(`
// <div style="display: flex; justify-content: center; align-items: center; height: 100vh;">
// <img src="${qrCodeDataURL}" style="max-width: 100%; max-height: 100%;" />
// </div>
// `);
// }

// // 크게 보기 로직 구현
// };

const handleViewLarger = () => {
// 크게 보기 로직 구현
const newWindow = window.open('', 'qrcodePopup');
if (newWindow) {
newWindow.document.write(`
<div style="display: flex; flex-wrap: wrap; justify-content: center; align-items: center; height: 100vh;">
`);

selectedQrcodes.forEach((selectedId) => {
const qrCodeItem = qrcodeData.find((item) => item.id === selectedId);
if (qrCodeItem) {
newWindow.document.write(`
<div style="margin: 10px;">
<img src="${qrCodeItem.url}" style="max-width: 100%; max-height: 100%;" />
</div>
`);
}
});

newWindow.document.write(`</div>`);
}
};

const handleDeleteQrcode = () => {
Expand All @@ -48,19 +80,23 @@ function QrcodeStorage() {
return (
<S.Container>
<S.ButtonContainer>
<S.SelectAllButton onClick={toggleSelectAll}>
{selectedQrcodes.length < qrcodeData.length
? '전체 선택'
: '선택 해제'}
</S.SelectAllButton>
<S.Button onClick={handleViewLarger}>크게보기</S.Button>
<S.Button>인쇄하기</S.Button>
<S.Button onClick={handleDownload}>다운로드</S.Button>
<S.Button onClick={handleDeleteQrcode}>삭제하기</S.Button>
</S.ButtonContainer>
<S.SelectAllButton onClick={toggleSelectAll}>
{selectedQrcodes.length < qrcodeData.length ? '전체 선택' : '선택 해제'}
</S.SelectAllButton>

<S.QrcodeBlockContainer>
{qrcodeData.map((item) => (
<QrcodeBlock
onClick={() => onToggle(data.id)}
key={item.id}
data={item}
data={item.url}
isSelected={selectedQrcodes.includes(item.id)}
onToggle={() => toggleSelect(item.id)}
/>
Expand Down
Loading

0 comments on commit 67017b6

Please sign in to comment.