tethys.backend/resources/js/composables/useDatasetFormSubmission.ts
Arno Kaimbacher 5efddc2a58
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s
feat: add dataset change detection and form submission composables
- Implemented `useDatasetChangeDetection` for tracking unsaved changes in dataset forms, including comparisons for licenses, basic properties, files, coverage, and more.
- Added `useDatasetFormSubmission` for handling dataset form submissions with validation, success/error handling, and auto-save functionality.
2026-01-12 17:02:47 +01:00

217 lines
No EOL
6 KiB
TypeScript

// ====================================================================
// FILE: composables/useDatasetFormSubmission.ts
// ====================================================================
import { Ref } from 'vue';
import type { Dataset, License } from '@/Dataset';
import { InertiaForm } from '@inertiajs/vue3';
import { stardust } from '@eidellev/adonis-stardust/client';
import { notify } from '@/notiwind';
interface SubmissionOptions {
onSuccess?: (updatedDataset: Dataset) => void;
onError?: (errors: any) => void;
showNotification?: boolean;
}
export function useDatasetFormSubmission(
form: InertiaForm<Dataset>,
originalDataset: Ref<Dataset>
) {
/**
* Check if object has id attribute (type guard)
*/
const hasIdAttribute = (obj: License | number): obj is License => {
return typeof obj === 'object' && 'id' in obj;
};
/**
* Transform licenses for submission
*/
const transformLicenses = (): string[] => {
return form.licenses.map((obj) => {
if (hasIdAttribute(obj)) {
return obj.id.toString();
}
return String(obj);
});
};
/**
* Validate form before submission
*/
const validateForm = (): { valid: boolean; errors: string[] } => {
const errors: string[] = [];
// Required field validations
if (!form.language) {
errors.push('Language is required');
}
if (!form.type) {
errors.push('Dataset type is required');
}
if (!form.creating_corporation) {
errors.push('Creating corporation is required');
}
if (!form.titles || !form.titles[0]?.value) {
errors.push('Main title is required');
}
if (!form.descriptions || !form.descriptions[0]?.value) {
errors.push('Main abstract is required');
}
return {
valid: errors.length === 0,
errors,
};
};
/**
* Handle successful submission
*/
const handleSubmitSuccess = (
updatedDataset: Dataset,
showNotification: boolean = true
) => {
// Clear deletion arrays
if (updatedDataset.subjectsToDelete) {
updatedDataset.subjectsToDelete = [];
}
if (updatedDataset.referencesToDelete) {
updatedDataset.referencesToDelete = [];
}
// Update form with fresh data from server
Object.keys(updatedDataset).forEach((key) => {
if (key !== 'licenses' && key in form) {
form[key] = updatedDataset[key];
}
});
// Clear form errors
form.clearErrors();
// Update original dataset reference
originalDataset.value = JSON.parse(JSON.stringify(updatedDataset));
// Show success notification
if (showNotification) {
notify(
{
type: 'success',
title: 'Success',
text: 'Dataset updated successfully',
},
4000,
);
}
};
/**
* Handle submission errors
*/
const handleSubmitError = (errors: any) => {
console.error('Submission errors:', errors);
notify(
{
type: 'error',
title: 'Error',
text: 'Failed to update dataset. Please check the form for errors.',
},
5000,
);
};
/**
* Submit form with auto-save behavior
*/
const submitWithAutoSave = async (
options: SubmissionOptions = {}
): Promise<void> => {
try {
const route = stardust.route('editor.dataset.update', [form.id]);
const licenses = transformLicenses();
await form
.transform((data) => ({
...data,
licenses,
rights: 'true',
}))
.put(route, {
onSuccess: (page) => {
const updatedDataset = page.props.dataset || form.data();
handleSubmitSuccess(
updatedDataset,
options.showNotification ?? true
);
if (options.onSuccess) {
options.onSuccess(updatedDataset);
}
},
onError: (errors) => {
handleSubmitError(errors);
if (options.onError) {
options.onError(errors);
}
},
});
} catch (error) {
console.error('Unexpected error during submission:', error);
notify(
{
type: 'error',
title: 'Error',
text: 'An unexpected error occurred. Please try again.',
},
5000,
);
}
};
/**
* Standard submit with validation
*/
const submit = async (
options: SubmissionOptions = {}
): Promise<void> => {
// Validate form first
const validation = validateForm();
if (!validation.valid) {
notify(
{
type: 'error',
title: 'Validation Error',
text: validation.errors.join(', '),
},
5000,
);
return;
}
await submitWithAutoSave({
...options,
showNotification: true,
});
};
/**
* Silent submit without notification (for auto-save)
*/
const submitSilently = async (): Promise<void> => {
await submitWithAutoSave({
showNotification: false,
});
};
return {
submit,
submitWithAutoSave,
submitSilently,
validateForm,
transformLicenses,
};
}