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) => { {/* アクションボタン */}
- - {parseInt(localStorage.getItem('countDown') || '0', 10) > 1 && ( - + {isLoading ? ( +
+
+
+ ) : ( + <> + + {parseInt(localStorage.getItem('countDown') || '0', 10) > 1 && ( + + )} + )}
diff --git a/apps/web/src/components/result/ResultScreen.module.css b/apps/web/src/components/result/ResultScreen.module.css index 24a6dd5..44ebf63 100644 --- a/apps/web/src/components/result/ResultScreen.module.css +++ b/apps/web/src/components/result/ResultScreen.module.css @@ -93,8 +93,8 @@ } .character-image { - width: 52%; - height: 52%; + width: 42%; + height: 42%; object-fit: contain; object-position: center; border-radius: 64px;