diff --git a/apps/web/src/components/photo/PhotoPreview.module.css b/apps/web/src/components/photo/PhotoPreview.module.css index 0b69b5f..0048f90 100644 --- a/apps/web/src/components/photo/PhotoPreview.module.css +++ b/apps/web/src/components/photo/PhotoPreview.module.css @@ -132,3 +132,37 @@ background: var(--accent-bg); transform: translateY(-2px); } + +.loading-container { + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; + padding: 20px; +} + +.loading-spinner { + width: 40px; + height: 40px; + border: 4px solid var(--accent-bg); + border-top: 4px solid var(--warm-brown); + border-radius: 50%; + animation: spin 1s linear infinite; +} + +.loading-text { + font-size: 16px; + color: var(--text-primary); + font-weight: 500; + text-align: center; + margin: 0; +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +} diff --git a/apps/web/src/components/photo/PhotoPreview.tsx b/apps/web/src/components/photo/PhotoPreview.tsx index 83e921f..7a7c2b3 100644 --- a/apps/web/src/components/photo/PhotoPreview.tsx +++ b/apps/web/src/components/photo/PhotoPreview.tsx @@ -1,4 +1,4 @@ -import { useCallback } from 'react'; +import { useCallback, useState } from 'react'; import { useNavigate } from 'react-router-dom'; import clsx from 'clsx'; @@ -17,12 +17,16 @@ interface PhotoPreviewProps { export const PhotoPreview = (props: PhotoPreviewProps) => { const { onConfirm, onRetake } = props; + const [isLoading, setIsLoading] = useState(false); + const navigate = useNavigate(); const handleConfirm = useCallback(() => { if (onConfirm) { onConfirm(); } + setIsLoading(true); + // localStorage から theme と difficulty と base64 のデータを取得し、リクエストボディに含める const themesData = JSON.parse( localStorage.getItem('currentThemes') || '{"themes": []}', @@ -67,6 +71,7 @@ export const PhotoPreview = (props: PhotoPreviewProps) => { navigate('/result'); } catch (e) { console.error(e); + setIsLoading(false); } }; @@ -119,19 +124,33 @@ export const PhotoPreview = (props: PhotoPreviewProps) => { {/* アクションボタン */}