Skip to content

Question Card (components/Editor/question-card.tsx)

Overview

A dynamic card component for displaying and managing individual tender questions, featuring theme assignment, editing capabilities, and smooth animations. The component provides an interactive interface for question management with expandable content and theme selection.

Features

  • Expandable content
  • Theme selection
  • Question editing
  • Hover effects
  • Remove mode
  • Checkbox selection
  • Theme assignment
  • State persistence
  • Error handling
  • Visual feedback

Dependencies

import { useState, useEffect } from 'react'
import { motion } from 'framer-motion'
import { Card, CardContent } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { Textarea } from '@/components/ui/textarea'
import { Checkbox } from '@/components/ui/checkbox'

Props

interface QuestionCardProps {
  id: string;
  question: string;
  themes: Theme[];
  onThemeChange: (id: string, themes: Theme[]) => void;
  onEdit: (id: string, question: string) => void;
  isRemoveMode: boolean;
  onSelect: (id: string) => void;
  isSelected: boolean;
}

interface Theme {
  id: string;
  name: string;
  description: string;
}

Implementation

State Management

const [isEditing, setIsEditing] = useState(false);
const [editedQuestion, setEditedQuestion] = useState(question);
const [selectedThemes, setSelectedThemes] = useState<Theme[]>(themes);

Methods

const handleSave = () => {
  onEdit(id, editedQuestion);
  setIsEditing(false);
};

const handleThemeToggle = (theme: Theme) => {
  const newThemes = selectedThemes.some(t => t.id === theme.id)
    ? selectedThemes.filter(t => t.id !== theme.id)
    : [...selectedThemes, theme];
  setSelectedThemes(newThemes);
  onThemeChange(id, newThemes);
};

Unique Functionality

// Manages question editing and theme assignment with interactive UI

HTML Structure

<Card className="relative hover:shadow-md transition-shadow duration-300">
  <CardContent className="p-4">
    {isRemoveMode ? (
      <div className="absolute top-4 right-4">
        <Checkbox
          checked={isSelected}
          onCheckedChange={() => onSelect(id)}
        />
      </div>
    ) : (
      <div className="flex justify-end space-x-2">
        <Button onClick={() => setIsEditing(!isEditing)}>
          {isEditing ? 'Cancel' : 'Edit'}
        </Button>
        {isEditing && (
          <Button onClick={handleSave}>Save</Button>
        )}
      </div>
    )}

    {isEditing ? (
      <Textarea
        value={editedQuestion}
        onChange={(e) => setEditedQuestion(e.target.value)}
        className="mt-4"
      />
    ) : (
      <p className="mt-4">{question}</p>
    )}

    <div className="mt-4">
      <h4 className="text-sm font-semibold mb-2">Assigned Themes</h4>
      <div className="flex flex-wrap gap-2">
        {themes.map(theme => (
          <Button
            key={theme.id}
            variant={selectedThemes.some(t => t.id === theme.id) ? 'default' : 'outline'}
            onClick={() => handleThemeToggle(theme)}
          >
            {theme.name}
          </Button>
        ))}
      </div>
    </div>
  </CardContent>
</Card>

API Integration

  • Not applicable for this component

Components Used

Notes

  • Supports theme assignment
  • Features question editing
  • Provides visual feedback
  • Maintains state consistency
  • Handles user interactions