workspace.tsx 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. 'use client';
  2. import { useState } from 'react';
  3. import { ArrowLeft } from 'lucide-react';
  4. import type { PBLProjectConfig } from '@/lib/pbl/types';
  5. import { IssueboardPanel } from './issueboard-panel';
  6. import { ChatPanel } from './chat-panel';
  7. import { usePBLChat } from './use-pbl-chat';
  8. import { PBLGuidePanel } from './guide';
  9. import { useI18n } from '@/lib/hooks/use-i18n';
  10. interface PBLWorkspaceProps {
  11. readonly projectConfig: PBLProjectConfig;
  12. readonly userRole: string;
  13. readonly onConfigUpdate: (config: PBLProjectConfig) => void;
  14. readonly onReset: () => void;
  15. }
  16. export function PBLWorkspace({
  17. projectConfig,
  18. userRole,
  19. onConfigUpdate,
  20. onReset,
  21. }: PBLWorkspaceProps) {
  22. const { t } = useI18n();
  23. const [showConfirm, setShowConfirm] = useState(false);
  24. const { messages, isLoading, sendMessage, currentIssue } = usePBLChat({
  25. projectConfig,
  26. userRole,
  27. onConfigUpdate,
  28. });
  29. return (
  30. <div className="flex h-full w-full">
  31. {/* Left: Issueboard (~35%) */}
  32. <div className="w-[35%] min-w-[280px] border-r overflow-hidden flex flex-col">
  33. {/* Back button bar */}
  34. <div className="px-3 pt-2 flex items-center gap-1.5">
  35. {!showConfirm ? (
  36. <div className="flex items-center gap-1 flex-1">
  37. <button
  38. onClick={() => setShowConfirm(true)}
  39. className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors px-1.5 py-1 rounded-md hover:bg-muted"
  40. >
  41. <ArrowLeft className="w-3.5 h-3.5" />
  42. <span>{t('pbl.workspace.restart')}</span>
  43. </button>
  44. <div className="ml-auto">
  45. <PBLGuidePanel />
  46. </div>
  47. </div>
  48. ) : (
  49. <div className="flex items-center gap-1.5 text-xs">
  50. <span className="text-muted-foreground">{t('pbl.workspace.confirmRestart')}</span>
  51. <button
  52. onClick={() => {
  53. setShowConfirm(false);
  54. onReset();
  55. }}
  56. className="px-2 py-0.5 rounded bg-destructive text-destructive-foreground hover:bg-destructive/90 transition-colors"
  57. >
  58. {t('pbl.workspace.confirm')}
  59. </button>
  60. <button
  61. onClick={() => setShowConfirm(false)}
  62. className="px-2 py-0.5 rounded bg-muted hover:bg-muted/80 transition-colors"
  63. >
  64. {t('pbl.workspace.cancel')}
  65. </button>
  66. </div>
  67. )}
  68. </div>
  69. <div className="flex-1 overflow-hidden">
  70. <IssueboardPanel issueboard={projectConfig.issueboard} />
  71. </div>
  72. </div>
  73. {/* Right: Chat (~65%) */}
  74. <div className="flex-1 overflow-hidden">
  75. <ChatPanel
  76. messages={messages}
  77. currentIssue={currentIssue}
  78. userRole={userRole}
  79. isLoading={isLoading}
  80. onSendMessage={sendMessage}
  81. />
  82. </div>
  83. </div>
  84. );
  85. }