File size: 2,670 Bytes
40aa09c
f002ae5
 
 
 
 
 
 
 
 
40aa09c
f002ae5
 
 
 
40aa09c
f002ae5
 
 
 
40aa09c
 
 
 
f002ae5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40aa09c
 
 
 
 
 
 
 
 
 
 
 
 
 
f002ae5
 
40aa09c
 
f002ae5
 
 
40aa09c
f002ae5
40aa09c
 
f002ae5
 
 
 
 
 
40aa09c
f002ae5
40aa09c
f002ae5
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { useState, useEffect } from "react";

interface Student {
  index: number;
  name: string;
  id: string;
}

interface StudentSelectorProps {
  students: Student[];
  onSelectionChange: (selectedIndices: number[]) => void;
}

export function StudentSelector({
  students,
  onSelectionChange,
}: StudentSelectorProps) {
  const [selected, setSelected] = useState<Set<number>>(
    () => new Set(students.map((s) => s.index))
  );

  useEffect(() => {
    onSelectionChange(Array.from(selected).sort((a, b) => a - b));
  }, [selected]);

  const toggleAll = () => {
    if (selected.size === students.length) {
      setSelected(new Set());
    } else {
      setSelected(new Set(students.map((s) => s.index)));
    }
  };

  const toggle = (index: number) => {
    setSelected((prev) => {
      const next = new Set(prev);
      if (next.has(index)) {
        next.delete(index);
      } else {
        next.add(index);
      }
      return next;
    });
  };

  const allSelected = selected.size === students.length;

  return (
    <div className="space-y-3">
      <div className="flex items-center gap-3">
        <h3 className="font-display text-sm font-semibold text-[var(--color-text)]">
          選擇學生
        </h3>
        <button
          onClick={toggleAll}
          className="btn btn-outline text-xs !py-1 !px-3"
        >
          {allSelected ? "取消全選" : "全選"}
        </button>
        <span className="text-sm text-[var(--color-text-muted)]">
          已選 {selected.size} / {students.length} 位學生
        </span>
      </div>

      <div className="card p-4 max-h-64 overflow-y-auto">
        <div className="grid gap-1.5 sm:grid-cols-2">
          {students.map((s) => (
            <label
              key={s.index}
              className={`flex items-center gap-3 px-3 py-2 rounded-lg cursor-pointer transition-colors ${
                selected.has(s.index)
                  ? "bg-[var(--color-primary)]/10"
                  : "hover:bg-[var(--color-surface)]"
              }`}
            >
              <input
                type="checkbox"
                checked={selected.has(s.index)}
                onChange={() => toggle(s.index)}
                className="w-4 h-4 rounded accent-[var(--color-primary)]"
              />
              <span className="text-sm font-medium text-[var(--color-text)]">
                {s.name}
              </span>
              {s.id && (
                <span className="text-xs text-[var(--color-text-muted)]">
                  ({s.id})
                </span>
              )}
            </label>
          ))}
        </div>
      </div>
    </div>
  );
}