Showcase.tsx 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import * as React from 'react';
  2. import { GreenPage } from '../types';
  3. import { Preview } from './Preview';
  4. import { Icon } from './ui/Icon';
  5. // FIX: Added 'generateEnterpriseShowcases' to the import as it is now correctly exported.
  6. import { generatePersonalShowcases, generateEnterpriseShowcases } from '../services/showcaseDataService';
  7. interface ShowcaseProps {
  8. initialTab: 'personal' | 'enterprise';
  9. onImportPage: (page: GreenPage) => void;
  10. }
  11. const Showcase: React.FC<ShowcaseProps> = ({ initialTab, onImportPage }) => {
  12. const [activeTab, setActiveTab] = React.useState(initialTab);
  13. const [showcasePages, setShowcasePages] = React.useState<GreenPage[]>([]);
  14. const [selectedPage, setSelectedPage] = React.useState<GreenPage | null>(null);
  15. const [previewMode, setPreviewMode] = React.useState<'personal' | 'enterprise'>(initialTab);
  16. const [deviceView, setDeviceView] = React.useState<'pc' | 'mobile'>('pc');
  17. React.useEffect(() => {
  18. const pages = activeTab === 'personal' ? generatePersonalShowcases() : generateEnterpriseShowcases();
  19. setShowcasePages(pages);
  20. setSelectedPage(pages[0] || null);
  21. setPreviewMode(activeTab);
  22. }, [activeTab]);
  23. return (
  24. <div className="flex h-full">
  25. <div className="w-1/3 max-w-sm flex flex-col border-r border-gray-200 dark:border-gray-700">
  26. <header className="p-6 border-b border-gray-200 dark:border-gray-700 flex-shrink-0">
  27. <h2 className="text-2xl font-bold text-gray-900 dark:text-white">Showcase</h2>
  28. <p className="text-gray-500 dark:text-gray-400 mt-1">Explore what you can build.</p>
  29. <div className="mt-4 flex items-center gap-1 bg-gray-200 dark:bg-gray-800 p-1 rounded-lg">
  30. <button onClick={() => setActiveTab('personal')} className={`flex-1 px-3 py-1 text-sm rounded-md capitalize transition-colors ${activeTab === 'personal' ? 'bg-brand-primary text-white shadow' : 'hover:bg-gray-300 dark:hover:bg-gray-600'}`}>Personal</button>
  31. <button onClick={() => setActiveTab('enterprise')} className={`flex-1 px-3 py-1 text-sm rounded-md capitalize transition-colors ${activeTab === 'enterprise' ? 'bg-brand-primary text-white shadow' : 'hover:bg-gray-300 dark:hover:bg-gray-600'}`}>Enterprise</button>
  32. </div>
  33. </header>
  34. <div className="flex-1 overflow-y-auto p-4 space-y-3">
  35. {showcasePages.map(page => (
  36. <button
  37. key={page.id}
  38. onClick={() => setSelectedPage(page)}
  39. className={`w-full p-4 rounded-lg text-left transition-all duration-200 ${selectedPage?.id === page.id ? 'bg-brand-primary/10 ring-2 ring-brand-primary' : 'bg-white dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-700/50'}`}
  40. >
  41. <p className="font-semibold text-gray-900 dark:text-white">{page.name}</p>
  42. <p className="text-xs text-gray-500 dark:text-gray-400 truncate">{page.slug}</p>
  43. </button>
  44. ))}
  45. </div>
  46. </div>
  47. <div className="flex-1 border-l border-gray-200 dark:border-gray-700 flex flex-col bg-gray-200 dark:bg-gray-900/50">
  48. <div className="flex-shrink-0 bg-white dark:bg-gray-800 p-2 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center">
  49. {selectedPage ? (
  50. <button
  51. onClick={() => onImportPage(selectedPage)}
  52. className="flex items-center gap-2 bg-brand-primary text-white font-semibold py-2 px-4 rounded-lg hover:bg-brand-secondary transition-colors"
  53. >
  54. <Icon className="h-5 w-5"><path strokeLinecap="round" strokeLinejoin="round" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4" /></Icon>
  55. Import Page
  56. </button>
  57. ) : <div />}
  58. <div className="flex items-center gap-1 bg-gray-200 dark:bg-gray-700 p-1 rounded-lg">
  59. <button onClick={() => setDeviceView('pc')} className={`p-2 rounded-md ${deviceView === 'pc' ? 'bg-brand-primary text-white' : ''}`}>
  60. <Icon className='h-5 w-5'><path strokeLinecap="round" strokeLinejoin="round" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /></Icon>
  61. </button>
  62. <button onClick={() => setDeviceView('mobile')} className={`p-2 rounded-md ${deviceView === 'mobile' ? 'bg-brand-primary text-white' : ''}`}>
  63. <Icon className='h-5 w-5'><path strokeLinecap="round" strokeLinejoin="round" d="M12 18h.01M7 21h10a2 2 0 002-2V5a2 2 0 00-2-2H7a2 2 0 00-2 2v14a2 2 0 002 2z" /></Icon>
  64. </button>
  65. </div>
  66. </div>
  67. <div className="flex-1 overflow-hidden relative">
  68. {selectedPage ? (
  69. <Preview
  70. key={`${selectedPage.id}-${previewMode}-${deviceView}`}
  71. pageSettings={selectedPage.pageSettings}
  72. aigcVideos={selectedPage.aigcSettings.videos}
  73. aigcArticles={selectedPage.aigcSettings.articles}
  74. previewMode={previewMode}
  75. deviceView={deviceView}
  76. // FIX: Added the required 'onFormSubmit' prop with a dummy function as it's not needed in the showcase.
  77. onFormSubmit={() => {}}
  78. />
  79. ) : (
  80. <div className="flex items-center justify-center h-full text-gray-500 dark:text-gray-400">Select a showcase to preview</div>
  81. )}
  82. </div>
  83. </div>
  84. </div>
  85. );
  86. };
  87. export default Showcase;