x
This commit is contained in:
1 parent
8d415ecef7
commit
af6047fb4d
2 files changed
+2088
-2
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -19,12 +19,15 @@ import {
|
|||||||
Copy,
|
Copy,
|
||||||
Check,
|
Check,
|
||||||
Sparkles,
|
Sparkles,
|
||||||
Globe
|
Globe,
|
||||||
|
Download,
|
||||||
|
Upload,
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { API_BASE, type Page, type PageSection, type Category } from '@homaroma/types';
|
import { API_BASE, type Page, type PageSection, type Category } from '@homaroma/types';
|
||||||
import { getAdminDisplayString } from '../utils/localization';
|
import { getAdminDisplayString } from '../utils/localization';
|
||||||
import MediaLibraryModal from '../components/MediaLibraryModal';
|
import MediaLibraryModal from '../components/MediaLibraryModal';
|
||||||
import PageSeoModal from '../components/page-builder/PageSeoModal';
|
import PageSeoModal from '../components/page-builder/PageSeoModal';
|
||||||
|
import BlockTranslationModal, { isTranslatableBlock } from '../components/page-builder/BlockTranslationModal';
|
||||||
import { useStoreSettings } from '../contexts/StoreSettingsContext';
|
import { useStoreSettings } from '../contexts/StoreSettingsContext';
|
||||||
import { getAuthHeaders } from '../utils/auth';
|
import { getAuthHeaders } from '../utils/auth';
|
||||||
|
|
||||||
@@ -189,6 +192,8 @@ export default function PageBuilderPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const [editingLang, setEditingLang] = useState('th');
|
const [editingLang, setEditingLang] = useState('th');
|
||||||
|
const [isTranslationModalOpen, setIsTranslationModalOpen] = useState(false);
|
||||||
|
const [translationModalTab, setTranslationModalTab] = useState<'export' | 'import'>('export');
|
||||||
|
|
||||||
// Helper to read localized string safely
|
// Helper to read localized string safely
|
||||||
const getLocalizedValue = (payload: any, field: string) => {
|
const getLocalizedValue = (payload: any, field: string) => {
|
||||||
@@ -1363,14 +1368,44 @@ export default function PageBuilderPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
{isTranslatableBlock(editingSection.type) && (
|
||||||
|
<div className="flex items-center gap-2 mr-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setTranslationModalTab('export');
|
||||||
|
setIsTranslationModalOpen(true);
|
||||||
|
}}
|
||||||
|
className="flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-cyan-glow/10 hover:bg-cyan-glow/20 text-cyan-glow border border-cyan-glow/20 text-xs font-bold transition-all shadow-sm cursor-pointer"
|
||||||
|
title="ส่งออกข้อความทุกภาษาเพื่อนำไปแปลด้วย LLM (Export & AI Prompt)"
|
||||||
|
>
|
||||||
|
<Download className="w-3.5 h-3.5" />
|
||||||
|
<span>Export ภาษา</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
setTranslationModalTab('import');
|
||||||
|
setIsTranslationModalOpen(true);
|
||||||
|
}}
|
||||||
|
className="flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-pop-pink/10 hover:bg-pop-pink/20 text-pop-pink border border-pop-pink/20 text-xs font-bold transition-all shadow-sm cursor-pointer"
|
||||||
|
title="วาง JSON ผลลัพธ์จาก LLM เพื่ออัปเดตทุกภาษาพร้อมกัน (Import Translations)"
|
||||||
|
>
|
||||||
|
<Upload className="w-3.5 h-3.5" />
|
||||||
|
<span>Import ภาษา</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setEditingSection(null)}
|
onClick={() => setEditingSection(null)}
|
||||||
className="p-2 rounded-xl hover:bg-white/5 text-slate-400 hover:text-white transition-all"
|
className="p-2 rounded-xl hover:bg-white/5 text-slate-400 hover:text-white transition-all cursor-pointer"
|
||||||
>
|
>
|
||||||
<X className="w-6 h-6" />
|
<X className="w-6 h-6" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Premium Sub-header for Language Tabs */}
|
{/* Premium Sub-header for Language Tabs */}
|
||||||
<div className="px-8 py-4 border-b border-white/5 bg-night-950/50 flex items-center overflow-x-auto hide-scrollbar">
|
<div className="px-8 py-4 border-b border-white/5 bg-night-950/50 flex items-center overflow-x-auto hide-scrollbar">
|
||||||
@@ -2155,6 +2190,17 @@ export default function PageBuilderPage() {
|
|||||||
}}
|
}}
|
||||||
frontendBaseUrl={frontendBase}
|
frontendBaseUrl={frontendBase}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<BlockTranslationModal
|
||||||
|
isOpen={isTranslationModalOpen}
|
||||||
|
onClose={() => setIsTranslationModalOpen(false)}
|
||||||
|
section={editingSection}
|
||||||
|
pageSlug={page?.slug}
|
||||||
|
initialTab={translationModalTab}
|
||||||
|
onApplyTranslations={(updatedPayload) => {
|
||||||
|
setEditingSection((prev) => (prev ? { ...prev, payload: updatedPayload } : null));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user