forked from mns/mini-skamja
145 lines
4.3 KiB
TypeScript
145 lines
4.3 KiB
TypeScript
// 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,
|
||
};
|
||
} |