kanban-app/frontend/src/pages/BoardEdit.tsx

125 lines
4.1 KiB
TypeScript

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { useNavigate, Link, useParams } from 'react-router-dom';
import { useBoard } from '../hooks/useBoard';
import { useBoards } from '../hooks/useBoards';
import { useEffect } from 'react';
import { useToast } from '@/context/toasts';
const boardSchema = z.object({
name: z
.string()
.min(1, 'Board name is required')
.max(100, 'Board name must be less than 100 characters'),
description: z.string().max(500, 'Description must be less than 500 characters').optional(),
});
type BoardFormData = z.infer<typeof boardSchema>;
export function BoardEdit() {
const navigate = useNavigate();
const { id } = useParams<{ id: string }>();
const { board } = useBoard(parseInt(id || '0'));
const { updateBoard } = useBoards();
const { addNotification } = useToast();
const {
register,
handleSubmit,
formState: { errors },
setValue,
} = useForm<BoardFormData>({
resolver: zodResolver(boardSchema),
});
// Populate form when board data is loaded
useEffect(() => {
if (board) {
setValue('name', board.name);
setValue('description', board.description || '');
}
}, [board, setValue]);
const onSubmit = async (data: BoardFormData) => {
if (!id) return;
try {
await updateBoard(parseInt(id), data);
navigate(`/boards/${id}`);
} catch (err) {
// Error is handled by the hook
const errorMessage = err instanceof Error ? err.message : 'Failed to create card';
addNotification({
type: 'error',
title: 'Error Login',
message: errorMessage,
duration: 5000,
});
}
};
if (!board) {
return <div className="text-white">Loading...</div>;
}
return (
<div className="max-w-2xl mx-auto">
<div className="mb-8">
<Link to={`/boards/${id}`} className="text-gray-400 hover:text-white transition-colors">
Back to Board
</Link>
</div>
<div className="bg-gray-800 rounded-lg p-8 border border-gray-700">
<h1 className="text-3xl font-bold text-white mb-6">Edit Board</h1>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-6">
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-300 mb-2">
Board Name <span className="text-red-400">*</span>
</label>
<input
id="name"
type="text"
{...register('name')}
className="w-full px-4 py-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent"
placeholder="e.g., Project Alpha, Personal Tasks"
/>
{errors.name && <p className="mt-1 text-sm text-red-400">{errors.name.message}</p>}
</div>
<div>
<label htmlFor="description" className="block text-sm font-medium text-gray-300 mb-2">
Description
</label>
<textarea
id="description"
rows={4}
{...register('description')}
className="w-full px-4 py-3 bg-gray-700 border border-gray-600 rounded-lg text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-none"
placeholder="Optional description for your board..."
/>
{errors.description && (
<p className="mt-1 text-sm text-red-400">{errors.description.message}</p>
)}
</div>
<div className="flex justify-end gap-3 pt-4">
<Link
to={`/boards/${id}`}
className="px-6 py-3 text-gray-300 hover:text-white transition-colors"
>
Cancel
</Link>
<button
type="submit"
className="bg-blue-600 hover:bg-blue-700 text-white font-medium py-3 px-6 rounded-lg transition-colors"
>
Save Changes
</button>
</div>
</form>
</div>
</div>
);
}