turash/bugulma/frontend/components/add-organization/steps/BasicInfoSection.tsx
2025-12-15 10:06:41 +01:00

125 lines
3.7 KiB
TypeScript

/**
* Basic Information Section for Organization Creation
* Handles core organization details: name, sector, description
* Separated from main Step1 component for better SRP
*/
import React from 'react';
import { Control, FieldErrors, UseFormWatch } from 'react-hook-form';
import { useDynamicSectors } from '@/hooks/useDynamicSectors.ts';
import { useTranslation } from '@/hooks/useI18n.tsx';
import { OrganizationFormData } from '@/types.ts';
import FormField from '@/components/form/FormField.tsx';
import Input from '@/components/ui/Input.tsx';
import Select from '@/components/ui/Select.tsx';
interface BasicInfoSectionProps {
control: Control<OrganizationFormData>;
errors: FieldErrors<OrganizationFormData>;
watch: UseFormWatch<OrganizationFormData>;
generateDescription: (payload: [string, string, string]) => void;
isGenerating: boolean;
}
const DescriptionField = React.forwardRef<
HTMLTextAreaElement,
{
onGenerate: () => void;
isGenerating: boolean;
canGenerate: boolean;
[key: string]: unknown;
}
>(({ onGenerate, isGenerating, canGenerate, ...props }, ref) => {
const { t } = useTranslation();
return (
<div className="relative">
<textarea
ref={ref}
{...props}
placeholder={t('addOrgWizard.step1.descriptionPlaceholder')}
rows={3}
className="pr-24"
/>
<button
type="button"
onClick={onGenerate}
disabled={!canGenerate || isGenerating}
className="absolute bottom-2 right-2 px-3 py-1 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 disabled:cursor-not-allowed"
>
{isGenerating ? '...' : t('addOrgWizard.step1.generateButton')}
</button>
</div>
);
});
DescriptionField.displayName = 'DescriptionField';
export const BasicInfoSection: React.FC<BasicInfoSectionProps> = ({
control,
errors,
watch,
generateDescription,
isGenerating,
}) => {
const { t } = useTranslation();
const { sectors: dynamicSectors } = useDynamicSectors(50); // Get more sectors for selection
const translatedSectors = dynamicSectors.map((s) => ({
...s,
name: t(s.nameKey),
value: s.backendName,
}));
const [name, sector, description] = watch(['name', 'sector', 'description']);
const canGenerate = name && sector;
const handleGenerate = () => {
if (canGenerate) {
generateDescription([name, sector, description || '']);
}
};
return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-x-8 gap-y-6">
<div className="md:col-span-2 space-y-6">
<FormField
control={control}
errors={errors}
name="name"
label={t('addOrgWizard.step1.orgName')}
component={Input}
placeholder={t('addOrgWizard.step1.orgNamePlaceholder')}
required
/>
<FormField
control={control}
errors={errors}
name="sector"
label={t('addOrgWizard.step1.sector')}
component={Select}
required
>
<option value="" disabled>
{t('addOrgWizard.step1.selectSector')}
</option>
{translatedSectors.map((sector) => (
<option key={sector.nameKey} value={sector.nameKey}>
{sector.name}
</option>
))}
</FormField>
<FormField
control={control}
errors={errors}
name="description"
label={t('addOrgWizard.step1.description')}
component={DescriptionField}
onGenerate={handleGenerate}
isGenerating={isGenerating}
canGenerate={canGenerate}
required
/>
</div>
</div>
);
};