better studio debugger loading
This commit is contained in:
parent
f0d9797cac
commit
5a7aedf11b
@ -10,7 +10,7 @@ import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Textarea } from '@/components/ui/textarea'
|
||||
import { LoadingSpinner } from '@/components/ui/loading-spinner'
|
||||
import { FullScreenLoading } from '@/components/ui/full-screen-loading'
|
||||
import { LoadingRing } from '@/components/ui/loading-ring'
|
||||
import { VersionTimeline, VersionTimelineRef } from '@/components/studio/VersionTimeline'
|
||||
import { PermissionToggle } from '@/components/studio/PermissionToggle'
|
||||
import {
|
||||
@ -71,10 +71,6 @@ export default function PromptPage({ params }: PromptPageProps) {
|
||||
const [originalTitle, setOriginalTitle] = useState('')
|
||||
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false)
|
||||
const [isDuplicating, setIsDuplicating] = useState(false)
|
||||
const [fullScreenLoading, setFullScreenLoading] = useState({
|
||||
isVisible: false,
|
||||
message: ''
|
||||
})
|
||||
const versionTimelineRef = useRef<VersionTimelineRef>(null)
|
||||
|
||||
useEffect(() => {
|
||||
@ -164,10 +160,6 @@ export default function PromptPage({ params }: PromptPageProps) {
|
||||
if (!user || !promptId) return
|
||||
|
||||
setIsSaving(true)
|
||||
setFullScreenLoading({
|
||||
isVisible: true,
|
||||
message: '正在保存提示词...'
|
||||
})
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/prompts/${promptId}`, {
|
||||
@ -204,10 +196,6 @@ export default function PromptPage({ params }: PromptPageProps) {
|
||||
console.error('Failed to save prompt:', error)
|
||||
} finally {
|
||||
setIsSaving(false)
|
||||
setFullScreenLoading({
|
||||
isVisible: false,
|
||||
message: ''
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,10 +257,6 @@ export default function PromptPage({ params }: PromptPageProps) {
|
||||
if (!user || !prompt) return
|
||||
|
||||
setIsDuplicating(true)
|
||||
setFullScreenLoading({
|
||||
isVisible: true,
|
||||
message: '正在复制提示词...'
|
||||
})
|
||||
|
||||
try {
|
||||
// 创建新的prompt,使用当前显示的内容
|
||||
@ -292,40 +276,22 @@ export default function PromptPage({ params }: PromptPageProps) {
|
||||
|
||||
if (response.ok) {
|
||||
const newPrompt = await response.json()
|
||||
|
||||
// 先隐藏加载遮罩,然后跳转
|
||||
setFullScreenLoading({
|
||||
isVisible: false,
|
||||
message: ''
|
||||
})
|
||||
|
||||
// 延迟跳转以确保遮罩动画完成
|
||||
setTimeout(() => {
|
||||
router.push(`/studio/${newPrompt.id}`)
|
||||
}, 300)
|
||||
router.push(`/studio/${newPrompt.id}`)
|
||||
} else {
|
||||
console.error('Failed to duplicate prompt')
|
||||
setFullScreenLoading({
|
||||
isVisible: false,
|
||||
message: ''
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error duplicating prompt:', error)
|
||||
setFullScreenLoading({
|
||||
isVisible: false,
|
||||
message: ''
|
||||
})
|
||||
} finally {
|
||||
setIsDuplicating(false)
|
||||
}
|
||||
}
|
||||
|
||||
if (loading || isLoading) {
|
||||
return <FullScreenLoading isVisible={true} message={t('loadingStudio')} />
|
||||
if (loading) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (!user || !prompt) {
|
||||
if (!user) {
|
||||
return null
|
||||
}
|
||||
|
||||
@ -352,8 +318,17 @@ export default function PromptPage({ params }: PromptPageProps) {
|
||||
<div className="flex items-center space-x-2">
|
||||
<FileText className="h-5 w-5 text-muted-foreground" />
|
||||
<div>
|
||||
<h1 className="font-semibold text-foreground">{prompt?.name || 'Loading...'}</h1>
|
||||
<p className="text-xs text-muted-foreground">Version {prompt?.currentVersion || 1} • {prompt?.usage || 0} uses</p>
|
||||
{isLoading ? (
|
||||
<div className="flex items-center space-x-2">
|
||||
<LoadingRing size="sm" />
|
||||
<span className="text-muted-foreground">Loading...</span>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<h1 className="font-semibold text-foreground">{prompt?.name || 'Loading...'}</h1>
|
||||
<p className="text-xs text-muted-foreground">Version {prompt?.currentVersion || 1} • {prompt?.usage || 0} uses</p>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -381,46 +356,61 @@ export default function PromptPage({ params }: PromptPageProps) {
|
||||
</div>
|
||||
|
||||
<div className="max-w-7xl mx-auto p-4">
|
||||
{/* Mobile Layout (stacked) */}
|
||||
<div className="lg:hidden space-y-6">
|
||||
{/* 1. Prompt Editor (Mobile First) */}
|
||||
<div className="bg-card rounded-lg border border-border">
|
||||
<div className="p-4 border-b border-border">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="font-semibold text-foreground">{t('promptEditor')}</h3>
|
||||
<div className="flex items-center space-x-1 text-xs text-muted-foreground">
|
||||
<span>{promptContent.length} characters</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label htmlFor="promptTitle" className="text-sm font-medium">
|
||||
{t('promptName')}
|
||||
</Label>
|
||||
<Input
|
||||
id="promptTitle"
|
||||
value={promptTitle}
|
||||
onChange={(e) => setPromptTitle(e.target.value)}
|
||||
className="mt-1"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label htmlFor="promptContent" className="text-sm font-medium">
|
||||
{t('promptContent')}
|
||||
</Label>
|
||||
<Textarea
|
||||
id="promptContent"
|
||||
value={promptContent}
|
||||
onChange={(e) => setPromptContent(e.target.value)}
|
||||
className="mt-1 min-h-[300px] font-mono text-sm resize-none"
|
||||
placeholder="Write your prompt here..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{isLoading ? (
|
||||
/* Loading State */
|
||||
<div className="flex items-center justify-center py-16">
|
||||
<div className="text-center">
|
||||
<LoadingRing size="lg" className="mb-4" />
|
||||
<p className="text-muted-foreground">{t('loadingStudio')}</p>
|
||||
</div>
|
||||
</div>
|
||||
) : !prompt ? (
|
||||
/* No Prompt State */
|
||||
<div className="text-center py-16">
|
||||
<p className="text-muted-foreground">Prompt not found</p>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
{/* Mobile Layout (stacked) */}
|
||||
<div className="lg:hidden space-y-6">
|
||||
{/* 1. Prompt Editor (Mobile First) */}
|
||||
<div className="bg-card rounded-lg border border-border">
|
||||
<div className="p-4 border-b border-border">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="font-semibold text-foreground">{t('promptEditor')}</h3>
|
||||
<div className="flex items-center space-x-1 text-xs text-muted-foreground">
|
||||
<span>{promptContent.length} characters</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<div className="space-y-4">
|
||||
<div>
|
||||
<Label htmlFor="promptTitle" className="text-sm font-medium">
|
||||
{t('promptName')}
|
||||
</Label>
|
||||
<Input
|
||||
id="promptTitle"
|
||||
value={promptTitle}
|
||||
onChange={(e) => setPromptTitle(e.target.value)}
|
||||
className="mt-1"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label htmlFor="promptContent" className="text-sm font-medium">
|
||||
{t('promptContent')}
|
||||
</Label>
|
||||
<Textarea
|
||||
id="promptContent"
|
||||
value={promptContent}
|
||||
onChange={(e) => setPromptContent(e.target.value)}
|
||||
className="mt-1 min-h-[300px] font-mono text-sm resize-none"
|
||||
placeholder="Write your prompt here..."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Permissions (Mobile) */}
|
||||
<PermissionToggle
|
||||
@ -684,13 +674,9 @@ export default function PromptPage({ params }: PromptPageProps) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Full Screen Loading */}
|
||||
<FullScreenLoading
|
||||
isVisible={fullScreenLoading.isVisible}
|
||||
message={fullScreenLoading.message}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user