ge-tool/components/SubmissionForm.tsx

126 lines
4.4 KiB
TypeScript
Raw Permalink Normal View History

2025-12-10 06:41:43 +00:00
import React, { useRef, useEffect, useState, useCallback } from 'react';
import UsernameAutocomplete from './UsernameAutocomplete';
interface SubmissionFormProps {
username: string;
setUsername: (value: string) => void;
geIdAndLang: string;
setGeIdAndLang: (value: string) => void;
handleSubmit: (e: React.FormEvent) => void;
onManageUserClick: () => void;
onViewInfoClick?: () => void;
}
const SubmissionForm: React.FC<SubmissionFormProps> = ({
username,
setUsername,
geIdAndLang,
setGeIdAndLang,
handleSubmit,
onManageUserClick,
onViewInfoClick,
}) => {
const geIdAndLangRef = useRef<HTMLTextAreaElement>(null);
const [usernameHeight, setUsernameHeight] = useState<number | null>(null);
// Memoize callbacks to prevent unnecessary re-renders
const handleUsernameChange = useCallback((value: string) => {
setUsername(value);
}, [setUsername]);
const handleUserSelect = useCallback((user: string) => {
setUsername(user);
}, [setUsername]);
const handleHeightChange = useCallback((h: number) => {
setUsernameHeight(h);
}, []);
const handleGeIdAndLangChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
setGeIdAndLang(e.target.value);
}, [setGeIdAndLang]);
useEffect(() => {
const geIdAndLangEl = geIdAndLangRef.current;
if (!geIdAndLangEl) return;
const observer = new ResizeObserver(entries => {
window.requestAnimationFrame(() => {
if (!entries.length) return;
const newHeightPx = `${(entries[0].target as HTMLElement).offsetHeight}px`;
if (geIdAndLangEl.style.height !== newHeightPx) {
geIdAndLangEl.style.height = newHeightPx;
}
});
});
observer.observe(geIdAndLangEl);
return () => observer.disconnect();
}, []);
return (
<form onSubmit={handleSubmit}>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<UsernameAutocomplete
value={username}
onChange={handleUsernameChange}
onUserSelect={handleUserSelect}
disabled={false}
placeholder="DKI_공통_PTrinh(L)
DKI_공통_Amii(DM)"
rows={5}
onHeightChange={handleHeightChange}
/>
</div>
<div>
<textarea
ref={geIdAndLangRef}
id="geIdAndLang"
value={geIdAndLang}
onChange={handleGeIdAndLangChange}
className="bg-slate-900/50 border border-slate-700 text-slate-100 text-sm rounded-lg focus:ring-indigo-500 focus:border-indigo-500 block w-full p-2.5 transition-colors duration-200 resize-y min-h-32"
placeholder="1000 de
696 us f"
rows={5}
style={usernameHeight ? { height: `${usernameHeight}px` } : undefined}
/>
</div>
</div>
<div className="flex justify-between items-center">
<div className="flex items-center gap-4">
<button
type="submit"
className="flex justify-center items-center text-white bg-indigo-600 hover:bg-indigo-700 focus:ring-4 focus:outline-none focus:ring-indigo-800 font-medium rounded-lg text-sm px-5 py-3 text-center transition-all duration-200"
>
Cấp quyền
</button>
<button
type="button"
onClick={onManageUserClick}
className="text-white bg-slate-600 hover:bg-slate-700 focus:ring-4 focus:outline-none focus:ring-slate-800 font-medium rounded-lg text-sm px-5 py-3 text-center transition-all duration-200"
>
Quản người dùng
</button>
{onViewInfoClick && (
<button
type="button"
disabled={!geIdAndLang.trim()}
onClick={onViewInfoClick}
className="text-white bg-emerald-600 hover:bg-emerald-700 focus:ring-4 focus:outline-none focus:ring-emerald-800 font-medium rounded-lg text-sm px-5 py-3 text-center transition-all duration-200 disabled:bg-emerald-900 disabled:text-slate-500 disabled:cursor-not-allowed"
title={!geIdAndLang.trim() ? 'Vui lòng nhập GE ID & Lang' : 'Xem thông tin project TMS'}
>
Xem thông tin
</button>
)}
</div>
</div>
</form>
);
};
export default SubmissionForm;