105 lines
3.0 KiB
TypeScript
105 lines
3.0 KiB
TypeScript
import { useState } from 'react';
|
|
import { Check, Minus } from 'lucide-react';
|
|
import { Button, Input } from '../../components/ui';
|
|
import { EnvParam } from '../../models/EnvParam';
|
|
import { AddEvent, RemoveEvent, UpdateEvent } from '../../models/Env';
|
|
|
|
interface EnvironmentParamProps {
|
|
param: EnvParam;
|
|
onChanged: (event: AddEvent<EnvParam> | RemoveEvent<EnvParam> | UpdateEvent<EnvParam>) => void;
|
|
isNew: boolean;
|
|
}
|
|
|
|
export function EnvironmentParam({ param, onChanged, isNew }: EnvironmentParamProps) {
|
|
const [localParam, setLocalParam] = useState(param);
|
|
const [isFocused, setIsFocused] = useState(false);
|
|
|
|
function updateParam(updates: Partial<EnvParam>) {
|
|
const updated = localParam.update(updates).markChanged(true);
|
|
setLocalParam(updated);
|
|
}
|
|
|
|
function handleChange() {
|
|
if (!localParam.isChanged) return;
|
|
|
|
const savedParam = localParam.markChanged(false);
|
|
|
|
if (!isNew) {
|
|
onChanged(UpdateEvent.update(savedParam));
|
|
}
|
|
|
|
setLocalParam(savedParam);
|
|
}
|
|
|
|
function handleAdd() {
|
|
onChanged(AddEvent.add(localParam));
|
|
setLocalParam(new EnvParam(0, '', ''));
|
|
}
|
|
|
|
function handleKeyUp(event: React.KeyboardEvent<HTMLInputElement>) {
|
|
if (event.key === 'Enter') {
|
|
handleChange();
|
|
}
|
|
}
|
|
|
|
const isChangedClass = localParam.isChanged ? 'ring-2 ring-yellow-400 border-yellow-400' : '';
|
|
const focusedClass = isFocused ? 'bg-blue-50' : '';
|
|
|
|
return (
|
|
<div
|
|
className={`
|
|
grid grid-cols-12 gap-2 p-2 rounded-lg transition-all duration-200
|
|
${isChangedClass}
|
|
${focusedClass ? 'bg-blue-50' : 'bg-white'}
|
|
hover:bg-slate-50
|
|
`}
|
|
>
|
|
<div className="col-span-4">
|
|
<Input
|
|
value={localParam.name ?? ''}
|
|
onChange={(e) => updateParam({ name: e.target.value })}
|
|
onBlur={() => { handleChange(); setIsFocused(false); }}
|
|
onFocus={() => setIsFocused(true)}
|
|
onKeyUp={handleKeyUp}
|
|
placeholder="Parameter name"
|
|
className="text-sm"
|
|
/>
|
|
</div>
|
|
|
|
<div className="col-span-7">
|
|
<Input
|
|
value={localParam.value ?? ''}
|
|
onChange={(e) => updateParam({ value: e.target.value })}
|
|
onBlur={() => { handleChange(); setIsFocused(false); }}
|
|
onFocus={() => setIsFocused(true)}
|
|
onKeyUp={handleKeyUp}
|
|
placeholder="Parameter value"
|
|
className="text-sm"
|
|
/>
|
|
</div>
|
|
|
|
<div className="col-span-1 flex items-center justify-center">
|
|
{isNew ? (
|
|
<Button
|
|
variant="success"
|
|
size="sm"
|
|
onClick={handleAdd}
|
|
title="Add parameter"
|
|
icon={Check}
|
|
className="px-2"
|
|
/>
|
|
) : (
|
|
<Button
|
|
variant="secondary"
|
|
size="sm"
|
|
onClick={() => onChanged(new RemoveEvent(localParam))}
|
|
title="Remove parameter"
|
|
icon={Minus}
|
|
className="px-2 text-red-600 hover:text-red-700 hover:bg-red-50"
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|