refactor(components): finish rename of storyForm.vue
				
					
				
			also add mechanisms to save drafts beyond the original debounced functions
This commit is contained in:
		
							parent
							
								
									8a7c10b63a
								
							
						
					
					
						commit
						d4ae55a25b
					
				
							
								
								
									
										209
									
								
								components/story/create/storyForm.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								components/story/create/storyForm.vue
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,209 @@ | |||||||
|  | <script setup lang="ts"> | ||||||
|  | 	import draggable from "vuedraggable"; | ||||||
|  | 	import { v4 } from "uuid"; | ||||||
|  | 	import lmove from "lodash-move"; | ||||||
|  | 	import { | ||||||
|  | 		Field, | ||||||
|  | 		Form as veeForm, | ||||||
|  | 		FieldArray, | ||||||
|  | 		FieldEntry, | ||||||
|  | 		useForm, | ||||||
|  | 	} from "vee-validate"; | ||||||
|  | 	import { storySchema } from "@client/storyFormSchema"; | ||||||
|  | 	import { | ||||||
|  | 		FormChapter, | ||||||
|  | 		FormStory, | ||||||
|  | 		defaultChapter, | ||||||
|  | 	} from "@client/types/form/story"; | ||||||
|  | 	import { | ||||||
|  | 		autoEdit, | ||||||
|  | 		autoSave, | ||||||
|  | 		debouncedAutoEdit, | ||||||
|  | 		debouncedAutoSave, | ||||||
|  | 	} from "@client/utils"; | ||||||
|  | 
 | ||||||
|  | 	import findUser from "~/components/findUser.vue"; | ||||||
|  | 
 | ||||||
|  | 	import singleChapter from "./singleChapter.vue"; | ||||||
|  | 	import icon from "~/components/icon.vue"; | ||||||
|  | 
 | ||||||
|  | 	const props = defineProps<{ | ||||||
|  | 		data: FormStory; | ||||||
|  | 		canDraft?: boolean; | ||||||
|  | 		endpoint: string; | ||||||
|  | 		endpointMethod: "put" | "post"; | ||||||
|  | 		submitText?: string; | ||||||
|  | 	}>(); | ||||||
|  | 	let drag = false; | ||||||
|  | 	let acData = ref(props.data); | ||||||
|  | 	const expandos = ref<string[]>([]); | ||||||
|  | 
 | ||||||
|  | 	function logSubmit(values, actions) { | ||||||
|  | 		console.debug("VALUE"); | ||||||
|  | 		console.debug(values); | ||||||
|  | 		console.debug(actions); | ||||||
|  | 	} | ||||||
|  | 	const otherBtnInvoked = ref<boolean>(false); | ||||||
|  | 	async function onSubmit(values, actions) { | ||||||
|  | 		logSubmit(values, actions); | ||||||
|  | 		if (props.canDraft) { | ||||||
|  | 			if (otherBtnInvoked.value) { | ||||||
|  | 				otherBtnInvoked.value = false; | ||||||
|  | 				await autoSave(values); | ||||||
|  | 			} else { | ||||||
|  | 				await useApiFetch(`/story/new`, { | ||||||
|  | 					method: "post", | ||||||
|  | 					body: values, | ||||||
|  | 				}); | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			await autoEdit(values, props.endpoint, props.endpointMethod); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	function inval({ values, errors, results }) { | ||||||
|  | 		logSubmit(values, undefined); | ||||||
|  | 	} | ||||||
|  | 	const { values, setFieldValue, handleSubmit } = useForm({ | ||||||
|  | 		keepValuesOnUnmount: true, | ||||||
|  | 		validationSchema: storySchema, | ||||||
|  | 		initialValues: props.data, | ||||||
|  | 	}); | ||||||
|  | 	const subCb = handleSubmit(onSubmit); | ||||||
|  | </script> | ||||||
|  | <template> | ||||||
|  | 	<!-- <vee-form | ||||||
|  | 		:keep-values="true" | ||||||
|  | 		v-slot="{ values, setFieldValue }" | ||||||
|  | 		:validation-schema="storySchema" | ||||||
|  | 		:initial-values="data" | ||||||
|  | 		@submit="onSubmit" | ||||||
|  | 		@invalid-submit="inval" | ||||||
|  | 	> --> | ||||||
|  | 	<form | ||||||
|  | 		@submit="subCb" | ||||||
|  | 		@change=" | ||||||
|  | 			() => | ||||||
|  | 				canDraft | ||||||
|  | 					? debouncedAutoSave(values) | ||||||
|  | 					: debouncedAutoEdit(values, endpoint, endpointMethod) | ||||||
|  | 		" | ||||||
|  | 	> | ||||||
|  | 		<!-- <a-form v-bind:model="acData"> --> | ||||||
|  | 		<Field name="title" v-slot="{ value, field, errorMessage }"> | ||||||
|  | 			<a-form-item | ||||||
|  | 				label="Title" | ||||||
|  | 				:help="errorMessage" | ||||||
|  | 				:validate-status="!!errorMessage ? 'error' : ''" | ||||||
|  | 			> | ||||||
|  | 				<a-input v-bind="field" :value="value" /> | ||||||
|  | 			</a-form-item> | ||||||
|  | 		</Field> | ||||||
|  | 		<a-form-item label="Co-author (optional)"> | ||||||
|  | 			<find-user :initial-option="null" fieldName="coAuthor" :multi="false" /> | ||||||
|  | 		</a-form-item> | ||||||
|  | 		<Field | ||||||
|  | 			:unchecked-value="false" | ||||||
|  | 			:value="true" | ||||||
|  | 			type="checkbox" | ||||||
|  | 			name="completed" | ||||||
|  | 			v-slot="{ value, field, errorMessage }" | ||||||
|  | 		> | ||||||
|  | 			<a-checkbox v-bind="field"> Complete </a-checkbox> | ||||||
|  | 		</Field> | ||||||
|  | 		<a-divider /> | ||||||
|  | 		<!-- <test1/> --> | ||||||
|  | 		<field-array name="chapters" v-slot="{ fields, push, remove, move }"> | ||||||
|  | 			<draggable | ||||||
|  | 				:component-data="{ type: 'transtion-group' }" | ||||||
|  | 				@start="drag = true" | ||||||
|  | 				@end="drag = false" | ||||||
|  | 				v-model="values.chapters" | ||||||
|  | 				tag="div" | ||||||
|  | 				item-key="uuidKey" | ||||||
|  | 				@change=" | ||||||
|  | 					(e) => { | ||||||
|  | 						if (e.moved) { | ||||||
|  | 							// log.debug(e.moved); | ||||||
|  | 							move(e.moved.oldIndex, e.moved.newIndex); | ||||||
|  | 							acData.chapters = lmove( | ||||||
|  | 								acData.chapters, | ||||||
|  | 								e.moved.oldIndex, | ||||||
|  | 								e.moved.newIndex, | ||||||
|  | 							); | ||||||
|  | 							// log.debug(toRaw(acData.chapters.map((a) => toRaw(a)))); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				" | ||||||
|  | 			> | ||||||
|  | 				<template #item="{ element, index }"> | ||||||
|  | 					<a-collapse v-model:active-key="expandos" collapsible="icon"> | ||||||
|  | 						<a-collapse-panel :key="`${element.uuidKey}`"> | ||||||
|  | 							<template #header> | ||||||
|  | 								{{ values.chapters[index]?.chapterTitle || "Untitled" }} | ||||||
|  | 								<a-button | ||||||
|  | 									@click=" | ||||||
|  | 										(e) => { | ||||||
|  | 											let localFields = toRaw(fields); | ||||||
|  | 											// log.debug(`${index} | ${element.index}`); | ||||||
|  | 											// log.debug('fields->', localFields); | ||||||
|  | 											acData.chapters.splice(index, 1); | ||||||
|  | 											remove(index); | ||||||
|  | 											// todo renumber | ||||||
|  | 											// renumber() | ||||||
|  | 										} | ||||||
|  | 									" | ||||||
|  | 								> | ||||||
|  | 									<icon istyle="regular" name="trash" /> | ||||||
|  | 								</a-button> | ||||||
|  | 							</template> | ||||||
|  | 							<single-chapter :data="element" :name="`chapters[${index}]`" /> | ||||||
|  | 						</a-collapse-panel> | ||||||
|  | 					</a-collapse> | ||||||
|  | 				</template> | ||||||
|  | 				<template #footer> | ||||||
|  | 					<a-button | ||||||
|  | 						@click=" | ||||||
|  | 							(e) => { | ||||||
|  | 								if (!Array.isArray(values.chapters)) { | ||||||
|  | 									// noinspection TypeScriptValidateTypes | ||||||
|  | 									setFieldValue('chapters', []); | ||||||
|  | 								} | ||||||
|  | 								const chaps = [...toRaw(values.chapters)]; | ||||||
|  | 								let lastIndex = chaps.length - 1; | ||||||
|  | 								if (lastIndex < 0) lastIndex = 0; | ||||||
|  | 								let lastChapter = chaps[lastIndex]; | ||||||
|  | 								// log.debug('chaptrs->', chaps); | ||||||
|  | 								// log.debug('lastIndex->', lastIndex, lastChapter); | ||||||
|  | 								let newChapter = Object.assign({}, defaultChapter, { | ||||||
|  | 									summary: lastChapter?.summary || '', | ||||||
|  | 									index: (lastChapter?.index || 0) + 1, | ||||||
|  | 									bands: lastChapter?.bands || [], | ||||||
|  | 									characters: lastChapter?.characters || [], | ||||||
|  | 									relationships: lastChapter?.relationships || [], | ||||||
|  | 									uuidKey: v4(), | ||||||
|  | 									genre: lastChapter?.genre || [], | ||||||
|  | 								}); | ||||||
|  | 								// log.debug('nc->', newChapter); | ||||||
|  | 								push(newChapter); | ||||||
|  | 								acData.chapters.push(newChapter); | ||||||
|  | 							} | ||||||
|  | 						" | ||||||
|  | 					> | ||||||
|  | 						Add chapter | ||||||
|  | 					</a-button> | ||||||
|  | 				</template> | ||||||
|  | 			</draggable> | ||||||
|  | 		</field-array> | ||||||
|  | 		<a-button type="primary" html-type="submit">{{ | ||||||
|  | 			submitText || "Post" | ||||||
|  | 		}}</a-button> | ||||||
|  | 		<a-button | ||||||
|  | 			html-type="submit" | ||||||
|  | 			v-if="canDraft" | ||||||
|  | 			@click="() => (otherBtnInvoked = true)" | ||||||
|  | 		> | ||||||
|  | 			Save for Later | ||||||
|  | 		</a-button> | ||||||
|  | 	</form> | ||||||
|  | 	<!-- </vee-form> --> | ||||||
|  | </template> | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user