File size: 2,822 Bytes
8934ee3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import clsx from 'clsx';
import { useState } from 'react';

import { useTableStore } from '@/store/tableStore';

import { Input } from './ui/input';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from './ui/select';

interface TableCellInputProps {
  tableId: string;
  options?: string[];
  rowIndex: number;
  columnId: string;
  columnType: 'text' | 'number' | 'select';
  initialValue: string;
}

export default function TableCellInput({
  tableId,
  options,
  rowIndex,
  columnId,
  columnType,
  initialValue,
}: TableCellInputProps) {
  const { editCell } = useTableStore();
  const [value, setValue] = useState(initialValue);
  const [isEditable, setIsEditable] = useState(false);

  const finishEditing = () => {
    editCell(tableId, rowIndex, columnId, value);
    setIsEditable(false);
  };

  const onKeyDown = (
    e: React.KeyboardEvent<HTMLInputElement | HTMLSelectElement>
  ) => {
    if (e.key === 'Enter' || e.key === 'Escape') {
      e.preventDefault();
      finishEditing();
    }
  };

  const handleDoubleClick = (
    e: React.MouseEvent<HTMLInputElement | HTMLSelectElement>
  ) => {
    e.preventDefault();
    if (isEditable) return;
    setIsEditable(true);
  };

  const renderInput = () => {
    switch (columnType) {
      case 'number':
        return (
          <Input
            type="number"
            value={value}
            onBlur={finishEditing}
            onChange={(e) => setValue(e.target.value)}
            onKeyDown={onKeyDown}
            readOnly={!isEditable}
            className={clsx('border-none', { 'cursor-pointer': !isEditable })}
            onDoubleClick={handleDoubleClick}
          />
        );
      case 'select':
        return (
          <Select
            value={value}
            onOpenChange={(open) => {
              if (!open) {
                finishEditing();
              }
            }}
            onValueChange={(newValue) => setValue(newValue)}
          >
            <SelectTrigger className="w-[180px]">
              <SelectValue placeholder="Select" />
            </SelectTrigger>
            <SelectContent>
              {options?.map((option) => (
                <SelectItem key={option} value={option}>
                  {option}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        );
      case 'text':
      default:
        return (
          <Input
            value={value}
            onBlur={finishEditing}
            onChange={(e) => setValue(e.target.value)}
            onKeyDown={onKeyDown}
            readOnly={!isEditable}
            className={clsx('border-none', { 'cursor-pointer': !isEditable })}
            onDoubleClick={handleDoubleClick}
          />
        );
    }
  };

  return renderInput();
}