1→import { useEffect, useState } from 'react'
     2→import { useSearchParams } from 'react-router-dom'
     3→import { useProjectStore } from '../stores/projectStore'
     4→import { useToastStore } from '../components/Toast'
     5→import {
     6→  FileText,
     7→  RefreshCw,
     8→  History,
     9→  Clock,
    10→  Check,
    11→  ChevronDown,
    12→  ChevronUp,
    13→  Edit3,
    14→  Save,
    15→  X,
    16→  Loader2,
    17→} from 'lucide-react'
    18→import * as Dialog from '@radix-ui/react-dialog'
    19→
    20→interface Spec {
    21→  id: number
    22→  project_id: number
    23→  version: number
    24→  content: string
    25→  is_active: boolean
    26→  parent_spec_id: number | null
    27→  created_at: string
    28→}
    29→
    30→export default function SpecEditor() {
    31→  const [searchParams] = useSearchParams()
    32→  const { currentProject } = useProjectStore()
    33→  const { addToast } = useToastStore()
    34→
    35→  const [currentSpec, setCurrentSpec] = useState<Spec | null>(null)
    36→  const [specHistory, setSpecHistory] = useState<Spec[]>([])
    37→  const [isLoading, setIsLoading] = useState(true)
    38→  const [showHistory, setShowHistory] = useState(false)
    39→  const [showRespecDialog, setShowRespecDialog] = useState(false)
    40→  const [respecContent, setRespecContent] = useState('')
    41→  const [isSubmitting, setIsSubmitting] = useState(false)
    42→
    43→  // Edit mode
    44→  const [isEditing, setIsEditing] = useState(false)
    45→  const [editContent, setEditContent] = useState('')
    46→  const [isSaving, setIsSaving] = useState(false)
    47→
    48→  // Fetch spec data when project changes
    49→  useEffect(() => {
    50→    if (currentProject) {
    51→      fetchSpec()
    52→      fetchSpecHistory()
    53→    } else {
    54→      setCurrentSpec(null)
    55→      setSpecHistory([])
    56→      setIsLoading(false)
    57→    }
    58→  }, [currentProject])
    59→
    60→  const fetchSpec = async () => {
    61→    if (!currentProject) return
    62→
    63→    try {
    64→      const response = await fetch(
    65→        `http://localhost:8000/api/projects/${currentProject.id}/spec`
    66→      )
    67→      if (response.ok) {
    68→        const data = await response.json()
    69→        setCurrentSpec(data)
    70→        setEditContent(data.content)
    71→      } else if (response.status === 404) {
    72→        setCurrentSpec(null)
    73→      }
    74→    } catch (error) {
    75→      console.error('Failed to fetch spec:', error)
    76→    } finally {
    77→      setIsLoading(false)
    78→    }
    79→  }
    80→
    81→  const fetchSpecHistory = async () => {
    82→    if (!currentProject) return
    83→
    84→    try {
    85→      const response = await fetch(
    86→        `http://localhost:8000/api/projects/${currentProject.id}/spec/history`
    87→      )
    88→      if (response.ok) {
    89→        const data = await response.json()
    90→        setSpecHistory(data)
    91→      }
    92→    } catch (error) {
    93→      console.error('Failed to fetch spec history:', error)
    94→    }
    95→  }
    96→
    97→  const handleCreateSpec = async () => {
    98→    if (!currentProject || !editContent.trim()) return
    99→
   100→    setIsSaving(true)
   101→    try {
   102→      const response = await fetch(
   103→        `http://localhost:8000/api/projects/${currentProject.id}/spec`,
   104→        {
   105→          method: 'POST',
   106→          headers: { 'Content-Type': 'application/json' },
   107→          body: JSON.stringify({ content: editContent }),
   108→        }
   109→      )
   110→
   111→      if (!response.ok) {
   112→        throw new Error('Failed to create spec')
   113→      }
   114→
   115→      const data = await response.json()
   116→      setCurrentSpec(data)
   117→      setIsEditing(false)
   118→      addToast('success', 'Spec Created', 'Project specification has been saved')
   119→      fetchSpecHistory()
   120→    } catch (error) {
   121→      console.error('Failed to create spec:', error)
   122→      addToast('error', 'Save Failed', 'Failed to save specification')
   123→    } finally {
   124→      setIsSaving(false)
   125→    }
   126→  }
   127→
   128→  const handleRespec = async () => {
   129→    if (!currentProject || !respecContent.trim()) return
   130→
   131→    setIsSubmitting(true)
   132→    try {
   133→      const response = await fetch(
   134→        `http://localhost:8000/api/projects/${currentProject.id}/respec`,
   135→        {
   136→          method: 'POST',
   137→          headers: { 'Content-Type': 'application/json' },
   138→          body: JSON.stringify({ content: respecContent }),
   139→        }
   140→      )
   141→
   142→      if (!response.ok) {
   143→        throw new Error('Failed to create Re-Spec')
   144→      }
   145→
   146→      const data = await response.json()
   147→      setCurrentSpec(data)
   148→      setEditContent(data.content)
   149→      setShowRespecDialog(false)
   150→      setRespecContent('')
   151→      addToast('success', 'Re-Spec Complete', `Created spec version ${data.version}`)
   152→      fetchSpecHistory()
   153→    } catch (error) {
   154→      console.error('Failed to respec:', error)
   155→      addToast('error', 'Re-Spec Failed', 'Failed to create new specification version')
   156→    } finally {
   157→      setIsSubmitting(false)
   158→    }
   159→  }
   160→
   161→  const openRespecDialog = () => {
   162→    // Pre-populate with current spec content
   163→    setRespecContent(currentSpec?.content || '')
   164→    setShowRespecDialog(true)
   165→  }
   166→
   167→  const formatDate = (dateStr: string) => {
   168→    return new Date(dateStr).toLocaleString()
   169→  }
   170→
   171→  if (!currentProject) {
   172→    return (
   173→

   174→        <FileText size={64} className="text-muted-foreground mb-4" />
   175→

   176→          No Project Selected
   177→

   178→

   179→          Select a project from the sidebar to view and edit its specification.
   180→

   181→

   182→    )
   183→  }
   184→
   185→  if (isLoading) {
   186→    return (
   187→

   188→        <Loader2 className="animate-spin text-accent" size={32} />
   189→

   190→    )
   191→  }
   192→
   193→  return (
   194→

   195→      {/* Header */}
   196→

   197→

   198→
Specification

   199→

   200→            {currentSpec
   201→              ? `Version ${currentSpec.version} - Last updated ${formatDate(currentSpec.created_at)}`
   202→              : 'No specification created yet'}
   203→

   204→

   205→

   206→          {currentSpec && (
   207→            <>
   208→              <button
   209→                onClick={() => setShowHistory(!showHistory)}
   210→                className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
   211→              >
   212→                <History size={16} />
   213→                History ({specHistory.length})
   214→                {showHistory ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
   215→              </button>
   216→              <button
   217→                onClick={openRespecDialog}
   218→                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors"
   219→              >
   220→                <RefreshCw size={16} />
   221→                Re-Spec
   222→              </button>
   223→            </>
   224→          )}
   225→

   226→

   227→
   228→      {/* Spec History Panel */}
   229→      {showHistory && specHistory.length > 0 && (
   230→

   231→

   232→            <History size={18} className="text-accent" />
   233→            Specification History
   234→

   235→

   236→            {specHistory.map((spec) => (
   237→

   245→

   246→

   251→

   252→

   253→                      Version {spec.version}
   254→                      {spec.is_active && (
   255→                        (Active)
   256→                      )}
   257→

   258→

   259→                      {formatDate(spec.created_at)}
   260→

   261→

   262→

   263→                {spec.parent_spec_id && (
   264→
   265→                    Re-Spec from v{specHistory.find((s) => s.id === spec.parent_spec_id)?.version || '?'}
   266→
   267→                )}
   268→

   269→            ))}
   270→

   271→

   272→      )}
   273→
   274→      {/* Spec Content */}
   275→

   276→

   277→

   278→            <FileText size={18} className="text-accent" />
   279→            {currentSpec ? 'Current Specification' : 'Create Specification'}
   280→

   281→          {currentSpec && !isEditing && (
   282→            <button
   283→              onClick={() => setIsEditing(true)}
   284→              className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
   285→            >
   286→              <Edit3 size={14} />
   287→              Edit
   288→            </button>
   289→          )}
   290→          {isEditing && (
   291→

   292→              <button
   293→                onClick={() => {
   294→                  setIsEditing(false)
   295→                  setEditContent(currentSpec?.content || '')
   296→                }}
   297→                className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
   298→              >
   299→                <X size={14} />
   300→                Cancel
   301→              </button>
   302→              <button
   303→                onClick={handleCreateSpec}
   304→                disabled={isSaving || !editContent.trim()}
   305→                className="flex items-center gap-2 px-3 py-1.5 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
   306→              >
   307→                {isSaving ? (
   308→                  <Loader2 size={14} className="animate-spin" />
   309→                ) : (
   310→                  <Save size={14} />
   311→                )}
   312→                Save
   313→              </button>
   314→

   315→          )}
   316→

   317→
   318→

   319→          {isEditing || !currentSpec ? (
   320→            <textarea
   321→              value={editContent}
   322→              onChange={(e) => setEditContent(e.target.value)}
   323→              placeholder="Enter your project specification here...
   324→
   325→Describe your project's:
   326→- Purpose and goals
   327→- Key features and functionality
   328→- Technical requirements
   329→- User interface guidelines
   330→- Any constraints or considerations"
   331→              rows={20}
   332→              className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
   333→            />
   334→          ) : (
   335→

   336→

   337→                {currentSpec.content}
   338→

   339→

   340→          )}
   341→
   342→          {!currentSpec && !isEditing && (
   343→

   344→              <FileText size={48} className="mx-auto text-muted-foreground mb-4" />
   345→

   346→                No specification has been created for this project yet.
   347→

   348→              <button
   349→                onClick={() => setIsEditing(true)}
   350→                className="btn-accent"
   351→              >
   352→                Create Specification
   353→              </button>
   354→

   355→          )}
   356→

   357→

   358→
   359→      {/* Re-Spec Dialog */}
   360→      <Dialog.Root open={showRespecDialog} onOpenChange={setShowRespecDialog}>
   361→        <Dialog.Portal>
   362→          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
   363→          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-6 w-[calc(100%-2rem)] max-w-2xl max-h-[calc(100vh-4rem)] overflow-y-auto z-50 shadow-xl">
   364→

   365→              <Dialog.Title className="text-xl font-semibold text-foreground flex items-center gap-2">
   366→                <RefreshCw size={20} className="text-accent" />
   367→                Re-Spec Project
   368→              </Dialog.Title>
   369→              <Dialog.Close asChild>
   370→                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors">
   371→                  <X size={20} />
   372→                </button>
   373→              </Dialog.Close>
   374→

   375→
   376→            <Dialog.Description className="text-muted-foreground mb-4">
   377→              Create a new specification version. The current specification is shown below for
   378→              reference. Modify it to reflect your updated requirements.
   379→            </Dialog.Description>
   380→
   381→            {currentSpec && (
   382→

   383→

   384→                  Previous Context (Version {currentSpec.version})
   385→

   386→

   387→                  {currentSpec.content.substring(0, 200)}...
   388→

   389→

   390→            )}
   391→
   392→

   393→
   394→                Updated Specification *
   395→
   396→              <textarea
   397→                value={respecContent}
   398→                onChange={(e) => setRespecContent(e.target.value)}
   399→                placeholder="Enter your updated project specification..."
   400→                rows={12}
   401→                className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
   402→              />
   403→

   404→
   405→

   406→              <Dialog.Close asChild>
   407→                <button className="px-4 py-2 text-sm text-muted-foreground hover:bg-secondary rounded-lg transition-colors">
   408→                  Cancel
   409→                </button>
   410→              </Dialog.Close>
   411→              <button
   412→                onClick={handleRespec}
   413→                disabled={isSubmitting || !respecContent.trim()}
   414→                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
   415→              >
   416→                {isSubmitting ? (
   417→                  <>
   418→                    <Loader2 size={16} className="animate-spin" />
   419→                    Creating...
   420→                  </>
   421→                ) : (
   422→                  <>
   423→                    <Check size={16} />
   424→                    Create Re-Spec
   425→                  </>
   426→                )}
   427→              </button>
   428→

   429→          </Dialog.Content>
   430→        </Dialog.Portal>
   431→      </Dialog.Root>
   432→

   433→  )
   434→}
   435→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import { useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { useProjectStore } from '../stores/projectStore'
import { useToastStore } from '../components/Toast'
import {
  FileText,
  RefreshCw,
  History,
  Clock,
  Check,
  ChevronDown,
  ChevronUp,
  Edit3,
  Save,
  X,
  Loader2,
} from 'lucide-react'
import * as Dialog from '@radix-ui/react-dialog'

interface Spec {
  id: number
  project_id: number
  version: number
  content: string
  is_active: boolean
  parent_spec_id: number | null
  created_at: string
}

export default function SpecEditor() {
  const [searchParams] = useSearchParams()
  const { currentProject } = useProjectStore()
  const { addToast } = useToastStore()

  const [currentSpec, setCurrentSpec] = useState<Spec | null>(null)
  const [specHistory, setSpecHistory] = useState<Spec[]>([])
  const [isLoading, setIsLoading] = useState(true)
  const [showHistory, setShowHistory] = useState(false)
  const [showRespecDialog, setShowRespecDialog] = useState(false)
  const [respecContent, setRespecContent] = useState('')
  const [isSubmitting, setIsSubmitting] = useState(false)

  // Edit mode
  const [isEditing, setIsEditing] = useState(false)
  const [editContent, setEditContent] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // Fetch spec data when project changes
  useEffect(() => {
    if (currentProject) {
      fetchSpec()
      fetchSpecHistory()
    } else {
      setCurrentSpec(null)
      setSpecHistory([])
      setIsLoading(false)
    }
  }, [currentProject])

  const fetchSpec = async () => {
    if (!currentProject) return

    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec`
      )
      if (response.ok) {
        const data = await response.json()
        setCurrentSpec(data)
        setEditContent(data.content)
      } else if (response.status === 404) {
        setCurrentSpec(null)
      }
    } catch (error) {
      console.error('Failed to fetch spec:', error)
    } finally {
      setIsLoading(false)
    }
  }

  const fetchSpecHistory = async () => {
    if (!currentProject) return

    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec/history`
      )
      if (response.ok) {
        const data = await response.json()
        setSpecHistory(data)
      }
    } catch (error) {
      console.error('Failed to fetch spec history:', error)
    }
  }

  const handleCreateSpec = async () => {
    if (!currentProject || !editContent.trim()) return

    setIsSaving(true)
    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ content: editContent }),
        }
      )

      if (!response.ok) {
        throw new Error('Failed to create spec')
      }

      const data = await response.json()
      setCurrentSpec(data)
      setIsEditing(false)
      addToast('success', 'Spec Created', 'Project specification has been saved')
      fetchSpecHistory()
    } catch (error) {
      console.error('Failed to create spec:', error)
      addToast('error', 'Save Failed', 'Failed to save specification')
    } finally {
      setIsSaving(false)
    }
  }

  const handleRespec = async () => {
    if (!currentProject || !respecContent.trim()) return

    setIsSubmitting(true)
    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/respec`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ content: respecContent }),
        }
      )

      if (!response.ok) {
        throw new Error('Failed to create Re-Spec')
      }

      const data = await response.json()
      setCurrentSpec(data)
      setEditContent(data.content)
      setShowRespecDialog(false)
      setRespecContent('')
      addToast('success', 'Re-Spec Complete', `Created spec version ${data.version}`)
      fetchSpecHistory()
    } catch (error) {
      console.error('Failed to respec:', error)
      addToast('error', 'Re-Spec Failed', 'Failed to create new specification version')
    } finally {
      setIsSubmitting(false)
    }
  }

  const openRespecDialog = () => {
    // Pre-populate with current spec content
    setRespecContent(currentSpec?.content || '')
    setShowRespecDialog(true)
  }

  const formatDate = (dateStr: string) => {
    return new Date(dateStr).toLocaleString()
  }

  if (!currentProject) {
    return (

        <FileText size={64} className="text-muted-foreground mb-4" />

          No Project Selected

          Select a project from the sidebar to view and edit its specification.

    )
  }

  if (isLoading) {
    return (

        <Loader2 className="animate-spin text-accent" size={32} />

    )
  }

  return (

      {/* Header */}

Specification

            {currentSpec
              ? `Version ${currentSpec.version} - Last updated ${formatDate(currentSpec.created_at)}`
              : 'No specification created yet'}

          {currentSpec && (
            <>
              <button
                onClick={() => setShowHistory(!showHistory)}
                className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
              >
                <History size={16} />
                History ({specHistory.length})
                {showHistory ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
              </button>
              <button
                onClick={openRespecDialog}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors"
              >
                <RefreshCw size={16} />
                Re-Spec
              </button>
            </>
          )}

      {/* Spec History Panel */}
      {showHistory && specHistory.length > 0 && (

            <History size={18} className="text-accent" />
            Specification History

            {specHistory.map((spec) => (

                      Version {spec.version}
                      {spec.is_active && (
                        (Active)
                      )}

                      {formatDate(spec.created_at)}

                {spec.parent_spec_id && (

                    Re-Spec from v{specHistory.find((s) => s.id === spec.parent_spec_id)?.version || '?'}

                )}

            ))}

      )}

      {/* Spec Content */}

            <FileText size={18} className="text-accent" />
            {currentSpec ? 'Current Specification' : 'Create Specification'}

          {currentSpec && !isEditing && (
            <button
              onClick={() => setIsEditing(true)}
              className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
            >
              <Edit3 size={14} />
              Edit
            </button>
          )}
          {isEditing && (

              <button
                onClick={() => {
                  setIsEditing(false)
                  setEditContent(currentSpec?.content || '')
                }}
                className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
              >
                <X size={14} />
                Cancel
              </button>
              <button
                onClick={handleCreateSpec}
                disabled={isSaving || !editContent.trim()}
                className="flex items-center gap-2 px-3 py-1.5 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSaving ? (
                  <Loader2 size={14} className="animate-spin" />
                ) : (
                  <Save size={14} />
                )}
                Save
              </button>

          )}

          {isEditing || !currentSpec ? (
            <textarea
              value={editContent}
              onChange={(e) => setEditContent(e.target.value)}
              placeholder="Enter your project specification here...

Describe your project's:
- Purpose and goals
- Key features and functionality
- Technical requirements
- User interface guidelines
- Any constraints or considerations"
              rows={20}
              className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
            />
          ) : (

                {currentSpec.content}

          )}

          {!currentSpec && !isEditing && (

              <FileText size={48} className="mx-auto text-muted-foreground mb-4" />

                No specification has been created for this project yet.

              <button
                onClick={() => setIsEditing(true)}
                className="btn-accent"
              >
                Create Specification
              </button>

          )}

      {/* Re-Spec Dialog */}
      <Dialog.Root open={showRespecDialog} onOpenChange={setShowRespecDialog}>
        <Dialog.Portal>
          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-6 w-[calc(100%-2rem)] max-w-2xl max-h-[calc(100vh-4rem)] overflow-y-auto z-50 shadow-xl">

              <Dialog.Title className="text-xl font-semibold text-foreground flex items-center gap-2">
                <RefreshCw size={20} className="text-accent" />
                Re-Spec Project
              </Dialog.Title>
              <Dialog.Close asChild>
                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors">
                  <X size={20} />
                </button>
              </Dialog.Close>

            <Dialog.Description className="text-muted-foreground mb-4">
              Create a new specification version. The current specification is shown below for
              reference. Modify it to reflect your updated requirements.
            </Dialog.Description>

            {currentSpec && (

                  Previous Context (Version {currentSpec.version})

                  {currentSpec.content.substring(0, 200)}...

            )}

                Updated Specification *

              <textarea
                value={respecContent}
                onChange={(e) => setRespecContent(e.target.value)}
                placeholder="Enter your updated project specification..."
                rows={12}
                className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
              />

              <Dialog.Close asChild>
                <button className="px-4 py-2 text-sm text-muted-foreground hover:bg-secondary rounded-lg transition-colors">
                  Cancel
                </button>
              </Dialog.Close>
              <button
                onClick={handleRespec}
                disabled={isSubmitting || !respecContent.trim()}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSubmitting ? (
                  <>
                    <Loader2 size={16} className="animate-spin" />
                    Creating...
                  </>
                ) : (
                  <>
                    <Check size={16} />
                    Create Re-Spec
                  </>
                )}
              </button>

          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>

  )
}


I need to add functionality to view historical spec versions. I'll add:
1. A state variable to track the selected/viewing spec version
2. A click handler on history items
3. A dialog or panel to view the historical content
4. An "Eye" icon from lucide-react for viewing


Edit

import {
  FileText,
  RefreshCw,
  History,
  Clock,
  Check,
  ChevronDown,
  ChevronUp,
  Edit3,
  Save,
  X,
  Loader2,
} from 'lucide-react'

import {
  FileText,
  RefreshCw,
  History,
  Clock,
  Check,
  ChevronDown,
  ChevronUp,
  Edit3,
  Save,
  X,
  Loader2,
  Eye,
} from 'lucide-react'


The file C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/SpecEditor.tsx has been updated. Here's the result of running `cat -n` on a snippet of the edited file:
     1→import { useEffect, useState } from 'react'
     2→import { useSearchParams } from 'react-router-dom'
     3→import { useProjectStore } from '../stores/projectStore'
     4→import { useToastStore } from '../components/Toast'
     5→import {
     6→  FileText,
     7→  RefreshCw,
     8→  History,
     9→  Clock,
    10→  Check,
    11→  ChevronDown,
    12→  ChevronUp,
    13→  Edit3,
    14→  Save,
    15→  X,
    16→  Loader2,
    17→  Eye,
    18→} from 'lucide-react'
    19→import * as Dialog from '@radix-ui/react-dialog'
    20→
    21→interface Spec {
    22→  id: number

import {
  FileText,
  RefreshCw,
  History,
  Clock,
  Check,
  ChevronDown,
  ChevronUp,
  Edit3,
  Save,
  X,
  Loader2,
  Eye,
} from 'lucide-react'

import { useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { useProjectStore } from '../stores/projectStore'
import { useToastStore } from '../components/Toast'
import {
  FileText,
  RefreshCw,
  History,
  Clock,
  Check,
  ChevronDown,
  ChevronUp,
  Edit3,
  Save,
  X,
  Loader2,
} from 'lucide-react'
import * as Dialog from '@radix-ui/react-dialog'

interface Spec {
  id: number
  project_id: number
  version: number
  content: string
  is_active: boolean
  parent_spec_id: number | null
  created_at: string
}

export default function SpecEditor() {
  const [searchParams] = useSearchParams()
  const { currentProject } = useProjectStore()
  const { addToast } = useToastStore()

  const [currentSpec, setCurrentSpec] = useState<Spec | null>(null)
  const [specHistory, setSpecHistory] = useState<Spec[]>([])
  const [isLoading, setIsLoading] = useState(true)
  const [showHistory, setShowHistory] = useState(false)
  const [showRespecDialog, setShowRespecDialog] = useState(false)
  const [respecContent, setRespecContent] = useState('')
  const [isSubmitting, setIsSubmitting] = useState(false)

  // Edit mode
  const [isEditing, setIsEditing] = useState(false)
  const [editContent, setEditContent] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // Fetch spec data when project changes
  useEffect(() => {
    if (currentProject) {
      fetchSpec()
      fetchSpecHistory()
    } else {
      setCurrentSpec(null)
      setSpecHistory([])
      setIsLoading(false)
    }
  }, [currentProject])

  const fetchSpec = async () => {
    if (!currentProject) return

    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec`
      )
      if (response.ok) {
        const data = await response.json()
        setCurrentSpec(data)
        setEditContent(data.content)
      } else if (response.status === 404) {
        setCurrentSpec(null)
      }
    } catch (error) {
      console.error('Failed to fetch spec:', error)
    } finally {
      setIsLoading(false)
    }
  }

  const fetchSpecHistory = async () => {
    if (!currentProject) return

    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec/history`
      )
      if (response.ok) {
        const data = await response.json()
        setSpecHistory(data)
      }
    } catch (error) {
      console.error('Failed to fetch spec history:', error)
    }
  }

  const handleCreateSpec = async () => {
    if (!currentProject || !editContent.trim()) return

    setIsSaving(true)
    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ content: editContent }),
        }
      )

      if (!response.ok) {
        throw new Error('Failed to create spec')
      }

      const data = await response.json()
      setCurrentSpec(data)
      setIsEditing(false)
      addToast('success', 'Spec Created', 'Project specification has been saved')
      fetchSpecHistory()
    } catch (error) {
      console.error('Failed to create spec:', error)
      addToast('error', 'Save Failed', 'Failed to save specification')
    } finally {
      setIsSaving(false)
    }
  }

  const handleRespec = async () => {
    if (!currentProject || !respecContent.trim()) return

    setIsSubmitting(true)
    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/respec`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ content: respecContent }),
        }
      )

      if (!response.ok) {
        throw new Error('Failed to create Re-Spec')
      }

      const data = await response.json()
      setCurrentSpec(data)
      setEditContent(data.content)
      setShowRespecDialog(false)
      setRespecContent('')
      addToast('success', 'Re-Spec Complete', `Created spec version ${data.version}`)
      fetchSpecHistory()
    } catch (error) {
      console.error('Failed to respec:', error)
      addToast('error', 'Re-Spec Failed', 'Failed to create new specification version')
    } finally {
      setIsSubmitting(false)
    }
  }

  const openRespecDialog = () => {
    // Pre-populate with current spec content
    setRespecContent(currentSpec?.content || '')
    setShowRespecDialog(true)
  }

  const formatDate = (dateStr: string) => {
    return new Date(dateStr).toLocaleString()
  }

  if (!currentProject) {
    return (

        <FileText size={64} className="text-muted-foreground mb-4" />

          No Project Selected

          Select a project from the sidebar to view and edit its specification.

    )
  }

  if (isLoading) {
    return (

        <Loader2 className="animate-spin text-accent" size={32} />

    )
  }

  return (

      {/* Header */}

Specification

            {currentSpec
              ? `Version ${currentSpec.version} - Last updated ${formatDate(currentSpec.created_at)}`
              : 'No specification created yet'}

          {currentSpec && (
            <>
              <button
                onClick={() => setShowHistory(!showHistory)}
                className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
              >
                <History size={16} />
                History ({specHistory.length})
                {showHistory ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
              </button>
              <button
                onClick={openRespecDialog}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors"
              >
                <RefreshCw size={16} />
                Re-Spec
              </button>
            </>
          )}

      {/* Spec History Panel */}
      {showHistory && specHistory.length > 0 && (

            <History size={18} className="text-accent" />
            Specification History

            {specHistory.map((spec) => (

                      Version {spec.version}
                      {spec.is_active && (
                        (Active)
                      )}

                      {formatDate(spec.created_at)}

                {spec.parent_spec_id && (

                    Re-Spec from v{specHistory.find((s) => s.id === spec.parent_spec_id)?.version || '?'}

                )}

            ))}

      )}

      {/* Spec Content */}

            <FileText size={18} className="text-accent" />
            {currentSpec ? 'Current Specification' : 'Create Specification'}

          {currentSpec && !isEditing && (
            <button
              onClick={() => setIsEditing(true)}
              className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
            >
              <Edit3 size={14} />
              Edit
            </button>
          )}
          {isEditing && (

              <button
                onClick={() => {
                  setIsEditing(false)
                  setEditContent(currentSpec?.content || '')
                }}
                className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
              >
                <X size={14} />
                Cancel
              </button>
              <button
                onClick={handleCreateSpec}
                disabled={isSaving || !editContent.trim()}
                className="flex items-center gap-2 px-3 py-1.5 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSaving ? (
                  <Loader2 size={14} className="animate-spin" />
                ) : (
                  <Save size={14} />
                )}
                Save
              </button>

          )}

          {isEditing || !currentSpec ? (
            <textarea
              value={editContent}
              onChange={(e) => setEditContent(e.target.value)}
              placeholder="Enter your project specification here...

Describe your project's:
- Purpose and goals
- Key features and functionality
- Technical requirements
- User interface guidelines
- Any constraints or considerations"
              rows={20}
              className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
            />
          ) : (

                {currentSpec.content}

          )}

          {!currentSpec && !isEditing && (

              <FileText size={48} className="mx-auto text-muted-foreground mb-4" />

                No specification has been created for this project yet.

              <button
                onClick={() => setIsEditing(true)}
                className="btn-accent"
              >
                Create Specification
              </button>

          )}

      {/* Re-Spec Dialog */}
      <Dialog.Root open={showRespecDialog} onOpenChange={setShowRespecDialog}>
        <Dialog.Portal>
          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-6 w-[calc(100%-2rem)] max-w-2xl max-h-[calc(100vh-4rem)] overflow-y-auto z-50 shadow-xl">

              <Dialog.Title className="text-xl font-semibold text-foreground flex items-center gap-2">
                <RefreshCw size={20} className="text-accent" />
                Re-Spec Project
              </Dialog.Title>
              <Dialog.Close asChild>
                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors">
                  <X size={20} />
                </button>
              </Dialog.Close>

            <Dialog.Description className="text-muted-foreground mb-4">
              Create a new specification version. The current specification is shown below for
              reference. Modify it to reflect your updated requirements.
            </Dialog.Description>

            {currentSpec && (

                  Previous Context (Version {currentSpec.version})

                  {currentSpec.content.substring(0, 200)}...

            )}

                Updated Specification *

              <textarea
                value={respecContent}
                onChange={(e) => setRespecContent(e.target.value)}
                placeholder="Enter your updated project specification..."
                rows={12}
                className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
              />

              <Dialog.Close asChild>
                <button className="px-4 py-2 text-sm text-muted-foreground hover:bg-secondary rounded-lg transition-colors">
                  Cancel
                </button>
              </Dialog.Close>
              <button
                onClick={handleRespec}
                disabled={isSubmitting || !respecContent.trim()}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSubmitting ? (
                  <>
                    <Loader2 size={16} className="animate-spin" />
                    Creating...
                  </>
                ) : (
                  <>
                    <Check size={16} />
                    Create Re-Spec
                  </>
                )}
              </button>

          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>

  )
}


  // Edit mode
  const [isEditing, setIsEditing] = useState(false)
  const [editContent, setEditContent] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // Edit mode
  const [isEditing, setIsEditing] = useState(false)
  const [editContent, setEditContent] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // View historical version
  const [viewingSpec, setViewingSpec] = useState<Spec | null>(null)
  const [showViewDialog, setShowViewDialog] = useState(false)


<tool_use_error>File has been modified since read, either by the user or by a linter. Read it again before attempting to write it.</tool_use_error>

Error: File has been modified since read, either by the user or by a linter. Read it again before attempting to write it.


1→import { useEffect, useState } from 'react'
     2→import { useSearchParams } from 'react-router-dom'
     3→import { useProjectStore } from '../stores/projectStore'
     4→import { useToastStore } from '../components/Toast'
     5→import {
     6→  FileText,
     7→  RefreshCw,
     8→  History,
     9→  Clock,
    10→  Check,
    11→  ChevronDown,
    12→  ChevronUp,
    13→  Edit3,
    14→  Save,
    15→  X,
    16→  Loader2,
    17→  Eye,
    18→} from 'lucide-react'
    19→import * as Dialog from '@radix-ui/react-dialog'
    20→
    21→interface Spec {
    22→  id: number
    23→  project_id: number
    24→  version: number
    25→  content: string
    26→  is_active: boolean
    27→  parent_spec_id: number | null
    28→  created_at: string
    29→}
    30→
    31→export default function SpecEditor() {
    32→  const [searchParams] = useSearchParams()
    33→  const { currentProject } = useProjectStore()
    34→  const { addToast } = useToastStore()
    35→
    36→  const [currentSpec, setCurrentSpec] = useState<Spec | null>(null)
    37→  const [specHistory, setSpecHistory] = useState<Spec[]>([])
    38→  const [isLoading, setIsLoading] = useState(true)
    39→  const [showHistory, setShowHistory] = useState(false)
    40→  const [showRespecDialog, setShowRespecDialog] = useState(false)
    41→  const [respecContent, setRespecContent] = useState('')
    42→  const [isSubmitting, setIsSubmitting] = useState(false)
    43→
    44→  // Edit mode
    45→  const [isEditing, setIsEditing] = useState(false)
    46→  const [editContent, setEditContent] = useState('')
    47→  const [isSaving, setIsSaving] = useState(false)
    48→
    49→  // Fetch spec data when project changes
    50→  useEffect(() => {
    51→    if (currentProject) {
    52→      fetchSpec()
    53→      fetchSpecHistory()
    54→    } else {
    55→      setCurrentSpec(null)
    56→      setSpecHistory([])
    57→      setIsLoading(false)
    58→    }
    59→  }, [currentProject])
    60→
    61→  const fetchSpec = async () => {
    62→    if (!currentProject) return
    63→
    64→    try {
    65→      const response = await fetch(
    66→        `http://localhost:8000/api/projects/${currentProject.id}/spec`
    67→      )
    68→      if (response.ok) {
    69→        const data = await response.json()
    70→        setCurrentSpec(data)
    71→        setEditContent(data.content)
    72→      } else if (response.status === 404) {
    73→        setCurrentSpec(null)
    74→      }
    75→    } catch (error) {
    76→      console.error('Failed to fetch spec:', error)
    77→    } finally {
    78→      setIsLoading(false)
    79→    }
    80→  }
    81→
    82→  const fetchSpecHistory = async () => {
    83→    if (!currentProject) return
    84→
    85→    try {
    86→      const response = await fetch(
    87→        `http://localhost:8000/api/projects/${currentProject.id}/spec/history`
    88→      )
    89→      if (response.ok) {
    90→        const data = await response.json()
    91→        setSpecHistory(data)
    92→      }
    93→    } catch (error) {
    94→      console.error('Failed to fetch spec history:', error)
    95→    }
    96→  }
    97→
    98→  const handleCreateSpec = async () => {
    99→    if (!currentProject || !editContent.trim()) return
   100→
   101→    setIsSaving(true)
   102→    try {
   103→      const response = await fetch(
   104→        `http://localhost:8000/api/projects/${currentProject.id}/spec`,
   105→        {
   106→          method: 'POST',
   107→          headers: { 'Content-Type': 'application/json' },
   108→          body: JSON.stringify({ content: editContent }),
   109→        }
   110→      )
   111→
   112→      if (!response.ok) {
   113→        throw new Error('Failed to create spec')
   114→      }
   115→
   116→      const data = await response.json()
   117→      setCurrentSpec(data)
   118→      setIsEditing(false)
   119→      addToast('success', 'Spec Created', 'Project specification has been saved')
   120→      fetchSpecHistory()
   121→    } catch (error) {
   122→      console.error('Failed to create spec:', error)
   123→      addToast('error', 'Save Failed', 'Failed to save specification')
   124→    } finally {
   125→      setIsSaving(false)
   126→    }
   127→  }
   128→
   129→  const handleRespec = async () => {
   130→    if (!currentProject || !respecContent.trim()) return
   131→
   132→    setIsSubmitting(true)
   133→    try {
   134→      const response = await fetch(
   135→        `http://localhost:8000/api/projects/${currentProject.id}/respec`,
   136→        {
   137→          method: 'POST',
   138→          headers: { 'Content-Type': 'application/json' },
   139→          body: JSON.stringify({ content: respecContent }),
   140→        }
   141→      )
   142→
   143→      if (!response.ok) {
   144→        throw new Error('Failed to create Re-Spec')
   145→      }
   146→
   147→      const data = await response.json()
   148→      setCurrentSpec(data)
   149→      setEditContent(data.content)
   150→      setShowRespecDialog(false)
   151→      setRespecContent('')
   152→      addToast('success', 'Re-Spec Complete', `Created spec version ${data.version}`)
   153→      fetchSpecHistory()
   154→    } catch (error) {
   155→      console.error('Failed to respec:', error)
   156→      addToast('error', 'Re-Spec Failed', 'Failed to create new specification version')
   157→    } finally {
   158→      setIsSubmitting(false)
   159→    }
   160→  }
   161→
   162→  const openRespecDialog = () => {
   163→    // Pre-populate with current spec content
   164→    setRespecContent(currentSpec?.content || '')
   165→    setShowRespecDialog(true)
   166→  }
   167→
   168→  const formatDate = (dateStr: string) => {
   169→    return new Date(dateStr).toLocaleString()
   170→  }
   171→
   172→  if (!currentProject) {
   173→    return (
   174→

   175→        <FileText size={64} className="text-muted-foreground mb-4" />
   176→

   177→          No Project Selected
   178→

   179→

   180→          Select a project from the sidebar to view and edit its specification.
   181→

   182→

   183→    )
   184→  }
   185→
   186→  if (isLoading) {
   187→    return (
   188→

   189→        <Loader2 className="animate-spin text-accent" size={32} />
   190→

   191→    )
   192→  }
   193→
   194→  return (
   195→

   196→      {/* Header */}
   197→

   198→

   199→
Specification

   200→

   201→            {currentSpec
   202→              ? `Version ${currentSpec.version} - Last updated ${formatDate(currentSpec.created_at)}`
   203→              : 'No specification created yet'}
   204→

   205→

   206→

   207→          {currentSpec && (
   208→            <>
   209→              <button
   210→                onClick={() => setShowHistory(!showHistory)}
   211→                className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
   212→              >
   213→                <History size={16} />
   214→                History ({specHistory.length})
   215→                {showHistory ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
   216→              </button>
   217→              <button
   218→                onClick={openRespecDialog}
   219→                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors"
   220→              >
   221→                <RefreshCw size={16} />
   222→                Re-Spec
   223→              </button>
   224→            </>
   225→          )}
   226→

   227→

   228→
   229→      {/* Spec History Panel */}
   230→      {showHistory && specHistory.length > 0 && (
   231→

   232→

   233→            <History size={18} className="text-accent" />
   234→            Specification History
   235→

   236→

   237→            {specHistory.map((spec) => (
   238→

   246→

   247→

   252→

   253→

   254→                      Version {spec.version}
   255→                      {spec.is_active && (
   256→                        (Active)
   257→                      )}
   258→

   259→

   260→                      {formatDate(spec.created_at)}
   261→

   262→

   263→

   264→                {spec.parent_spec_id && (
   265→
   266→                    Re-Spec from v{specHistory.find((s) => s.id === spec.parent_spec_id)?.version || '?'}
   267→
   268→                )}
   269→

   270→            ))}
   271→

   272→

   273→      )}
   274→
   275→      {/* Spec Content */}
   276→

   277→

   278→

   279→            <FileText size={18} className="text-accent" />
   280→            {currentSpec ? 'Current Specification' : 'Create Specification'}
   281→

   282→          {currentSpec && !isEditing && (
   283→            <button
   284→              onClick={() => setIsEditing(true)}
   285→              className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
   286→            >
   287→              <Edit3 size={14} />
   288→              Edit
   289→            </button>
   290→          )}
   291→          {isEditing && (
   292→

   293→              <button
   294→                onClick={() => {
   295→                  setIsEditing(false)
   296→                  setEditContent(currentSpec?.content || '')
   297→                }}
   298→                className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
   299→              >
   300→                <X size={14} />
   301→                Cancel
   302→              </button>
   303→              <button
   304→                onClick={handleCreateSpec}
   305→                disabled={isSaving || !editContent.trim()}
   306→                className="flex items-center gap-2 px-3 py-1.5 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
   307→              >
   308→                {isSaving ? (
   309→                  <Loader2 size={14} className="animate-spin" />
   310→                ) : (
   311→                  <Save size={14} />
   312→                )}
   313→                Save
   314→              </button>
   315→

   316→          )}
   317→

   318→
   319→

   320→          {isEditing || !currentSpec ? (
   321→            <textarea
   322→              value={editContent}
   323→              onChange={(e) => setEditContent(e.target.value)}
   324→              placeholder="Enter your project specification here...
   325→
   326→Describe your project's:
   327→- Purpose and goals
   328→- Key features and functionality
   329→- Technical requirements
   330→- User interface guidelines
   331→- Any constraints or considerations"
   332→              rows={20}
   333→              className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
   334→            />
   335→          ) : (
   336→

   337→

   338→                {currentSpec.content}
   339→

   340→

   341→          )}
   342→
   343→          {!currentSpec && !isEditing && (
   344→

   345→              <FileText size={48} className="mx-auto text-muted-foreground mb-4" />
   346→

   347→                No specification has been created for this project yet.
   348→

   349→              <button
   350→                onClick={() => setIsEditing(true)}
   351→                className="btn-accent"
   352→              >
   353→                Create Specification
   354→              </button>
   355→

   356→          )}
   357→

   358→

   359→
   360→      {/* Re-Spec Dialog */}
   361→      <Dialog.Root open={showRespecDialog} onOpenChange={setShowRespecDialog}>
   362→        <Dialog.Portal>
   363→          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
   364→          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-6 w-[calc(100%-2rem)] max-w-2xl max-h-[calc(100vh-4rem)] overflow-y-auto z-50 shadow-xl">
   365→

   366→              <Dialog.Title className="text-xl font-semibold text-foreground flex items-center gap-2">
   367→                <RefreshCw size={20} className="text-accent" />
   368→                Re-Spec Project
   369→              </Dialog.Title>
   370→              <Dialog.Close asChild>
   371→                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors">
   372→                  <X size={20} />
   373→                </button>
   374→              </Dialog.Close>
   375→

   376→
   377→            <Dialog.Description className="text-muted-foreground mb-4">
   378→              Create a new specification version. The current specification is shown below for
   379→              reference. Modify it to reflect your updated requirements.
   380→            </Dialog.Description>
   381→
   382→            {currentSpec && (
   383→

   384→

   385→                  Previous Context (Version {currentSpec.version})
   386→

   387→

   388→                  {currentSpec.content.substring(0, 200)}...
   389→

   390→

   391→            )}
   392→
   393→

   394→
   395→                Updated Specification *
   396→
   397→              <textarea
   398→                value={respecContent}
   399→                onChange={(e) => setRespecContent(e.target.value)}
   400→                placeholder="Enter your updated project specification..."
   401→                rows={12}
   402→                className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
   403→              />
   404→

   405→
   406→

   407→              <Dialog.Close asChild>
   408→                <button className="px-4 py-2 text-sm text-muted-foreground hover:bg-secondary rounded-lg transition-colors">
   409→                  Cancel
   410→                </button>
   411→              </Dialog.Close>
   412→              <button
   413→                onClick={handleRespec}
   414→                disabled={isSubmitting || !respecContent.trim()}
   415→                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
   416→              >
   417→                {isSubmitting ? (
   418→                  <>
   419→                    <Loader2 size={16} className="animate-spin" />
   420→                    Creating...
   421→                  </>
   422→                ) : (
   423→                  <>
   424→                    <Check size={16} />
   425→                    Create Re-Spec
   426→                  </>
   427→                )}
   428→              </button>
   429→

   430→          </Dialog.Content>
   431→        </Dialog.Portal>
   432→      </Dialog.Root>
   433→

   434→  )
   435→}
   436→

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

import { useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { useProjectStore } from '../stores/projectStore'
import { useToastStore } from '../components/Toast'
import {
  FileText,
  RefreshCw,
  History,
  Clock,
  Check,
  ChevronDown,
  ChevronUp,
  Edit3,
  Save,
  X,
  Loader2,
  Eye,
} from 'lucide-react'
import * as Dialog from '@radix-ui/react-dialog'

interface Spec {
  id: number
  project_id: number
  version: number
  content: string
  is_active: boolean
  parent_spec_id: number | null
  created_at: string
}

export default function SpecEditor() {
  const [searchParams] = useSearchParams()
  const { currentProject } = useProjectStore()
  const { addToast } = useToastStore()

  const [currentSpec, setCurrentSpec] = useState<Spec | null>(null)
  const [specHistory, setSpecHistory] = useState<Spec[]>([])
  const [isLoading, setIsLoading] = useState(true)
  const [showHistory, setShowHistory] = useState(false)
  const [showRespecDialog, setShowRespecDialog] = useState(false)
  const [respecContent, setRespecContent] = useState('')
  const [isSubmitting, setIsSubmitting] = useState(false)

  // Edit mode
  const [isEditing, setIsEditing] = useState(false)
  const [editContent, setEditContent] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // Fetch spec data when project changes
  useEffect(() => {
    if (currentProject) {
      fetchSpec()
      fetchSpecHistory()
    } else {
      setCurrentSpec(null)
      setSpecHistory([])
      setIsLoading(false)
    }
  }, [currentProject])

  const fetchSpec = async () => {
    if (!currentProject) return

    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec`
      )
      if (response.ok) {
        const data = await response.json()
        setCurrentSpec(data)
        setEditContent(data.content)
      } else if (response.status === 404) {
        setCurrentSpec(null)
      }
    } catch (error) {
      console.error('Failed to fetch spec:', error)
    } finally {
      setIsLoading(false)
    }
  }

  const fetchSpecHistory = async () => {
    if (!currentProject) return

    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec/history`
      )
      if (response.ok) {
        const data = await response.json()
        setSpecHistory(data)
      }
    } catch (error) {
      console.error('Failed to fetch spec history:', error)
    }
  }

  const handleCreateSpec = async () => {
    if (!currentProject || !editContent.trim()) return

    setIsSaving(true)
    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ content: editContent }),
        }
      )

      if (!response.ok) {
        throw new Error('Failed to create spec')
      }

      const data = await response.json()
      setCurrentSpec(data)
      setIsEditing(false)
      addToast('success', 'Spec Created', 'Project specification has been saved')
      fetchSpecHistory()
    } catch (error) {
      console.error('Failed to create spec:', error)
      addToast('error', 'Save Failed', 'Failed to save specification')
    } finally {
      setIsSaving(false)
    }
  }

  const handleRespec = async () => {
    if (!currentProject || !respecContent.trim()) return

    setIsSubmitting(true)
    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/respec`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ content: respecContent }),
        }
      )

      if (!response.ok) {
        throw new Error('Failed to create Re-Spec')
      }

      const data = await response.json()
      setCurrentSpec(data)
      setEditContent(data.content)
      setShowRespecDialog(false)
      setRespecContent('')
      addToast('success', 'Re-Spec Complete', `Created spec version ${data.version}`)
      fetchSpecHistory()
    } catch (error) {
      console.error('Failed to respec:', error)
      addToast('error', 'Re-Spec Failed', 'Failed to create new specification version')
    } finally {
      setIsSubmitting(false)
    }
  }

  const openRespecDialog = () => {
    // Pre-populate with current spec content
    setRespecContent(currentSpec?.content || '')
    setShowRespecDialog(true)
  }

  const formatDate = (dateStr: string) => {
    return new Date(dateStr).toLocaleString()
  }

  if (!currentProject) {
    return (

        <FileText size={64} className="text-muted-foreground mb-4" />

          No Project Selected

          Select a project from the sidebar to view and edit its specification.

    )
  }

  if (isLoading) {
    return (

        <Loader2 className="animate-spin text-accent" size={32} />

    )
  }

  return (

      {/* Header */}

Specification

            {currentSpec
              ? `Version ${currentSpec.version} - Last updated ${formatDate(currentSpec.created_at)}`
              : 'No specification created yet'}

          {currentSpec && (
            <>
              <button
                onClick={() => setShowHistory(!showHistory)}
                className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
              >
                <History size={16} />
                History ({specHistory.length})
                {showHistory ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
              </button>
              <button
                onClick={openRespecDialog}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors"
              >
                <RefreshCw size={16} />
                Re-Spec
              </button>
            </>
          )}

      {/* Spec History Panel */}
      {showHistory && specHistory.length > 0 && (

            <History size={18} className="text-accent" />
            Specification History

            {specHistory.map((spec) => (

                      Version {spec.version}
                      {spec.is_active && (
                        (Active)
                      )}

                      {formatDate(spec.created_at)}

                {spec.parent_spec_id && (

                    Re-Spec from v{specHistory.find((s) => s.id === spec.parent_spec_id)?.version || '?'}

                )}

            ))}

      )}

      {/* Spec Content */}

            <FileText size={18} className="text-accent" />
            {currentSpec ? 'Current Specification' : 'Create Specification'}

          {currentSpec && !isEditing && (
            <button
              onClick={() => setIsEditing(true)}
              className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
            >
              <Edit3 size={14} />
              Edit
            </button>
          )}
          {isEditing && (

              <button
                onClick={() => {
                  setIsEditing(false)
                  setEditContent(currentSpec?.content || '')
                }}
                className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
              >
                <X size={14} />
                Cancel
              </button>
              <button
                onClick={handleCreateSpec}
                disabled={isSaving || !editContent.trim()}
                className="flex items-center gap-2 px-3 py-1.5 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSaving ? (
                  <Loader2 size={14} className="animate-spin" />
                ) : (
                  <Save size={14} />
                )}
                Save
              </button>

          )}

          {isEditing || !currentSpec ? (
            <textarea
              value={editContent}
              onChange={(e) => setEditContent(e.target.value)}
              placeholder="Enter your project specification here...

Describe your project's:
- Purpose and goals
- Key features and functionality
- Technical requirements
- User interface guidelines
- Any constraints or considerations"
              rows={20}
              className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
            />
          ) : (

                {currentSpec.content}

          )}

          {!currentSpec && !isEditing && (

              <FileText size={48} className="mx-auto text-muted-foreground mb-4" />

                No specification has been created for this project yet.

              <button
                onClick={() => setIsEditing(true)}
                className="btn-accent"
              >
                Create Specification
              </button>

          )}

      {/* Re-Spec Dialog */}
      <Dialog.Root open={showRespecDialog} onOpenChange={setShowRespecDialog}>
        <Dialog.Portal>
          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-6 w-[calc(100%-2rem)] max-w-2xl max-h-[calc(100vh-4rem)] overflow-y-auto z-50 shadow-xl">

              <Dialog.Title className="text-xl font-semibold text-foreground flex items-center gap-2">
                <RefreshCw size={20} className="text-accent" />
                Re-Spec Project
              </Dialog.Title>
              <Dialog.Close asChild>
                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors">
                  <X size={20} />
                </button>
              </Dialog.Close>

            <Dialog.Description className="text-muted-foreground mb-4">
              Create a new specification version. The current specification is shown below for
              reference. Modify it to reflect your updated requirements.
            </Dialog.Description>

            {currentSpec && (

                  Previous Context (Version {currentSpec.version})

                  {currentSpec.content.substring(0, 200)}...

            )}

                Updated Specification *

              <textarea
                value={respecContent}
                onChange={(e) => setRespecContent(e.target.value)}
                placeholder="Enter your updated project specification..."
                rows={12}
                className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
              />

              <Dialog.Close asChild>
                <button className="px-4 py-2 text-sm text-muted-foreground hover:bg-secondary rounded-lg transition-colors">
                  Cancel
                </button>
              </Dialog.Close>
              <button
                onClick={handleRespec}
                disabled={isSubmitting || !respecContent.trim()}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSubmitting ? (
                  <>
                    <Loader2 size={16} className="animate-spin" />
                    Creating...
                  </>
                ) : (
                  <>
                    <Check size={16} />
                    Create Re-Spec
                  </>
                )}
              </button>

          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>

  )
}


Let me add the state for viewing historical versions and the view button:


  // Edit mode
  const [isEditing, setIsEditing] = useState(false)
  const [editContent, setEditContent] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // Edit mode
  const [isEditing, setIsEditing] = useState(false)
  const [editContent, setEditContent] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // View historical version
  const [viewingSpec, setViewingSpec] = useState<Spec | null>(null)
  const [showViewDialog, setShowViewDialog] = useState(false)


The file C:/Users/MikeSwanson/AutoBuilder/My-Auto-Builder/frontend/src/pages/SpecEditor.tsx has been updated. Here's the result of running `cat -n` on a snippet of the edited file:
    40→  const [showRespecDialog, setShowRespecDialog] = useState(false)
    41→  const [respecContent, setRespecContent] = useState('')
    42→  const [isSubmitting, setIsSubmitting] = useState(false)
    43→
    44→  // Edit mode
    45→  const [isEditing, setIsEditing] = useState(false)
    46→  const [editContent, setEditContent] = useState('')
    47→  const [isSaving, setIsSaving] = useState(false)
    48→
    49→  // View historical version
    50→  const [viewingSpec, setViewingSpec] = useState<Spec | null>(null)
    51→  const [showViewDialog, setShowViewDialog] = useState(false)
    52→
    53→  // Fetch spec data when project changes
    54→  useEffect(() => {
    55→    if (currentProject) {

  // Edit mode
  const [isEditing, setIsEditing] = useState(false)
  const [editContent, setEditContent] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // View historical version
  const [viewingSpec, setViewingSpec] = useState<Spec | null>(null)
  const [showViewDialog, setShowViewDialog] = useState(false)

import { useEffect, useState } from 'react'
import { useSearchParams } from 'react-router-dom'
import { useProjectStore } from '../stores/projectStore'
import { useToastStore } from '../components/Toast'
import {
  FileText,
  RefreshCw,
  History,
  Clock,
  Check,
  ChevronDown,
  ChevronUp,
  Edit3,
  Save,
  X,
  Loader2,
  Eye,
} from 'lucide-react'
import * as Dialog from '@radix-ui/react-dialog'

interface Spec {
  id: number
  project_id: number
  version: number
  content: string
  is_active: boolean
  parent_spec_id: number | null
  created_at: string
}

export default function SpecEditor() {
  const [searchParams] = useSearchParams()
  const { currentProject } = useProjectStore()
  const { addToast } = useToastStore()

  const [currentSpec, setCurrentSpec] = useState<Spec | null>(null)
  const [specHistory, setSpecHistory] = useState<Spec[]>([])
  const [isLoading, setIsLoading] = useState(true)
  const [showHistory, setShowHistory] = useState(false)
  const [showRespecDialog, setShowRespecDialog] = useState(false)
  const [respecContent, setRespecContent] = useState('')
  const [isSubmitting, setIsSubmitting] = useState(false)

  // Edit mode
  const [isEditing, setIsEditing] = useState(false)
  const [editContent, setEditContent] = useState('')
  const [isSaving, setIsSaving] = useState(false)

  // Fetch spec data when project changes
  useEffect(() => {
    if (currentProject) {
      fetchSpec()
      fetchSpecHistory()
    } else {
      setCurrentSpec(null)
      setSpecHistory([])
      setIsLoading(false)
    }
  }, [currentProject])

  const fetchSpec = async () => {
    if (!currentProject) return

    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec`
      )
      if (response.ok) {
        const data = await response.json()
        setCurrentSpec(data)
        setEditContent(data.content)
      } else if (response.status === 404) {
        setCurrentSpec(null)
      }
    } catch (error) {
      console.error('Failed to fetch spec:', error)
    } finally {
      setIsLoading(false)
    }
  }

  const fetchSpecHistory = async () => {
    if (!currentProject) return

    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec/history`
      )
      if (response.ok) {
        const data = await response.json()
        setSpecHistory(data)
      }
    } catch (error) {
      console.error('Failed to fetch spec history:', error)
    }
  }

  const handleCreateSpec = async () => {
    if (!currentProject || !editContent.trim()) return

    setIsSaving(true)
    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/spec`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ content: editContent }),
        }
      )

      if (!response.ok) {
        throw new Error('Failed to create spec')
      }

      const data = await response.json()
      setCurrentSpec(data)
      setIsEditing(false)
      addToast('success', 'Spec Created', 'Project specification has been saved')
      fetchSpecHistory()
    } catch (error) {
      console.error('Failed to create spec:', error)
      addToast('error', 'Save Failed', 'Failed to save specification')
    } finally {
      setIsSaving(false)
    }
  }

  const handleRespec = async () => {
    if (!currentProject || !respecContent.trim()) return

    setIsSubmitting(true)
    try {
      const response = await fetch(
        `http://localhost:8000/api/projects/${currentProject.id}/respec`,
        {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ content: respecContent }),
        }
      )

      if (!response.ok) {
        throw new Error('Failed to create Re-Spec')
      }

      const data = await response.json()
      setCurrentSpec(data)
      setEditContent(data.content)
      setShowRespecDialog(false)
      setRespecContent('')
      addToast('success', 'Re-Spec Complete', `Created spec version ${data.version}`)
      fetchSpecHistory()
    } catch (error) {
      console.error('Failed to respec:', error)
      addToast('error', 'Re-Spec Failed', 'Failed to create new specification version')
    } finally {
      setIsSubmitting(false)
    }
  }

  const openRespecDialog = () => {
    // Pre-populate with current spec content
    setRespecContent(currentSpec?.content || '')
    setShowRespecDialog(true)
  }

  const formatDate = (dateStr: string) => {
    return new Date(dateStr).toLocaleString()
  }

  if (!currentProject) {
    return (

        <FileText size={64} className="text-muted-foreground mb-4" />

          No Project Selected

          Select a project from the sidebar to view and edit its specification.

    )
  }

  if (isLoading) {
    return (

        <Loader2 className="animate-spin text-accent" size={32} />

    )
  }

  return (

      {/* Header */}

Specification

            {currentSpec
              ? `Version ${currentSpec.version} - Last updated ${formatDate(currentSpec.created_at)}`
              : 'No specification created yet'}

          {currentSpec && (
            <>
              <button
                onClick={() => setShowHistory(!showHistory)}
                className="flex items-center gap-2 px-3 py-2 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
              >
                <History size={16} />
                History ({specHistory.length})
                {showHistory ? <ChevronUp size={14} /> : <ChevronDown size={14} />}
              </button>
              <button
                onClick={openRespecDialog}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors"
              >
                <RefreshCw size={16} />
                Re-Spec
              </button>
            </>
          )}

      {/* Spec History Panel */}
      {showHistory && specHistory.length > 0 && (

            <History size={18} className="text-accent" />
            Specification History

            {specHistory.map((spec) => (

                      Version {spec.version}
                      {spec.is_active && (
                        (Active)
                      )}

                      {formatDate(spec.created_at)}

                {spec.parent_spec_id && (

                    Re-Spec from v{specHistory.find((s) => s.id === spec.parent_spec_id)?.version || '?'}

                )}

            ))}

      )}

      {/* Spec Content */}

            <FileText size={18} className="text-accent" />
            {currentSpec ? 'Current Specification' : 'Create Specification'}

          {currentSpec && !isEditing && (
            <button
              onClick={() => setIsEditing(true)}
              className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
            >
              <Edit3 size={14} />
              Edit
            </button>
          )}
          {isEditing && (

              <button
                onClick={() => {
                  setIsEditing(false)
                  setEditContent(currentSpec?.content || '')
                }}
                className="flex items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:bg-secondary rounded-lg transition-colors"
              >
                <X size={14} />
                Cancel
              </button>
              <button
                onClick={handleCreateSpec}
                disabled={isSaving || !editContent.trim()}
                className="flex items-center gap-2 px-3 py-1.5 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSaving ? (
                  <Loader2 size={14} className="animate-spin" />
                ) : (
                  <Save size={14} />
                )}
                Save
              </button>

          )}

          {isEditing || !currentSpec ? (
            <textarea
              value={editContent}
              onChange={(e) => setEditContent(e.target.value)}
              placeholder="Enter your project specification here...

Describe your project's:
- Purpose and goals
- Key features and functionality
- Technical requirements
- User interface guidelines
- Any constraints or considerations"
              rows={20}
              className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
            />
          ) : (

                {currentSpec.content}

          )}

          {!currentSpec && !isEditing && (

              <FileText size={48} className="mx-auto text-muted-foreground mb-4" />

                No specification has been created for this project yet.

              <button
                onClick={() => setIsEditing(true)}
                className="btn-accent"
              >
                Create Specification
              </button>

          )}

      {/* Re-Spec Dialog */}
      <Dialog.Root open={showRespecDialog} onOpenChange={setShowRespecDialog}>
        <Dialog.Portal>
          <Dialog.Overlay className="fixed inset-0 bg-black/50 z-50" />
          <Dialog.Content className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-card border border-border rounded-lg p-6 w-[calc(100%-2rem)] max-w-2xl max-h-[calc(100vh-4rem)] overflow-y-auto z-50 shadow-xl">

              <Dialog.Title className="text-xl font-semibold text-foreground flex items-center gap-2">
                <RefreshCw size={20} className="text-accent" />
                Re-Spec Project
              </Dialog.Title>
              <Dialog.Close asChild>
                <button className="p-1 text-muted-foreground hover:text-foreground hover:bg-secondary rounded transition-colors">
                  <X size={20} />
                </button>
              </Dialog.Close>

            <Dialog.Description className="text-muted-foreground mb-4">
              Create a new specification version. The current specification is shown below for
              reference. Modify it to reflect your updated requirements.
            </Dialog.Description>

            {currentSpec && (

                  Previous Context (Version {currentSpec.version})

                  {currentSpec.content.substring(0, 200)}...

            )}

                Updated Specification *

              <textarea
                value={respecContent}
                onChange={(e) => setRespecContent(e.target.value)}
                placeholder="Enter your updated project specification..."
                rows={12}
                className="w-full px-4 py-3 bg-secondary border border-border rounded-lg text-foreground placeholder-muted-foreground focus:outline-none focus:ring-2 focus:ring-accent font-mono text-sm resize-none"
              />

              <Dialog.Close asChild>
                <button className="px-4 py-2 text-sm text-muted-foreground hover:bg-secondary rounded-lg transition-colors">
                  Cancel
                </button>
              </Dialog.Close>
              <button
                onClick={handleRespec}
                disabled={isSubmitting || !respecContent.trim()}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-accent hover:bg-accent/80 text-white rounded-lg transition-colors disabled:opacity-50"
              >
                {isSubmitting ? (
                  <>
                    <Loader2 size={16} className="animate-spin" />
                    Creating...
                  </>
                ) : (
                  <>
                    <Check size={16} />
                    Create Re-Spec
                  </>
                )}
              </button>

          </Dialog.Content>
        </Dialog.Portal>
      </Dialog.Root>

  )
}

+  const [viewingSpec, setViewingSpec] = useState<Spec | null>(null)

+  const [showViewDialog, setShowViewDialog] = useState(false)


Now let me add the view button to history items and add a function to handle viewing:


  const openRespecDialog = () => {
    // Pre-populate with current spec content
    setRespecContent(currentSpec?.content || '')
    setShowRespecDialog(true)
  }

  const openRespecDialog = () => {
    // Pre-populate with current spec content
    setRespecContent(currentSpec?.content || '')
    setShowRespecDialog(true)
  }

  const handleViewSpec = (spec: Spec) => {
    setViewingSpec(spec)
    setShowViewDialog(true)
  }