perf: optimize web data resources

This commit is contained in:
ZL-Q
2026-05-10 20:01:14 +08:00
parent a9739cddce
commit 1e4871e337
24 changed files with 1304 additions and 252 deletions
+14 -18
View File
@@ -1,7 +1,7 @@
import { useState, useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { getUserProfile, updateUserProfile, uploadAvatar, type UserProfile } from '../lib/api';
import { getAuth } from '../lib/auth';
import { updateProfileResource, uploadAvatarResource, useProfile } from '../lib/resources';
interface Props {
locale: string;
@@ -57,28 +57,25 @@ async function compressImage(file: File, maxWidth = 512, maxHeight = 512, qualit
export default function ProfileDetailPage({ locale, profile: p }: Props) {
const navigate = useNavigate();
const [profile, setProfile] = useState<UserProfile | null>(null);
const profileState = useProfile();
const profile = profileState.data ?? null;
const [displayName, setDisplayName] = useState('');
const [bio, setBio] = useState('');
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const [uploading, setUploading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [success, setSuccess] = useState<string | null>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
// Load profile on mount
useEffect(() => {
setLoading(true);
getUserProfile()
.then((data) => {
setProfile(data);
setDisplayName(data.display_name || '');
setBio(data.bio || '');
})
.catch((err) => setError(err.message || 'Failed to load profile'))
.finally(() => setLoading(false));
}, []);
if (!profileState.data) return;
setDisplayName(profileState.data.display_name || '');
setBio(profileState.data.bio || '');
}, [profileState.data]);
useEffect(() => {
if (profileState.error instanceof Error) setError(profileState.error.message || 'Failed to load profile');
}, [profileState.error]);
// Clear messages after 3 seconds
useEffect(() => {
@@ -92,7 +89,7 @@ export default function ProfileDetailPage({ locale, profile: p }: Props) {
setSaving(true);
setError(null);
try {
await updateUserProfile({
await updateProfileResource({
display_name: displayName || undefined,
bio: bio || undefined,
});
@@ -134,8 +131,7 @@ export default function ProfileDetailPage({ locale, profile: p }: Props) {
throw new Error(locale === 'en' ? 'Image too large, please choose a smaller one' : '图片太大,请选择更小的图片');
}
const updated = await uploadAvatar(compressedFile);
setProfile(updated);
await uploadAvatarResource(compressedFile);
setSuccess(locale === 'en' ? 'Avatar updated' : '头像已更新');
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to upload');
@@ -146,7 +142,7 @@ export default function ProfileDetailPage({ locale, profile: p }: Props) {
}
};
if (loading) {
if (profileState.loading) {
return (
<div className="flex flex-col gap-6 min-h-full">
<div className="text-slate-500">{locale === 'en' ? 'Loading...' : '加载中...'}</div>