refactor: enhance login handling and user feedback in FriendsPhoto and History components
This commit is contained in:
parent
b545e71243
commit
96ef8ffb3c
|
|
@ -1,23 +1,25 @@
|
||||||
|
import { authService } from '@/services/auth';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { bowongAI } from '../../../../sdk/bowongAISDK';
|
|
||||||
import { useI18n } from '../../../../hooks/useI18n';
|
import { useI18n } from '../../../../hooks/useI18n';
|
||||||
|
import { bowongAI } from '../../../../sdk/bowongAISDK';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
interface UploadCardProps {
|
interface UploadCardProps {
|
||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
onLogin: () => void;
|
||||||
onUploadSuccess: (imageUrl: string) => void;
|
onUploadSuccess: (imageUrl: string) => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function UploadCard({ imageUrl, title, onUploadSuccess, className = '', disabled = false }: UploadCardProps) {
|
export default function UploadCard({ imageUrl, title, onLogin, onUploadSuccess, className = '', disabled = false }: UploadCardProps) {
|
||||||
const [uploading, setUploading] = useState<boolean>(false);
|
const [uploading, setUploading] = useState<boolean>(false);
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const handleUpload = async () => {
|
const handleUpload = async () => {
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
alert('Please login first');
|
onLogin();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ export default function FriendsPhoto() {
|
||||||
const templateCode = searchParams.get('templateCode');
|
const templateCode = searchParams.get('templateCode');
|
||||||
const [template, setTemplate] = useState<Template | null>(null);
|
const [template, setTemplate] = useState<Template | null>(null);
|
||||||
|
|
||||||
|
const [loginRedirecting, setLoginRedirecting] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const checkLogin = async () => {
|
const checkLogin = async () => {
|
||||||
// Check login status, including OAuth 2.0 callback handling
|
// Check login status, including OAuth 2.0 callback handling
|
||||||
|
|
@ -50,16 +52,17 @@ export default function FriendsPhoto() {
|
||||||
// 提交处理
|
// 提交处理
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
if (!isLoggedIn) {
|
if (!isLoggedIn) {
|
||||||
|
setLoginRedirecting(true);
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
authService.login('/friends-photo');
|
await authService.login('/friends-photo');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!templateCode) {
|
if (!templateCode) {
|
||||||
alert(t('friendsPhoto.templateCodeNotSet'));
|
alert('Template code not set');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!image1 || !image2) {
|
if (!image1 || !image2) {
|
||||||
alert(t('friendsPhoto.uploadTwoImages'));
|
alert('Upload two images');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,36 +90,52 @@ export default function FriendsPhoto() {
|
||||||
// navigate(`/result?taskId=${taskId}&templateCode=${templateCode}`);
|
// navigate(`/result?taskId=${taskId}&templateCode=${templateCode}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('提交失败:', error);
|
console.error('提交失败:', error);
|
||||||
alert(t('friendsPhoto.waitForTaskCompletion'));
|
alert('Wait for task completion');
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// // If not authenticated, show login prompt
|
// // If not authenticated, show login prompt
|
||||||
// if (isLoggedIn === false) {
|
|
||||||
// return (
|
if (loginRedirecting) {
|
||||||
// <div className="app-loading">
|
return (
|
||||||
// <div className="loading-container">
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
|
||||||
// <div className="loading-spinner"></div>
|
<div>Redirecting to login...</div>
|
||||||
// <div className="loading-text">Redirecting to login page...</div>
|
</div>
|
||||||
// </div>
|
);
|
||||||
// </div>
|
}
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="friends-photo">
|
<div className="friends-photo">
|
||||||
{/* 上传区域 */}
|
{/* 上传区域 */}
|
||||||
<div className="upload-section">
|
<div className="upload-section">
|
||||||
<UploadCard disabled={!isLoggedIn} imageUrl={image1} title={t('friendsPhoto.selectYourPhoto')} onUploadSuccess={setImage1} />
|
<UploadCard
|
||||||
<UploadCard disabled={!isLoggedIn} imageUrl={image2} title={t('friendsPhoto.selectFriendPhoto')} onUploadSuccess={setImage2} />
|
disabled={!isLoggedIn}
|
||||||
|
imageUrl={image1}
|
||||||
|
title={t('friendsPhoto.selectYourPhoto')}
|
||||||
|
onUploadSuccess={setImage1}
|
||||||
|
onLogin={() => {
|
||||||
|
setLoginRedirecting(true);
|
||||||
|
authService.login('/friends-photo');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<UploadCard
|
||||||
|
disabled={!isLoggedIn}
|
||||||
|
imageUrl={image2}
|
||||||
|
title={t('friendsPhoto.selectFriendPhoto')}
|
||||||
|
onUploadSuccess={setImage2}
|
||||||
|
onLogin={() => {
|
||||||
|
setLoginRedirecting(true);
|
||||||
|
authService.login('/friends-photo');
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 固定底部按钮 */}
|
{/* 固定底部按钮 */}
|
||||||
<div className="submit-section">
|
<div className="submit-section">
|
||||||
<button
|
<button
|
||||||
className={`submit-button ${!image1 || !image2 || loading ? 'disabled' : ''}`}
|
className={`submit-button ${(!image1 || !image2 || loading) && isLoggedIn ? 'disabled' : ''}`}
|
||||||
disabled={(!image1 || !image2 || loading) && isLoggedIn}
|
disabled={(!image1 || !image2 || loading) && isLoggedIn}
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ export default function History() {
|
||||||
const [isLoggedIn, setIsLoggedIn] = useState<boolean | null>(null);
|
const [isLoggedIn, setIsLoggedIn] = useState<boolean | null>(null);
|
||||||
const serverSdk = useServerSdk();
|
const serverSdk = useServerSdk();
|
||||||
|
|
||||||
|
const [loginRedirecting, setLoginRedirecting] = useState(false);
|
||||||
|
|
||||||
const checkLoginStatus = async () => {
|
const checkLoginStatus = async () => {
|
||||||
try {
|
try {
|
||||||
const loginStatus = await authService.checkLogin();
|
const loginStatus = await authService.checkLogin();
|
||||||
|
|
@ -105,12 +107,21 @@ export default function History() {
|
||||||
|
|
||||||
const handleLogin = async () => {
|
const handleLogin = async () => {
|
||||||
try {
|
try {
|
||||||
|
setLoginRedirecting(true);
|
||||||
await authService.login('/history');
|
await authService.login('/history');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Login failed:', error);
|
console.error('Login failed:', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (loginRedirecting) {
|
||||||
|
return (
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
|
||||||
|
<div>Redirecting to login...</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="history">
|
<div className="history">
|
||||||
{/* Settings area */}
|
{/* Settings area */}
|
||||||
|
|
|
||||||
|
|
@ -46,13 +46,14 @@ export class AuthService {
|
||||||
/**
|
/**
|
||||||
* 跳转到Google OAuth登录页面
|
* 跳转到Google OAuth登录页面
|
||||||
*/
|
*/
|
||||||
async login(redirectUrl?: string): Promise<void> {
|
async login(redirectPath?: string): Promise<void> {
|
||||||
const { hostname, protocol, port } = window.location;
|
const { hostname, protocol, port } = window.location;
|
||||||
let baseUrl = `${protocol}//${hostname}`;
|
let baseUrl = `${protocol}//${hostname}`;
|
||||||
if (hostname === 'localhost') {
|
if (hostname === 'localhost') {
|
||||||
baseUrl = `${protocol}//${hostname}:${port}`;
|
baseUrl = `${protocol}//${hostname}:${port}`;
|
||||||
}
|
}
|
||||||
window.location.href = `https://mixvideo-workflow.bowong.cc/auth/google/authorize?redirect_url=${baseUrl}${redirectUrl || ''}`;
|
const redirectUrl = `https://mixvideo-workflow.bowong.cc/auth/google/authorize?redirect_url=${baseUrl}${redirectPath || ''}`;
|
||||||
|
window.location.href = redirectUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue