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

Feat/fortune result #9

Merged
merged 2 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"dependencies": {
"@radix-ui/react-alert-dialog": "^1.1.4",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-visually-hidden": "^1.1.1",
"@tanstack/react-query": "^5.64.1",
"@tanstack/react-query-devtools": "^5.64.1",
"@tanstack/react-router": "^1.95.6",
Expand Down
55 changes: 49 additions & 6 deletions src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { createFileRoute } from '@tanstack/react-router'
import { Route as rootRoute } from './routes/__root'
import { Route as IndexImport } from './routes/index'
import { Route as FormIndexImport } from './routes/form/index'
import { Route as DownloadIndexImport } from './routes/download/index'

// Create Virtual Routes

Expand All @@ -35,6 +36,18 @@ const FormIndexRoute = FormIndexImport.update({
getParentRoute: () => rootRoute,
} as any)

const DownloadIndexRoute = DownloadIndexImport.update({
id: '/download/',
path: '/download/',
getParentRoute: () => rootRoute,
} as any)

const DownloadIndexRoute = DownloadIndexImport.update({
id: '/download/',
path: '/download/',
getParentRoute: () => rootRoute,
} as any)

const ResultIdIndexLazyRoute = ResultIdIndexLazyImport.update({
id: '/result/$id/',
path: '/result/$id/',
Expand Down Expand Up @@ -62,6 +75,20 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexImport
parentRoute: typeof rootRoute
}
'/result/$id': {
id: '/result/$id'
path: '/result/$id'
fullPath: '/result/$id'
preLoaderRoute: typeof ResultIdLazyImport
parentRoute: typeof rootRoute
}
'/download/': {
id: '/download/'
path: '/download'
fullPath: '/download'
preLoaderRoute: typeof DownloadIndexImport
parentRoute: typeof rootRoute
}
'/form/': {
id: '/form/'
path: '/form'
Expand Down Expand Up @@ -90,13 +117,17 @@ declare module '@tanstack/react-router' {

export interface FileRoutesByFullPath {
'/': typeof IndexRoute
'/result/$id': typeof ResultIdLazyRoute
'/download': typeof DownloadIndexRoute
'/form': typeof FormIndexRoute
'/result/$id/detail': typeof ResultIdDetailLazyRoute
'/result/$id': typeof ResultIdIndexLazyRoute
}

export interface FileRoutesByTo {
'/': typeof IndexRoute
'/result/$id': typeof ResultIdLazyRoute
'/download': typeof DownloadIndexRoute
'/form': typeof FormIndexRoute
'/result/$id/detail': typeof ResultIdDetailLazyRoute
'/result/$id': typeof ResultIdIndexLazyRoute
Expand All @@ -105,29 +136,35 @@ export interface FileRoutesByTo {
export interface FileRoutesById {
__root__: typeof rootRoute
'/': typeof IndexRoute
'/result/$id': typeof ResultIdLazyRoute
'/download/': typeof DownloadIndexRoute
'/form/': typeof FormIndexRoute
'/result/$id/detail': typeof ResultIdDetailLazyRoute
'/result/$id/': typeof ResultIdIndexLazyRoute
}

export interface FileRouteTypes {
fileRoutesByFullPath: FileRoutesByFullPath
fullPaths: '/' | '/form' | '/result/$id/detail' | '/result/$id'
fullPaths: '/' | '/result/$id' | '/download' | '/form'
fileRoutesByTo: FileRoutesByTo
to: '/' | '/form' | '/result/$id/detail' | '/result/$id'
id: '__root__' | '/' | '/form/' | '/result/$id/detail' | '/result/$id/'
to: '/' | '/result/$id' | '/download' | '/form'
id: '__root__' | '/' | '/result/$id' | '/download/' | '/form/'
fileRoutesById: FileRoutesById
}

export interface RootRouteChildren {
IndexRoute: typeof IndexRoute
ResultIdLazyRoute: typeof ResultIdLazyRoute
DownloadIndexRoute: typeof DownloadIndexRoute
FormIndexRoute: typeof FormIndexRoute
ResultIdDetailLazyRoute: typeof ResultIdDetailLazyRoute
ResultIdIndexLazyRoute: typeof ResultIdIndexLazyRoute
}

const rootRouteChildren: RootRouteChildren = {
IndexRoute: IndexRoute,
ResultIdLazyRoute: ResultIdLazyRoute,
DownloadIndexRoute: DownloadIndexRoute,
FormIndexRoute: FormIndexRoute,
ResultIdDetailLazyRoute: ResultIdDetailLazyRoute,
ResultIdIndexLazyRoute: ResultIdIndexLazyRoute,
Expand All @@ -144,14 +181,20 @@ export const routeTree = rootRoute
"filePath": "__root.tsx",
"children": [
"/",
"/form/",
"/result/$id/detail",
"/result/$id/"
"/result/$id",
"/download/",
"/form/"
]
},
"/": {
"filePath": "index.tsx"
},
"/result/$id": {
"filePath": "result/$id.lazy.tsx"
},
"/download/": {
"filePath": "download/index.tsx"
},
"/form/": {
"filePath": "form/index.tsx"
},
Expand Down
72 changes: 72 additions & 0 deletions src/routes/download.$type.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { DecoratedBox } from '@/components/DecoratedBox';
import { createFileRoute } from '@tanstack/react-router';

export const Route = createFileRoute('/download/$type')({
component: FortuneImage,
});

function FortuneImage() {
// Add type to useParams
const { type } = Route.useParams();

const handleDownload = async () => {
try {
// 이미지 URL
const imageUrl = `/images/charm_${type}.png`;

// 이미지를 Blob으로 가져오기
const response = await fetch(imageUrl);
const blob = await response.blob();

// 다운로드 링크 생성
const downloadUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = downloadUrl;
link.download = `fortune_charm_${type}.png`; // 다운로드될 파일명

// 다운로드 트리거
document.body.appendChild(link);
link.click();

// 클린업
document.body.removeChild(link);
window.URL.revokeObjectURL(downloadUrl);
} catch (error) {
console.error('이미지 다운로드 중 오류가 발생했습니다:', error);
alert('이미지 다운로드에 실패했습니다. 다시 시도해 주세요.');
}
};

return (
<div className="h-screen w-full">
<DecoratedBox>
<div className="h-[calc(100vh-100px)] w-full">
<section className="flex h-full w-full flex-col items-center justify-center gap-4 p-6">
<div className="text-[24px] font-bold text-[#363E76]">
청사(靑蛇)의 해
</div>
<div className="text-[24px] font-bold text-[#363E76]">만사형통</div>
<img
src={`/images/charm_${type}.png`}
alt="운세 이미지"
width={260}
height={347}
className="h-auto max-w-full"
/>
</section>
</div>
</DecoratedBox>
<div className="flex h-[80px] w-full items-center justify-center">
<button
className="h-10 w-[100px] rounded-[12px] bg-[#363E76] text-white"
type="button"
onClick={handleDownload}
>
저장하기
</button>
</div>
</div>
);
}

export default FortuneImage;
46 changes: 27 additions & 19 deletions src/routes/form/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { VisuallyHidden } from '@radix-ui/react-visually-hidden';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { createFileRoute, useNavigate } from '@tanstack/react-router';
import { useForm, useWatch } from 'react-hook-form';
Expand Down Expand Up @@ -234,6 +235,7 @@ export function CustomAlertDialog({
errors: any;
setAlertOpen: (isOpen: boolean) => void;
}) {
const alertDialogDescriptionId = 'alert-dialog-description';
const getFirstErrorMessege = (errors: any) => {
if (errors?.name) {
return errors.name.message;
Expand All @@ -248,7 +250,12 @@ export function CustomAlertDialog({

return (
<AlertDialog open={isOpen} onOpenChange={setAlertOpen}>
<AlertDialogContent className="w-[90%] max-w-[400px] rounded-md">
<AlertDialogTitle hidden={true} />
<AlertDialogContent
className="w-[90%] max-w-[400px] rounded-md"
aria-describedby={alertDialogDescriptionId}
>
<AlertDialogDescription>커스텀 다이얼로그</AlertDialogDescription>
<AlertDialogHeader>
<AlertDialogTitle className="text-center font-[#394F6E]">
{getFirstErrorMessege(errors)}
Expand All @@ -268,27 +275,28 @@ export function CustomAlertDialog({
}

export function LoadingOverlay({ isPending }: { isPending: boolean }) {
const dialogDescriptionId = 'loading-dialog-description';
return (
<AlertDialog open={isPending}>
<AlertDialogTitle hidden={true} />
<AlertDialogContent className="h-full max-w-[500px]">
<AlertDialogDescription className="flex h-full w-full flex-col items-center justify-center">
<DecoratedBox>
<div className="py-15 flex flex-col items-center justify-center px-10 py-20">
<p className="text-2xl font-bold text-[#363E76]">
사주 분석중...
</p>
{isPending && (
<div className="my-10">
<LoadingSnake />
</div>
)}
<p className="text-[#363E76]">
2025년은 소띠, 뱀띠 닭띠의 운세가 좋아요
</p>
</div>
</DecoratedBox>
</AlertDialogDescription>
<AlertDialogContent
className="h-full max-w-[500px]"
aria-describedby={dialogDescriptionId}
>
<div id={dialogDescriptionId}>
<VisuallyHidden>
사주 정보를 분석하고 있습니다. 잠시만 기다려주세요.
</VisuallyHidden>
<AlertDialogDescription className="flex h-full w-full flex-col items-center justify-center">
사주분석중...
{isPending && (
<div className="my-10">
<LoadingSnake />
</div>
)}
2025년은 소띠, 뱀띠 닭띠의 운세가 좋아요
</AlertDialogDescription>
</div>
</AlertDialogContent>
</AlertDialog>
);
Expand Down
Loading
Loading