Tender Requirements (components/Editor/tender-requirements.tsx)¶
Overview¶
A comprehensive component for managing tender requirements, including questions and themes, with functionality for adding, editing, and removing questions, managing themes, and processing tender requirements. The component provides an interactive interface with batch operations and real-time updates.
Features¶
- Question management
- Theme handling
- Batch operations
- Animated transitions
- Responsive layout
- Real-time updates
- State persistence
- Error handling
- Search functionality
- Progress tracking
Dependencies¶
import { useState, useEffect } from 'react'
import { motion } from 'framer-motion'
import { Button } from '@/components/ui/button'
import { QuestionCard } from './question-card'
import { ThemesSection } from './themes-section'
import { ContractSummary } from './contract-summary'
Props¶
interface TenderRequirementsProps {
initialQuestions: Question[];
setReadyToProcess: (ready: boolean) => void;
onQuestionsUpdate: (questions: Question[]) => void;
onThemesUpdate: (themes: Theme[]) => void;
}
interface Question {
id: string;
text: string;
themes: Theme[];
}
interface Theme {
id: string;
name: string;
description: string;
}
Implementation¶
State Management¶
const [questions, setQuestions] = useState<Question[]>(initialQuestions);
const [selectedQuestions, setSelectedQuestions] = useState<string[]>([]);
const [isRemoveMode, setIsRemoveMode] = useState(false);
const [themes, setThemes] = useState<Theme[]>([]);
Methods¶
const handleQuestionEdit = (id: string, text: string) => {
setQuestions(questions.map(q =>
q.id === id ? { ...q, text } : q
));
onQuestionsUpdate(questions);
};
const handleThemeChange = (questionId: string, newThemes: Theme[]) => {
setQuestions(questions.map(q =>
q.id === questionId ? { ...q, themes: newThemes } : q
));
onQuestionsUpdate(questions);
};
const handleRemoveQuestions = () => {
setQuestions(questions.filter(q => !selectedQuestions.includes(q.id)));
setSelectedQuestions([]);
setIsRemoveMode(false);
onQuestionsUpdate(questions);
};
Unique Functionality¶
HTML Structure¶
<div className="space-y-6">
<div className="flex justify-between items-center">
<h2 className="text-2xl font-bold">Tender Requirements</h2>
<div className="flex space-x-2">
<Button onClick={() => setIsRemoveMode(!isRemoveMode)}>
{isRemoveMode ? 'Cancel' : 'Remove Questions'}
</Button>
{isRemoveMode && selectedQuestions.length > 0 && (
<Button onClick={handleRemoveQuestions}>
Remove Selected ({selectedQuestions.length})
</Button>
)}
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="space-y-4">
{questions.map(question => (
<QuestionCard
key={question.id}
{...question}
isRemoveMode={isRemoveMode}
isSelected={selectedQuestions.includes(question.id)}
onSelect={(id) => {
setSelectedQuestions(prev =>
prev.includes(id)
? prev.filter(qId => qId !== id)
: [...prev, id]
);
}}
onEdit={handleQuestionEdit}
onThemeChange={handleThemeChange}
/>
))}
</div>
<ThemesSection
themes={themes}
onThemesUpdate={setThemes}
onThemeSelect={(theme) => {
const updatedQuestions = questions.map(q => ({
...q,
themes: [...q.themes, theme]
}));
setQuestions(updatedQuestions);
onQuestionsUpdate(updatedQuestions);
}}
/>
</div>
</div>
API Integration¶
- Question state persistence
- Theme synchronization
- Progress tracking
- Batch operations
Components Used¶
Notes¶
- Supports batch operations
- Maintains theme consistency
- Features responsive design
- Handles state updates
- Provides user feedback