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

Feature/upload photo page #64

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "",
"main": "src/Main.tsx",
"scripts": {
"dev": "vite",
"dev": "vite --host",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview",
Expand Down Expand Up @@ -48,6 +48,7 @@
"@types/react": "^18.2.18",
"@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^5.52.0",
"@vitejs/plugin-basic-ssl": "^1.0.1",
"@vitejs/plugin-react": "^4.0.3",
"autoprefixer": "^10.4.15",
"chromatic": "^6.24.1",
Expand All @@ -63,6 +64,7 @@
"eslint-plugin-react": "^7.33.1",
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-storybook": "^0.6.13",
"html5-qrcode": "^2.3.8",
"husky": "^8.0.3",
"lint-staged": "^13.2.3",
"postcss": "^8.4.27",
Expand All @@ -85,6 +87,9 @@
"path": "cz-conventional-changelog"
}
},
"resolutions": {
"jackspeak": "2.1.1"
},
"packageManager": "[email protected]",
"readme": "ERROR: No README data found!",
"_id": "[email protected]"
Expand Down
5 changes: 4 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Route, Routes } from 'react-router-dom';

import DefaultMobileLayout from './domain/_common/layouts/DefaultMobileLayout';
import FullWidthMobileLayout from './domain/_common/layouts/FullWidthMobileLayout';
import Login from './domain/login';
import MyPage from './domain/myPage';
import AlbumRouters from './routers/AlbumRouters';
Expand All @@ -9,12 +10,14 @@ import PhotoRouters from './routers/PhotoRouters';
function App() {
return (
<Routes>
<Route element={<FullWidthMobileLayout />}>
<Route path={'/photo/*'} element={<PhotoRouters />} />
</Route>
<Route element={<DefaultMobileLayout />}>
<Route path={'/'} element={<Login />} />
<Route path={'/login'} element={<Login />} />
<Route path={'/my-page'} element={<MyPage />} />
<Route path={'/album/*'} element={<AlbumRouters />} />
<Route path={'/photo/*'} element={<PhotoRouters />} />
</Route>
</Routes>
);
Expand Down
14 changes: 7 additions & 7 deletions src/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import App from './App';
import './global.css';

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<BrowserRouter>
<ModalProvider>
<App />
</ModalProvider>
</BrowserRouter>
</React.StrictMode>
// <React.StrictMode>
<BrowserRouter>
<ModalProvider>
<App />
</ModalProvider>
</BrowserRouter>
// </React.StrictMode>
);
2 changes: 2 additions & 0 deletions src/assets/gallery.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/domain/_common/components/BottomTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { FloatingButton } from '.';

export function BottomTab() {
return (
<nav role="tab" className="px-[27px] py-[7px]">
<nav role="tab" className="px-[27px] py-[7px] h-[53px]">
<ul className="flex items-center justify-around fill-grey-placeholder">
<li>
<Picture />
Expand Down
2 changes: 1 addition & 1 deletion src/domain/_common/components/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function Checkbox({ type, control }: CheckboxProps) {

return (
<button
className={`w-[336px] h-[101px] border-2 rounded-xl flex justify-start items-center font-bold text-[24px] p-3 ${
className={`w-full h-[101px] border-2 rounded-xl flex justify-start items-center font-bold text-[24px] p-3 ${
isSelected
? 'text-white bg-primary-default border-primary-default'
: 'text-grey-placeholder border-grey-placeholder'
Expand Down
5 changes: 3 additions & 2 deletions src/domain/_common/components/IconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ interface IconButtonProps {
disabled?: boolean;
text: string;
icon: ReactNode;
className?: string;
}

export function IconButton({ onClick = () => {}, disabled = false, text, icon }: IconButtonProps) {
export function IconButton({ onClick = () => {}, disabled = false, text, icon, className = '' }: IconButtonProps) {
const handleButtonClick = () => {
onClick();
};
Expand All @@ -18,7 +19,7 @@ export function IconButton({ onClick = () => {}, disabled = false, text, icon }:
disabled={disabled}
className={`group flex px-2 py-[10px] space-x-4 items-center justify-center rounded-[4px] bg-highlight-gradient active:bg-highlight-gradient-dark disabled:bg-grey-whitegray disabled:bg-none ${
disabled ? 'fill-grey-placeholder' : 'fill-white'
}`}
} ${className}`}
>
<p className="text-white text-headline3 font-bold group-disabled:text-grey-placeholder">{text}</p>
{icon}
Expand Down
5 changes: 3 additions & 2 deletions src/domain/_common/components/NoticeBubble.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
interface BubbleProps {
message: string;
className?: string;
}

export default function Bubble({ message }: BubbleProps) {
export default function Bubble({ message, className = '' }: BubbleProps) {
return (
<div className="relative w-60 leading-[30px] rounded-[20px] bg-black">
<div className={`relative w-60 leading-[30px] rounded-[20px] bg-black ${className}`}>
<div className="px-[15px] text-center">
<p className="text-white text-[13px] font-bold">{message}</p>
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/domain/_common/components/Stepper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
interface StepperProps {
stepLength: number;
activeStep: number;
classProps?: number;
}

const indicatorStyle = {
Expand All @@ -11,7 +12,7 @@ const indicatorStyle = {
next: 'bg-white border border-grey-placeholder text-grey-placeholder',
};

export function Stepper({ stepLength, activeStep }: StepperProps) {
export function Stepper({ stepLength, activeStep, classProps }: StepperProps) {
const getIndicatorStyle = (step: number) => {
if (step < activeStep) {
return indicatorStyle.previous;
Expand Down
5 changes: 3 additions & 2 deletions src/domain/_common/components/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,12 @@ function TabItem({ icon, text, onClick, index }: TabItemProps) {
interface TabPannelProps {
index: number;
children: ReactNode;
className?: string;
}

function TabPannel({ index, children }: TabPannelProps) {
function TabPannel({ index, children, className }: TabPannelProps) {
const { selected } = useTabContext();
return selected === index && <div>{children}</div>;
return selected === index && <div className={className}>{children}</div>;
}

export const Tab = Object.assign(TabGroup, {
Expand Down
4 changes: 2 additions & 2 deletions src/domain/_common/components/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ export function TextInput({ name, label, control, useCheckmark = false, ...props
name={name}
control={control}
render={({ field, fieldState: { error, invalid, isDirty } }) => (
<div className="flex flex-col">
<div className="flex flex-col w-full">
<div
className={`p-[12px] border-grey-placeholder border-[1px] border-solid rounded-[12px] w-full min-w-[336px] flex items-center bg-white ${
className={`p-[12px] border-grey-placeholder border-[1px] border-solid rounded-[12px] w-full flex items-center bg-white ${
error ? 'border-red-default' : ''
}`}
>
Expand Down
13 changes: 13 additions & 0 deletions src/domain/_common/layouts/FullWidthMobileLayout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Outlet } from 'react-router-dom';

export default function FullWidthMobileLayout() {
return (
<main
className={
'm-auto grid min-h-screen w-full max-w-full grid-rows-header-footer bg-white text-grey-300 sm:max-w-lg py-6'
}
>
<Outlet />
</main>
);
}
73 changes: 73 additions & 0 deletions src/domain/photo/RegisterPhoto/ScanQRCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { Html5QrcodeScanner } from 'html5-qrcode';

import { useEffect, useState } from 'react';

export default function ScanQRCode() {
const [scanResultUrl, setscanResultUrl] = useState('');

const isImgUrl = async (url: string) => {
console.log(url);

const img = new Image();
img.src = `${url}.png`;

return await new Promise((resolve) => {
img.onerror = () => {
resolve(false);
};
img.onload = () => {
resolve(true);
};
});
};

useEffect(() => {
const scanner = new Html5QrcodeScanner(
'reader',
{
qrbox: {
width: 250,
height: 250,
},
fps: 5,
},
false
);

const qrSuccessCallback = (decodedText: any, decodedResult: any) => {
setscanResultUrl(String(decodedText));

scanner.clear().catch((err) => {
console.log(err);
});
};

const qrFailCallback = () => {};

scanner.render(qrSuccessCallback, qrFailCallback);

return () => {
scanner.clear().catch((error) => {
console.error('Failed to clear html5QrcodeScanner. ', error);
});
};
}, []);

useEffect(() => {
if (scanResultUrl) {
isImgUrl(scanResultUrl)
.then((result) => {
console.log(result);
})
.catch((err) => {
console.error(err);
});
}
}, [scanResultUrl]);

return (
<>
<div id="reader" className="w-full h-[250px]"></div>
</>
);
}
44 changes: 43 additions & 1 deletion src/domain/photo/RegisterPhoto/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,45 @@
import { type ReactNode } from 'react';

import { ReactComponent as CameraIcon } from '@/assets/camera.svg';
import { ReactComponent as GalleryIcon } from '@/assets/gallery.svg';
import { ReactComponent as QrIcon } from '@/assets/qr.svg';
import { BottomTab, Tab } from '@/domain/_common/components';

import ScanQRCode from './ScanQRCode';

interface tabArrayProps {
tabName: string;
tabIcon: ReactNode;
tabPage: ReactNode;
}

export default function RegisterPhoto() {
return <h1>RegisterPhoto ํŽ˜์ด์ง€</h1>;
const tabArray: tabArrayProps[] = [
{ tabName: '์นด๋ฉ”๋ผ', tabIcon: <CameraIcon />, tabPage: <h1>์นด๋ฉ”๋ผ ํŽ˜์ด์ง€</h1> },
{ tabName: '๊ฐค๋Ÿฌ๋ฆฌ', tabIcon: <GalleryIcon />, tabPage: <h1>๊ฐค๋Ÿฌ๋ฆฌ ํŽ˜์ด์ง€</h1> },
{ tabName: 'QR', tabIcon: <QrIcon />, tabPage: <ScanQRCode /> },
];

return (
<div className="small-h-screen flex flex-col">
<div className="p-10 bg-black-80 rounded-tl-[30px] rounded-tr-[30px] flex-1 flex flex-col items-center gap-5 w-full">
<h1 className="text-white font-bold text-[24px]">QR ์ฝ”๋“œ๋ฅผ ์Šค์บ”ํ•˜์„ธ์—ฌ</h1>
<Tab.Group initialIndex={1}>
<Tab.List className="w-full h-full">
{tabArray.map(({ tabName, tabPage }, index) => (
<Tab.Pannel key={`${tabName}_${index}`} index={index} className="w-full h-full">
{tabPage}
</Tab.Pannel>
))}
</Tab.List>
<Tab.List>
{tabArray.map(({ tabName, tabIcon }, index) => (
<Tab.Item index={index} key={`${tabName}__${index}`} icon={tabIcon} text={`${tabName}`} />
))}
</Tab.List>
</Tab.Group>
</div>
<BottomTab />
</div>
);
}
32 changes: 32 additions & 0 deletions src/domain/photo/UploadPhoto/components/AddPhotoIntoAlbum.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { ReactComponent as ArrowDownIcon } from '@/assets/arrow-down.svg';
import { IconButton } from '@/domain/_common/components';
import { Dropdown } from '@/domain/_common/components/Dropdown';
import Bubble from '@/domain/_common/components/NoticeBubble';

const sampleAlbumInfo = { id: '์ด๊ฑด ๋‚ด ์—˜๋ฒ”์ด์•ผ', link: 'https://ifh.cc/g/ySOj5R.jpg' };

export default function AddPhotoIntoAlbum() {
return (
<>
<div className="flex flex-col gap-1 items-start justify-center relative pb-2">
<Bubble message="์ถ”์–ต์„ ์ €์žฅํ•  ๊ณต๊ฐ„์„ ์„ ํƒํ•ด์ฃผ์„ธ์š”" className="z-30 fixed" />
<div className="flex flex-row justify-start gap-3 items-center">
<Dropdown className="relative">
<Dropdown.Trigger>
<IconButton text="์ผ์ƒ" icon={<ArrowDownIcon />} className="py-1 text-lg" />
</Dropdown.Trigger>
<Dropdown.List className="z-20 absolute">
<Dropdown.Item>์•จ๋ฒ”์ด๋ฆ„ 1</Dropdown.Item>
<Dropdown.Item>์•จ๋ฒ”์ด๋ฆ„ 2</Dropdown.Item>
<Dropdown.Item>์•จ๋ฒ”์ด๋ฆ„ 3</Dropdown.Item>
</Dropdown.List>
</Dropdown>
<h2 className="font-bold text-[18px]">์•จ๋ฒ”์— ์‚ฌ์ง„ ์ถ”๊ฐ€</h2>
</div>
</div>
<div className="flex flex-col items-center justify-start h-full w-full py-5">
<img src={sampleAlbumInfo.link} alt="์ƒ˜ํ”Œ ์‚ฌ์ง„" className="rounded-2xl h-4/5" />
</div>
</>
);
}
32 changes: 32 additions & 0 deletions src/domain/photo/UploadPhoto/components/SelectFrame.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Checkbox } from '@/domain/_common/components';
import { useForm } from '@/hooks';
import { yupSchema } from '@/utils/validation';

export default function SelectFrame() {
const { control } = useForm({
defaultValues: {
checkbox: '',
},
schema: {
checkbox: yupSchema.requiredString,
},
mode: 'onChange',
});

return (
<>
<h2 className="font-bold text-[18px] pb-5">ํ”„๋ ˆ์ž„ ์„ ํƒ</h2>
<ul className="w-full flex flex-col gap-3">
<li>
<Checkbox type="fatHorizontal" control={control} />
</li>
<li>
<Checkbox type="fatVertical" control={control} />
</li>
<li>
<Checkbox type="thinVertical" control={control} />
</li>
</ul>
</>
);
}
Loading