modcomms/frontend/components/ProofTypeManager.tsx
2025-12-18 16:51:27 +00:00

113 lines
No EOL
5.3 KiB
TypeScript
Executable file

import React, { useState, useEffect } from 'react';
import { TrashIcon } from './icons/TrashIcon';
import { ChevronDownIcon } from './icons/ChevronDownIcon';
interface ProofTypeManagerProps {
subChannels: string[];
proofTypesBySubChannel: Record<string, string[]>;
onAddProofType: (subChannel: string, value: string) => void;
onRemoveProofType: (subChannel: string, value: string) => void;
disabled: boolean;
}
export const ProofTypeManager: React.FC<ProofTypeManagerProps> = ({
subChannels,
proofTypesBySubChannel,
onAddProofType,
onRemoveProofType,
disabled
}) => {
const [selectedSubChannel, setSelectedSubChannel] = useState<string>('');
const [newItem, setNewItem] = useState('');
useEffect(() => {
// If subChannels are available, default to the first one.
if (subChannels.length > 0 && !selectedSubChannel) {
setSelectedSubChannel(subChannels[0]);
}
}, [subChannels, selectedSubChannel]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (newItem.trim() && selectedSubChannel) {
onAddProofType(selectedSubChannel, newItem.trim());
setNewItem('');
}
};
const currentProofTypes = proofTypesBySubChannel[selectedSubChannel] || [];
return (
<div className="bg-white rounded-lg shadow-md p-6 border border-gray-200 flex flex-col h-full">
<h2 className="text-xl font-bold text-brand-dark-blue mb-2">Proof Type Manager</h2>
<p className="text-sm text-gray-500 mb-4">Assign and manage specific proof types for each sub-channel.</p>
<div className="mb-4">
<label htmlFor="subchannel-select" className="block text-sm font-medium text-gray-700 mb-1">
Select a Sub-Channel to manage:
</label>
<div className="relative">
<select
id="subchannel-select"
value={selectedSubChannel}
onChange={(e) => setSelectedSubChannel(e.target.value)}
className="w-full bg-white border border-gray-300 rounded-md py-2 pl-3 pr-10 text-gray-900 focus:outline-none focus:ring-2 focus:ring-brand-accent appearance-none disabled:bg-gray-100"
disabled={disabled}
>
{subChannels.map(sc => (
<option key={sc} value={sc}>{sc}</option>
))}
</select>
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-3 text-gray-400">
<ChevronDownIcon className="h-4 w-4" />
</div>
</div>
</div>
<form onSubmit={handleSubmit} className="flex gap-2 mb-4">
<input
type="text"
value={newItem}
onChange={(e) => setNewItem(e.target.value)}
placeholder="New Proof Type..."
className="flex-grow p-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-brand-accent focus:border-brand-accent transition disabled:bg-gray-100 disabled:cursor-not-allowed"
disabled={disabled || !selectedSubChannel}
/>
<button
type="submit"
className="bg-brand-accent text-white font-semibold py-2 px-4 rounded-md hover:bg-brand-dark-blue transition-colors duration-300 disabled:bg-gray-400 disabled:cursor-not-allowed"
disabled={!newItem.trim() || disabled || !selectedSubChannel}
>
Add
</button>
</form>
<div className="flex-1 overflow-y-auto pr-2 -mr-2">
{currentProofTypes.length > 0 ? (
<ul className="space-y-2">
{currentProofTypes.map((item) => (
<li
key={item}
className="flex items-center justify-between bg-gray-50 p-2.5 rounded-md border border-gray-200 group"
>
<span className="text-gray-800">{item}</span>
<button
onClick={() => onRemoveProofType(selectedSubChannel, item)}
className={`text-gray-400 hover:text-red-600 transition-opacity ${disabled ? 'opacity-0 cursor-not-allowed' : 'opacity-0 group-hover:opacity-100'}`}
title={`Remove ${item}`}
disabled={disabled}
>
<TrashIcon className="h-5 w-5" />
</button>
</li>
))}
</ul>
) : (
<div className="text-center py-8 text-gray-500 bg-gray-50 rounded-md h-full flex items-center justify-center">
<p>No proof types configured for <br/> <strong className="text-gray-600">{selectedSubChannel}</strong>.</p>
</div>
)}
</div>
</div>
);
};