mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Remove nested git repository from bugulma/frontend/.git - Add all frontend files to main repository tracking - Convert from separate frontend/backend repos to unified monorepo - Preserve all frontend code and development history as tracked files - Eliminate nested repository complexity for simpler development workflow This creates a proper monorepo structure with frontend and backend coexisting in the same repository for easier development and deployment.
144 lines
5.1 KiB
TypeScript
144 lines
5.1 KiB
TypeScript
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
import { useAuth } from '@/contexts/AuthContext.tsx';
|
|
import { useCreateOrganization } from '@/hooks/api/useOrganizationsAPI.ts';
|
|
import { useCreateResourceFlow } from '@/hooks/api/useResourcesAPI.ts';
|
|
import { useCreateSite } from '@/hooks/api/useSitesAPI.ts';
|
|
import { useOrganizationWizard } from '@/hooks/features/useOrganizationWizard.ts';
|
|
import { useTranslation } from '@/hooks/useI18n.tsx';
|
|
import { convertNeedsAndOffersToResourceFlows } from '@/lib/resource-flow-mapper.ts';
|
|
import { OrganizationFormData } from '@/types.ts';
|
|
import ErrorMessage from '@/components/ui/ErrorMessage.tsx';
|
|
import Wizard from '@/components/wizard/Wizard.tsx';
|
|
import WizardContent from '@/components/add-organization/WizardContent.tsx';
|
|
import WizardFooter from '@/components/add-organization/WizardFooter.tsx';
|
|
|
|
interface AddOrganizationWizardProps {
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
}
|
|
|
|
const AddOrganizationWizard = ({ isOpen, onClose }: AddOrganizationWizardProps) => {
|
|
const { t } = useTranslation();
|
|
const { isAuthenticated } = useAuth();
|
|
const navigate = useNavigate();
|
|
const [error, setError] = useState<string | null>(null);
|
|
const createOrgMutation = useCreateOrganization();
|
|
const createSiteMutation = useCreateSite();
|
|
const createResourceFlowMutation = useCreateResourceFlow();
|
|
|
|
// Redirect to login if not authenticated
|
|
useEffect(() => {
|
|
if (isOpen && !isAuthenticated) {
|
|
navigate('/login');
|
|
onClose();
|
|
}
|
|
}, [isOpen, isAuthenticated, navigate, onClose]);
|
|
|
|
const onSuccess = useCallback(
|
|
async (data: OrganizationFormData) => {
|
|
try {
|
|
setError(null);
|
|
// Step 1: Create organization (backend API only accepts basic fields)
|
|
const orgPayload = {
|
|
name: data.name,
|
|
sector: data.sector,
|
|
description: data.description,
|
|
subtype: data.subtype,
|
|
website: data.website || '',
|
|
address: data.address
|
|
? `${data.address.street}, ${data.address.city}, ${data.address.state} ${data.address.zip}`.trim()
|
|
: '',
|
|
logoUrl: data.logoUrl || '',
|
|
galleryImages: data.galleryImages || [],
|
|
};
|
|
|
|
const newOrg = await createOrgMutation.mutateAsync(orgPayload);
|
|
if (!newOrg?.ID) {
|
|
throw new Error('Failed to create organization');
|
|
}
|
|
|
|
// Step 2: Create a default Site for the organization
|
|
const sitePayload = {
|
|
name: `${data.name} - Main Site`,
|
|
address: orgPayload.address,
|
|
latitude: data.location.lat,
|
|
longitude: data.location.lng,
|
|
owner_organization_id: newOrg.ID,
|
|
};
|
|
|
|
const newSite = await createSiteMutation.mutateAsync(sitePayload);
|
|
if (!newSite?.ID) {
|
|
throw new Error('Failed to create site');
|
|
}
|
|
|
|
// Step 3: Convert user-friendly needs/offers to ResourceFlows and create them
|
|
const resourceFlows = convertNeedsAndOffersToResourceFlows(data, newOrg.ID, newSite.ID);
|
|
|
|
// Create all ResourceFlows in parallel
|
|
await Promise.all(
|
|
resourceFlows.map((flow) => createResourceFlowMutation.mutateAsync(flow))
|
|
);
|
|
|
|
onClose();
|
|
navigate('/map');
|
|
} catch (error) {
|
|
const errorMessage =
|
|
error instanceof Error ? error.message : 'Failed to create organization';
|
|
setError(errorMessage);
|
|
console.error('Error creating organization:', error);
|
|
}
|
|
},
|
|
[createOrgMutation, createSiteMutation, createResourceFlowMutation, onClose, navigate]
|
|
);
|
|
|
|
const { wizardState, form, smartFill, descriptionGeneration, actions } = useOrganizationWizard({
|
|
onSuccess,
|
|
});
|
|
|
|
// Track previous isOpen value to detect when it changes from true to false
|
|
const prevIsOpenRef = useRef(isOpen);
|
|
|
|
// Reset form and wizard state when dialog closes (transitions from open to closed)
|
|
useEffect(() => {
|
|
if (prevIsOpenRef.current && !isOpen) {
|
|
actions.resetWizard();
|
|
}
|
|
prevIsOpenRef.current = isOpen;
|
|
}, [isOpen, actions]);
|
|
|
|
return (
|
|
<>
|
|
{error && (
|
|
<div className="mb-4">
|
|
<ErrorMessage message={error} />
|
|
</div>
|
|
)}
|
|
<Wizard isOpen={isOpen} onClose={onClose} title={t('addOrgWizard.title')}>
|
|
<WizardContent
|
|
currentStep={wizardState.currentStep}
|
|
form={form}
|
|
onSmartFill={smartFill.extractFromText}
|
|
onManualFill={wizardState.nextStep}
|
|
isParsing={smartFill.isExtractingFromText}
|
|
parseError={null}
|
|
generateDescription={descriptionGeneration.generateDescription}
|
|
isGenerating={descriptionGeneration.isGeneratingDescription}
|
|
/>
|
|
{wizardState.currentStep > 1 && (
|
|
<WizardFooter
|
|
isFirstStep={wizardState.isFirstStep}
|
|
isLastStep={wizardState.isLastStep}
|
|
onBack={wizardState.prevStep}
|
|
onNext={actions.handleNext}
|
|
onSubmit={form.handleSubmit(actions.onSubmit)}
|
|
isValid={form.formState.isValid}
|
|
/>
|
|
)}
|
|
</Wizard>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default AddOrganizationWizard;
|