Refactor: Unify moderation queue for all entities

This commit is contained in:
gpt-engineer-app[bot]
2025-10-01 20:00:22 +00:00
parent 5831705fe2
commit d100e0188b
11 changed files with 94 additions and 223 deletions

View File

@@ -15,14 +15,15 @@ export interface CompanyFormData {
export async function submitCompanyCreation(
data: CompanyFormData,
companyType: 'manufacturer' | 'designer' | 'operator' | 'property_owner',
userId: string,
isModerator: boolean
userId: string
) {
if (isModerator) {
// Moderators can create directly
const { data: newCompany, error } = await supabase
.from('companies')
.insert({
// All users submit for moderation
const { error } = await supabase
.from('content_submissions')
.insert([{
user_id: userId,
submission_type: 'company_create',
content: {
name: data.name,
slug: data.slug,
description: data.description,
@@ -30,50 +31,29 @@ export async function submitCompanyCreation(
website_url: data.website_url,
founded_year: data.founded_year,
headquarters_location: data.headquarters_location,
company_type: companyType
})
.select()
.single();
company_type: companyType,
images: data.images as any // Include image assignments in submission
} as any,
status: 'pending'
}]);
if (error) throw error;
return { company: newCompany, submitted: false };
} else {
// Regular users submit for moderation
const { error } = await supabase
.from('content_submissions')
.insert([{
user_id: userId,
submission_type: 'company_create',
content: {
name: data.name,
slug: data.slug,
description: data.description,
person_type: data.person_type,
website_url: data.website_url,
founded_year: data.founded_year,
headquarters_location: data.headquarters_location,
company_type: companyType,
images: data.images as any // Include image assignments in submission
} as any,
status: 'pending'
}]);
if (error) throw error;
return { company: null, submitted: true };
}
if (error) throw error;
return { submitted: true };
}
export async function submitCompanyUpdate(
companyId: string,
data: CompanyFormData,
userId: string,
isModerator: boolean
userId: string
) {
if (isModerator) {
// Moderators can update directly
const { error } = await supabase
.from('companies')
.update({
// All users submit for moderation
const { error } = await supabase
.from('content_submissions')
.insert([{
user_id: userId,
submission_type: 'company_edit',
content: {
company_id: companyId,
name: data.name,
slug: data.slug,
description: data.description,
@@ -81,34 +61,11 @@ export async function submitCompanyUpdate(
website_url: data.website_url,
founded_year: data.founded_year,
headquarters_location: data.headquarters_location,
updated_at: new Date().toISOString()
})
.eq('id', companyId);
images: data.images as any // Include image role assignments in submission
} as any,
status: 'pending'
}]);
if (error) throw error;
return { submitted: false };
} else {
// Regular users submit for moderation
const { error } = await supabase
.from('content_submissions')
.insert([{
user_id: userId,
submission_type: 'company_edit',
content: {
company_id: companyId,
name: data.name,
slug: data.slug,
description: data.description,
person_type: data.person_type,
website_url: data.website_url,
founded_year: data.founded_year,
headquarters_location: data.headquarters_location,
images: data.images as any // Include image role assignments in submission
} as any,
status: 'pending'
}]);
if (error) throw error;
return { submitted: true };
}
if (error) throw error;
return { submitted: true };
}

View File

@@ -51,24 +51,18 @@ export default function DesignerDetail() {
const handleEditSubmit = async (data: any) => {
try {
const result = await submitCompanyUpdate(
await submitCompanyUpdate(
designer!.id,
data,
user!.id,
isModerator()
user!.id
);
toast({
title: result.submitted ? "Edit Submitted" : "Designer Updated",
description: result.submitted
? "Your edit has been submitted for review."
: "The designer has been updated successfully."
title: "Edit Submitted",
description: "Your edit has been submitted for review."
});
setIsEditModalOpen(false);
if (!result.submitted) {
fetchDesignerData();
}
} catch (error: any) {
toast({
title: "Error",

View File

@@ -32,15 +32,14 @@ export default function Designers() {
navigate('/auth');
return;
}
const result = await submitCompanyCreation(data, 'designer', user.id, isModerator());
await submitCompanyCreation(data, 'designer', user.id);
toast({
title: result.submitted ? "Designer Submitted" : "Designer Created",
description: result.submitted ? "Your submission has been sent for review." : "The designer has been created successfully."
title: "Designer Submitted",
description: "Your submission has been sent for review."
});
setIsCreateModalOpen(false);
if (!result.submitted) fetchCompanies();
} catch (error: any) {
toast({ title: "Error", description: error.message || "Failed to create designer.", variant: "destructive" });
toast({ title: "Error", description: error.message || "Failed to submit designer.", variant: "destructive" });
}
};

View File

@@ -51,24 +51,18 @@ export default function ManufacturerDetail() {
const handleEditSubmit = async (data: any) => {
try {
const result = await submitCompanyUpdate(
await submitCompanyUpdate(
manufacturer!.id,
data,
user!.id,
isModerator()
user!.id
);
toast({
title: result.submitted ? "Edit Submitted" : "Manufacturer Updated",
description: result.submitted
? "Your edit has been submitted for review."
: "The manufacturer has been updated successfully."
title: "Edit Submitted",
description: "Your edit has been submitted for review."
});
setIsEditModalOpen(false);
if (!result.submitted) {
fetchManufacturerData();
}
} catch (error: any) {
toast({
title: "Error",

View File

@@ -71,28 +71,22 @@ export default function Manufacturers() {
return;
}
const result = await submitCompanyCreation(
await submitCompanyCreation(
data,
'manufacturer',
user.id,
isModerator()
user.id
);
toast({
title: result.submitted ? "Manufacturer Submitted" : "Manufacturer Created",
description: result.submitted
? "Your submission has been sent for review."
: "The manufacturer has been created successfully."
title: "Manufacturer Submitted",
description: "Your submission has been sent for review."
});
setIsCreateModalOpen(false);
if (!result.submitted) {
fetchCompanies();
}
} catch (error: any) {
toast({
title: "Error",
description: error.message || "Failed to create manufacturer.",
description: error.message || "Failed to submit manufacturer.",
variant: "destructive"
});
}

View File

@@ -51,24 +51,18 @@ export default function OperatorDetail() {
const handleEditSubmit = async (data: any) => {
try {
const result = await submitCompanyUpdate(
await submitCompanyUpdate(
operator!.id,
data,
user!.id,
isModerator()
user!.id
);
toast({
title: result.submitted ? "Edit Submitted" : "Operator Updated",
description: result.submitted
? "Your edit has been submitted for review."
: "The operator has been updated successfully."
title: "Edit Submitted",
description: "Your edit has been submitted for review."
});
setIsEditModalOpen(false);
if (!result.submitted) {
fetchOperatorData();
}
} catch (error: any) {
toast({
title: "Error",

View File

@@ -64,25 +64,22 @@ const Operators = () => {
return;
}
const result = await submitCompanyCreation(
await submitCompanyCreation(
data,
'operator',
user.id,
isModerator()
user.id
);
toast({
title: result.submitted ? "Operator Submitted" : "Operator Created",
description: result.submitted
? "Your submission has been sent for review."
: "The operator has been created successfully."
title: "Operator Submitted",
description: "Your submission has been sent for review."
});
setIsCreateModalOpen(false);
} catch (error: any) {
toast({
title: "Error",
description: error.message || "Failed to create operator.",
description: error.message || "Failed to submit operator.",
variant: "destructive"
});
}

View File

@@ -64,25 +64,22 @@ const ParkOwners = () => {
return;
}
const result = await submitCompanyCreation(
await submitCompanyCreation(
data,
'property_owner',
user.id,
isModerator()
user.id
);
toast({
title: result.submitted ? "Property Owner Submitted" : "Property Owner Created",
description: result.submitted
? "Your submission has been sent for review."
: "The property owner has been created successfully."
title: "Property Owner Submitted",
description: "Your submission has been sent for review."
});
setIsCreateModalOpen(false);
} catch (error: any) {
toast({
title: "Error",
description: error.message || "Failed to create property owner.",
description: error.message || "Failed to submit property owner.",
variant: "destructive"
});
}

View File

@@ -250,58 +250,24 @@ export default function Parks() {
}
try {
if (isModerator()) {
// Moderators can create parks directly
const { error } = await supabase
.from('parks')
.insert({
name: parkData.name,
slug: parkData.slug,
description: parkData.description || null,
park_type: parkData.park_type,
status: parkData.status,
opening_date: parkData.opening_date || null,
closing_date: parkData.closing_date || null,
website_url: parkData.website_url || null,
phone: parkData.phone || null,
email: parkData.email || null,
banner_image_url: parkData.banner_image_url || null,
banner_image_id: parkData.banner_image_id || null,
card_image_url: parkData.card_image_url || null,
card_image_id: parkData.card_image_id || null,
operator_id: parkData.operator_id || null,
property_owner_id: parkData.property_owner_id || null
});
if (error) throw error;
toast({
title: "Park Created",
description: "The park has been created successfully.",
// All users submit for moderation
const { error } = await supabase
.from('content_submissions')
.insert({
user_id: user.id,
submission_type: 'park',
status: 'pending',
content: parkData
});
setIsAddParkModalOpen(false);
fetchParks();
} else {
// Regular users submit for moderation
const { error } = await supabase
.from('content_submissions')
.insert({
user_id: user.id,
submission_type: 'park',
status: 'pending',
content: parkData
});
if (error) throw error;
if (error) throw error;
toast({
title: "Park Submitted",
description: "Your park submission has been sent for moderation review.",
});
toast({
title: "Submission Sent",
description: "Your park submission has been sent for moderation review.",
});
setIsAddParkModalOpen(false);
}
setIsAddParkModalOpen(false);
} catch (error: any) {
toast({
title: "Submission Failed",
@@ -477,7 +443,7 @@ export default function Parks() {
<DialogHeader>
<DialogTitle>Add New Park</DialogTitle>
<DialogDescription>
Add a new park to the database. {isModerator() ? 'The park will be added immediately.' : 'Your submission will be reviewed before being published.'}
Add a new park to the database. Your submission will be reviewed before being published.
</DialogDescription>
</DialogHeader>
<ParkForm

View File

@@ -51,24 +51,18 @@ export default function PropertyOwnerDetail() {
const handleEditSubmit = async (data: any) => {
try {
const result = await submitCompanyUpdate(
await submitCompanyUpdate(
owner!.id,
data,
user!.id,
isModerator()
user!.id
);
toast({
title: result.submitted ? "Edit Submitted" : "Property Owner Updated",
description: result.submitted
? "Your edit has been submitted for review."
: "The property owner has been updated successfully."
title: "Edit Submitted",
description: "Your edit has been submitted for review."
});
setIsEditModalOpen(false);
if (!result.submitted) {
fetchOwnerData();
}
} catch (error: any) {
toast({
title: "Error",

View File

@@ -83,39 +83,24 @@ export default function Rides() {
return;
}
if (isModerator()) {
const { error } = await supabase
.from('rides')
.insert(data);
if (error) throw error;
toast({
title: "Ride Created",
description: "The ride has been created successfully.",
// All users submit for moderation
const { error } = await supabase
.from('content_submissions')
.insert({
user_id: user.id,
submission_type: 'ride',
status: 'pending',
content: data
});
setIsCreateModalOpen(false);
fetchRides();
} else {
const { error } = await supabase
.from('content_submissions')
.insert({
user_id: user.id,
submission_type: 'ride',
status: 'pending',
content: data
});
if (error) throw error;
if (error) throw error;
toast({
title: "Ride Submitted",
description: "Your ride submission has been sent for moderation review.",
});
toast({
title: "Submission Sent",
description: "Your ride submission has been sent for moderation review.",
});
setIsCreateModalOpen(false);
}
setIsCreateModalOpen(false);
} catch (error: any) {
toast({
title: "Submission Failed",