feat(Makefile): patch Layout.jsx queryKey for local development feat(frontend-web): mock base44 client for local development with role switching feat(frontend-web): add event assignment modal with conflict detection and bulk assign feat(frontend-web): add client dashboard with key metrics and quick actions feat(frontend-web): add layout component with role-based navigation feat(frontend-web): update various pages to use "@/components" alias feat(frontend-web): update create event page with ai assistant toggle feat(frontend-web): update dashboard page with new components feat(frontend-web): update events page with quick assign popover feat(frontend-web): update invite vendor page with hover card feat(frontend-web): update messages page with conversation list and message thread feat(frontend-web): update operator dashboard page with new components feat(frontend-web): update partner management page with new components feat(frontend-web): update permissions page with new components feat(frontend-web): update procurement dashboard page with new components feat(frontend-web): update smart vendor onboarding page with new components feat(frontend-web): update staff directory page with new components feat(frontend-web): update teams page with new components feat(frontend-web): update user management page with new components feat(frontend-web): update vendor compliance page with new components feat(frontend-web): update main.jsx to include react query provider feat: add vendor marketplace page feat: add global import fix to prepare-export script feat: add patch-layout-query-key script to fix query key feat: update patch-base44-client script to use a more robust method
239 lines
8.7 KiB
JavaScript
239 lines
8.7 KiB
JavaScript
import React, { useState } from "react";
|
|
import { base44 } from "@/api/base44Client";
|
|
import { useMutation, useQueryClient, useQuery } from "@tanstack/react-query";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { createPageUrl } from "@/utils";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
import { MapPin, ArrowLeft, Save, Loader2 } from "lucide-react";
|
|
import PageHeader from "@/components/common/PageHeader";
|
|
import { useToast } from "@/components/ui/use-toast";
|
|
|
|
export default function EditSector() {
|
|
const navigate = useNavigate();
|
|
const queryClient = useQueryClient();
|
|
const { toast } = useToast();
|
|
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const sectorId = urlParams.get('id');
|
|
|
|
const { data: sectors = [] } = useQuery({
|
|
queryKey: ['sectors'],
|
|
queryFn: () => base44.entities.Sector.list(),
|
|
initialData: [],
|
|
});
|
|
|
|
const { data: enterprises = [] } = useQuery({
|
|
queryKey: ['enterprises'],
|
|
queryFn: () => base44.entities.Enterprise.list(),
|
|
initialData: [],
|
|
});
|
|
|
|
const sector = sectors.find(s => s.id === sectorId);
|
|
|
|
const [sectorData, setSectorData] = useState({
|
|
sector_number: "",
|
|
sector_name: "",
|
|
sector_code: "",
|
|
parent_enterprise_id: "",
|
|
parent_enterprise_name: "",
|
|
sector_type: "Food Service",
|
|
sector_policies: {
|
|
uniform_requirements: "",
|
|
certification_requirements: [],
|
|
special_training: []
|
|
},
|
|
is_active: true
|
|
});
|
|
|
|
React.useEffect(() => {
|
|
if (sector) {
|
|
setSectorData({
|
|
sector_number: sector.sector_number || "",
|
|
sector_name: sector.sector_name || "",
|
|
sector_code: sector.sector_code || "",
|
|
parent_enterprise_id: sector.parent_enterprise_id || "",
|
|
parent_enterprise_name: sector.parent_enterprise_name || "",
|
|
sector_type: sector.sector_type || "Food Service",
|
|
sector_policies: sector.sector_policies || {
|
|
uniform_requirements: "",
|
|
certification_requirements: [],
|
|
special_training: []
|
|
},
|
|
is_active: sector.is_active !== undefined ? sector.is_active : true
|
|
});
|
|
}
|
|
}, [sector]);
|
|
|
|
const updateSectorMutation = useMutation({
|
|
mutationFn: ({ id, data }) => base44.entities.Sector.update(id, data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['sectors'] });
|
|
toast({
|
|
title: "Sector Updated",
|
|
description: "Sector has been successfully updated",
|
|
});
|
|
navigate(createPageUrl("SectorManagement"));
|
|
},
|
|
});
|
|
|
|
const handleSubmit = (e) => {
|
|
e.preventDefault();
|
|
updateSectorMutation.mutate({ id: sectorId, data: sectorData });
|
|
};
|
|
|
|
const handleEnterpriseChange = (enterpriseId) => {
|
|
const enterprise = enterprises.find(e => e.id === enterpriseId);
|
|
setSectorData({
|
|
...sectorData,
|
|
parent_enterprise_id: enterpriseId,
|
|
parent_enterprise_name: enterprise?.enterprise_name || ""
|
|
});
|
|
};
|
|
|
|
if (!sector) {
|
|
return (
|
|
<div className="p-8 text-center">
|
|
<Loader2 className="w-8 h-8 animate-spin text-[#0A39DF] mx-auto mb-4" />
|
|
<h2 className="text-2xl font-bold text-slate-900 mb-4">Loading Sector...</h2>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="p-4 md:p-8 bg-slate-50 min-h-screen">
|
|
<div className="max-w-4xl mx-auto">
|
|
<PageHeader
|
|
title="Edit Sector"
|
|
subtitle={`Update information for ${sector.sector_name}`}
|
|
backTo={createPageUrl("SectorManagement")}
|
|
backButtonLabel="Back to Sectors"
|
|
/>
|
|
|
|
<form onSubmit={handleSubmit}>
|
|
<Card className="mb-6 border-slate-200 shadow-lg">
|
|
<CardHeader className="bg-gradient-to-br from-slate-50 to-white border-b">
|
|
<CardTitle className="flex items-center gap-2">
|
|
<MapPin className="w-5 h-5 text-[#0A39DF]" />
|
|
Basic Information
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="p-6 space-y-6">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div>
|
|
<Label htmlFor="sector_number">Sector Number</Label>
|
|
<Input
|
|
id="sector_number"
|
|
value={sectorData.sector_number}
|
|
readOnly
|
|
className="bg-slate-50 font-mono"
|
|
/>
|
|
<p className="text-xs text-slate-500 mt-1">Auto-generated unique ID</p>
|
|
</div>
|
|
|
|
<div>
|
|
<Label htmlFor="sector_code">Sector Code *</Label>
|
|
<Input
|
|
id="sector_code"
|
|
placeholder="e.g., BON"
|
|
value={sectorData.sector_code}
|
|
onChange={(e) => setSectorData({...sectorData, sector_code: e.target.value.toUpperCase()})}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div className="md:col-span-2">
|
|
<Label htmlFor="sector_name">Sector Name *</Label>
|
|
<Input
|
|
id="sector_name"
|
|
placeholder="e.g., Bon Appétit"
|
|
value={sectorData.sector_name}
|
|
onChange={(e) => setSectorData({...sectorData, sector_name: e.target.value})}
|
|
required
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<Label htmlFor="parent_enterprise">Parent Enterprise</Label>
|
|
<Select onValueChange={handleEnterpriseChange} value={sectorData.parent_enterprise_id}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select enterprise" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{enterprises.map((enterprise) => (
|
|
<SelectItem key={enterprise.id} value={enterprise.id}>
|
|
{enterprise.enterprise_name}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div>
|
|
<Label htmlFor="sector_type">Sector Type *</Label>
|
|
<Select onValueChange={(value) => setSectorData({...sectorData, sector_type: value})} value={sectorData.sector_type}>
|
|
<SelectTrigger>
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="Food Service">Food Service</SelectItem>
|
|
<SelectItem value="Facilities">Facilities</SelectItem>
|
|
<SelectItem value="Healthcare">Healthcare</SelectItem>
|
|
<SelectItem value="Education">Education</SelectItem>
|
|
<SelectItem value="Corporate">Corporate</SelectItem>
|
|
<SelectItem value="Sports & Entertainment">Sports & Entertainment</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<Label htmlFor="uniform_requirements">Uniform Requirements</Label>
|
|
<Input
|
|
id="uniform_requirements"
|
|
placeholder="e.g., Black chef coat, black pants, non-slip shoes"
|
|
value={sectorData.sector_policies?.uniform_requirements || ""}
|
|
onChange={(e) => setSectorData({
|
|
...sectorData,
|
|
sector_policies: {...sectorData.sector_policies, uniform_requirements: e.target.value}
|
|
})}
|
|
/>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<div className="flex justify-end gap-3">
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
onClick={() => navigate(createPageUrl("SectorManagement"))}
|
|
>
|
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
type="submit"
|
|
className="bg-[#0A39DF] hover:bg-[#0A39DF]/90"
|
|
disabled={updateSectorMutation.isPending}
|
|
>
|
|
{updateSectorMutation.isPending ? (
|
|
<>
|
|
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
|
Updating...
|
|
</>
|
|
) : (
|
|
<>
|
|
<Save className="w-4 h-4 mr-2" />
|
|
Update Sector
|
|
</>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
} |