4
0
Fork 0
mini-shater/composables/modal.ts

145 lines
4.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// useModalState.ts
import { useRuntimeConfig } from '#app';
type ModalDataType = {
phone?: string;
name?: string;
email?: string;
policy: boolean;
};
// Состояние открытия модального окна
const isModalOpen = ref(false);
// Реактивные данные формы
const modal_data = reactive<ModalDataType>({
email: undefined,
phone: undefined,
name: undefined,
policy: false,
});
// Реактивные данные состояния формы
const modal_form = reactive({
disabled: true,
errors: [] as string[],
});
// Реактивные данные состояния модального окна
const modal_state = reactive({
show_form: true,
show_status: null as null | 'loading' | 'success' | 'error',
});
export function useModalState(initialState = false) {
// Функция для открытия модального окна
const openModal = () => {
isModalOpen.value = true;
};
// Функция для закрытия модального окна
const closeModal = () => {
resetModalData();
isModalOpen.value = false;
};
// Функция для переключения состояния модального окна
const toggleModal = () => {
resetModalData();
isModalOpen.value = !isModalOpen.value;
};
// Функция для сброса данных формы
const resetModalData = () => {
modal_data.email = undefined;
modal_data.phone = undefined;
modal_data.name = undefined;
modal_data.policy = false;
modal_state.show_form = true;
modal_state.show_status = null;
modal_form.disabled = true;
modal_form.errors = [];
};
// Функция для открытия формы
const openForm = () => {
modal_state.show_form = !modal_state.show_form;
goal('open_form');
};
// Валидация ввода
const validateInput = (evt: KeyboardEvent) => {
const valid_symbols = /[a-zA-Z0-9\+(\\)\ @\.]/;
if (!valid_symbols.test(evt.key)) {
evt.preventDefault();
}
};
// Валидация данных формы
const validate = () => {
const phone_regexp = /^\+?[\d\s-()]{0,14}\d{11}$/;
const email_regex = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/;
modal_form.disabled = true;
if (
((modal_data.phone && phone_regexp.test(modal_data.phone)) ||
(modal_data.email && email_regex.test(modal_data.email))) &&
modal_data.policy === true
) {
modal_form.disabled = false;
}
};
// Отправка данных на сервер
const submit = async () => {
goal('submit_form', modal_data);
modal_state.show_status = 'loading';
const config = useRuntimeConfig()
const apiBase = config.public.apiBase
const prefix = config.public.apiPrefix
try {
const res = await fetch(`${apiBase}/gb/custom_request/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: modal_data.name || `ref from site ${new Date()}`,
phone: modal_data.phone,
email: modal_data.email,
privacy: true,
fence_info: 'Запрос скамейки'
}),
});
modal_state.show_status = 'success';
} catch (error) {
modal_state.show_status = 'error';
}
};
// Наблюдение за изменениями данных формы
watch(modal_data, validate);
// Наблюдение за состоянием модального окна
watch(isModalOpen, (newValue) => {
console.log(isModalOpen)
if (newValue) {
document.body.classList.add('modal-opened');
} else {
document.body.classList.remove('modal-opened');
}
});
return {
isModalOpen,
modal_data,
modal_form,
modal_state,
openModal,
closeModal,
toggleModal,
openForm,
validateInput,
validate,
submit,
};
}