This commit establishes the new monorepo architecture for the KROW Workforce platform. Key changes include: - Reorganized project into `frontend-web`, `mobile-apps`, `firebase`, `scripts`, and `secrets` directories. - Updated `Makefile` to support the new monorepo layout and automate Base44 export integration. - Fixed `scripts/prepare-export.js` for ES module compatibility and global component import resolution. - Created and updated `CONTRIBUTING.md` for developer onboarding. - Restructured, renamed, and translated all `docs/` files for clarity and consistency. - Implemented an interactive internal launchpad with diagram viewing capabilities. - Configured base Firebase project files (`firebase.json`, security rules). - Updated `README.md` to reflect the new project structure and documentation overview.
243 lines
9.0 KiB
JavaScript
243 lines
9.0 KiB
JavaScript
|
|
import React from "react";
|
|
import { base44 } from "@/api/base44Client";
|
|
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
import { useNavigate } from "react-router-dom";
|
|
import { createPageUrl } from "@/utils";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
|
import { Input } from "@/components/ui/input";
|
|
import { Label } from "@/components/ui/label";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
import { ArrowLeft, Save, Loader2 } from "lucide-react";
|
|
|
|
export default function EditBusiness() {
|
|
const navigate = useNavigate();
|
|
const queryClient = useQueryClient();
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
const businessId = urlParams.get('id');
|
|
|
|
const { data: allBusinesses, isLoading } = useQuery({
|
|
queryKey: ['businesses'],
|
|
queryFn: () => base44.entities.Business.list(),
|
|
initialData: [],
|
|
});
|
|
|
|
const business = allBusinesses.find(b => b.id === businessId);
|
|
|
|
const [formData, setFormData] = React.useState({
|
|
business_name: "",
|
|
company_logo: "",
|
|
contact_name: "",
|
|
email: "",
|
|
phone: "",
|
|
address: "",
|
|
notes: ""
|
|
});
|
|
|
|
React.useEffect(() => {
|
|
if (business) {
|
|
setFormData({
|
|
business_name: business.business_name || "",
|
|
company_logo: business.company_logo || "",
|
|
contact_name: business.contact_name || "",
|
|
email: business.email || "",
|
|
phone: business.phone || "",
|
|
address: business.address || "",
|
|
notes: business.notes || ""
|
|
});
|
|
}
|
|
}, [business]);
|
|
|
|
const updateBusinessMutation = useMutation({
|
|
mutationFn: ({ id, data }) => base44.entities.Business.update(id, data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['businesses'] });
|
|
navigate(createPageUrl("Business"));
|
|
},
|
|
});
|
|
|
|
const handleChange = (field, value) => {
|
|
setFormData(prev => ({ ...prev, [field]: value }));
|
|
};
|
|
|
|
const handleSubmit = (e) => {
|
|
e.preventDefault();
|
|
updateBusinessMutation.mutate({ id: businessId, data: formData });
|
|
};
|
|
|
|
if (isLoading) {
|
|
return (
|
|
<div className="flex items-center justify-center min-h-screen">
|
|
<Loader2 className="w-8 h-8 animate-spin text-blue-600" />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (!business) {
|
|
return (
|
|
<div className="p-8 text-center">
|
|
<h2 className="text-2xl font-bold text-slate-900 mb-4">Business Not Found</h2>
|
|
<Button onClick={() => navigate(createPageUrl("Business"))}>
|
|
Back to Businesses
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="p-4 md:p-8">
|
|
<div className="max-w-4xl mx-auto">
|
|
<div className="mb-8">
|
|
<Button
|
|
variant="ghost"
|
|
onClick={() => navigate(createPageUrl("Business"))}
|
|
className="mb-4 hover:bg-slate-100"
|
|
>
|
|
<ArrowLeft className="w-4 h-4 mr-2" />
|
|
Back to Businesses
|
|
</Button>
|
|
<h1 className="text-3xl md:text-4xl font-bold text-slate-900 mb-2">Edit Business Client</h1>
|
|
<p className="text-slate-600">Update information for {business.business_name}</p>
|
|
</div>
|
|
|
|
<form onSubmit={handleSubmit}>
|
|
<Card className="border-slate-200 shadow-lg">
|
|
<CardHeader className="bg-gradient-to-br from-slate-50 to-white border-b border-slate-100">
|
|
<CardTitle className="text-slate-900">Business Information</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="p-6">
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
<div className="space-y-2 md:col-span-2">
|
|
<Label htmlFor="business_name" className="text-slate-700 font-medium">Business Name *</Label>
|
|
<Input
|
|
id="business_name"
|
|
value={formData.business_name}
|
|
onChange={(e) => handleChange('business_name', e.target.value)}
|
|
required
|
|
className="border-slate-200"
|
|
placeholder="Enter business name"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2 md:col-span-2">
|
|
<Label htmlFor="company_logo" className="text-slate-700 font-medium">Company Logo URL</Label>
|
|
<Input
|
|
id="company_logo"
|
|
value={formData.company_logo}
|
|
onChange={(e) => handleChange('company_logo', e.target.value)}
|
|
className="border-slate-200"
|
|
placeholder="https://example.com/logo.png"
|
|
/>
|
|
<p className="text-xs text-slate-500">Optional: URL to company logo image</p>
|
|
{formData.company_logo && (
|
|
<div className="mt-2 p-3 bg-slate-50 rounded-lg border border-slate-200">
|
|
<p className="text-xs text-slate-600 mb-2">Preview:</p>
|
|
<img
|
|
src={formData.company_logo}
|
|
alt="Company logo preview"
|
|
className="w-16 h-16 object-contain"
|
|
onError={(e) => {
|
|
e.target.style.display = 'none';
|
|
e.target.parentElement.innerHTML = '<p class="text-xs text-red-500">Failed to load image</p>';
|
|
}}
|
|
/>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label htmlFor="contact_name" className="text-slate-700 font-medium">Contact Person</Label>
|
|
<Input
|
|
id="contact_name"
|
|
value={formData.contact_name}
|
|
onChange={(e) => handleChange('contact_name', e.target.value)}
|
|
className="border-slate-200"
|
|
placeholder="Primary contact name"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label htmlFor="phone" className="text-slate-700 font-medium">Phone Number</Label>
|
|
<Input
|
|
id="phone"
|
|
type="tel"
|
|
value={formData.phone}
|
|
onChange={(e) => handleChange('phone', e.target.value)}
|
|
className="border-slate-200"
|
|
placeholder="(555) 123-4567"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2 md:col-span-2">
|
|
<Label htmlFor="email" className="text-slate-700 font-medium">Email</Label>
|
|
<Input
|
|
id="email"
|
|
type="email"
|
|
value={formData.email}
|
|
onChange={(e) => handleChange('email', e.target.value)}
|
|
className="border-slate-200"
|
|
placeholder="business@example.com"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2 md:col-span-2">
|
|
<Label htmlFor="address" className="text-slate-700 font-medium">Address</Label>
|
|
<Textarea
|
|
id="address"
|
|
value={formData.address}
|
|
onChange={(e) => handleChange('address', e.target.value)}
|
|
rows={3}
|
|
className="border-slate-200"
|
|
placeholder="Full address including street, city, state, and zip"
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2 md:col-span-2">
|
|
<Label htmlFor="notes" className="text-slate-700 font-medium">Notes</Label>
|
|
<Textarea
|
|
id="notes"
|
|
value={formData.notes}
|
|
onChange={(e) => handleChange('notes', e.target.value)}
|
|
rows={4}
|
|
className="border-slate-200"
|
|
placeholder="Additional notes about this business..."
|
|
/>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<div className="flex justify-end gap-3 mt-6">
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
onClick={() => navigate(createPageUrl("Business"))}
|
|
className="border-slate-300"
|
|
>
|
|
Cancel
|
|
</Button>
|
|
<Button
|
|
type="submit"
|
|
disabled={updateBusinessMutation.isPending}
|
|
className="bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 text-white shadow-lg"
|
|
>
|
|
{updateBusinessMutation.isPending ? (
|
|
<>
|
|
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
|
Updating...
|
|
</>
|
|
) : (
|
|
<>
|
|
<Save className="w-4 h-4 mr-2" />
|
|
Update Business
|
|
</>
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|