mirror of
https://github.com/solidtime-io/solidtime.git
synced 2026-08-17 04:32:15 +01:00
move TimezonMismatchModal to ui package
This commit is contained in:
@@ -1,19 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import SecondaryButton from '@/packages/ui/src/Buttons/SecondaryButton.vue';
|
import { ref } from 'vue';
|
||||||
import DialogModal from '@/packages/ui/src/DialogModal.vue';
|
|
||||||
import PrimaryButton from '@/packages/ui/src/Buttons/PrimaryButton.vue';
|
|
||||||
import { onMounted, ref } from 'vue';
|
|
||||||
import { getUserTimezone } from '@/packages/ui/src/utils/settings';
|
|
||||||
import { getDayJsInstance } from '@/packages/ui/src/utils/time';
|
|
||||||
import { useForm, usePage } from '@inertiajs/vue3';
|
import { useForm, usePage } from '@inertiajs/vue3';
|
||||||
import type { User } from '@/types/models';
|
import type { User } from '@/types/models';
|
||||||
import { useSessionStorage } from '@vueuse/core';
|
import TimezoneMismatchModal from '@/packages/ui/src/TimezoneMismatchModal.vue';
|
||||||
|
|
||||||
const show = defineModel('show', { default: false });
|
const show = defineModel('show', { default: false });
|
||||||
const saving = defineModel('saving', { default: false });
|
const saving = ref(false);
|
||||||
|
|
||||||
const timezone = ref('');
|
|
||||||
const userTimezone = ref('');
|
|
||||||
|
|
||||||
const page = usePage<{
|
const page = usePage<{
|
||||||
auth: {
|
auth: {
|
||||||
@@ -21,27 +13,11 @@ const page = usePage<{
|
|||||||
};
|
};
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const hideTimezoneMismatchModal = useSessionStorage<boolean>('hide-timezone-mismatch-modal', false);
|
function handleUpdate(timezone: string) {
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
timezone.value = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
||||||
userTimezone.value = getUserTimezone();
|
|
||||||
|
|
||||||
const now = getDayJsInstance()();
|
|
||||||
|
|
||||||
if (
|
|
||||||
now.tz(timezone.value).format() !== now.tz(userTimezone.value).format() &&
|
|
||||||
!hideTimezoneMismatchModal.value
|
|
||||||
) {
|
|
||||||
show.value = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function submit() {
|
|
||||||
saving.value = true;
|
saving.value = true;
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
_method: 'PUT',
|
_method: 'PUT',
|
||||||
timezone: timezone.value,
|
timezone: timezone,
|
||||||
name: page.props.auth.user.name,
|
name: page.props.auth.user.name,
|
||||||
email: page.props.auth.user.email,
|
email: page.props.auth.user.email,
|
||||||
week_start: page.props.auth.user.week_start,
|
week_start: page.props.auth.user.week_start,
|
||||||
@@ -55,53 +31,15 @@ function submit() {
|
|||||||
show.value = false;
|
show.value = false;
|
||||||
location.reload();
|
location.reload();
|
||||||
},
|
},
|
||||||
|
onError: () => {
|
||||||
|
saving.value = false;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancel() {
|
|
||||||
show.value = false;
|
|
||||||
hideTimezoneMismatchModal.value = true;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<DialogModal closeable :show="show" @close="show = false">
|
<TimezoneMismatchModal v-model:show="show" :saving="saving" @update="handleUpdate" />
|
||||||
<template #title>
|
|
||||||
<div class="flex justify-center">
|
|
||||||
<span> Timezone mismatch detected </span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #content>
|
|
||||||
<div class="flex items-center space-x-4">
|
|
||||||
<div class="col-span-6 sm:col-span-4 flex-1 space-y-2">
|
|
||||||
<p>
|
|
||||||
The timezone of your device does not match the timezone in your user
|
|
||||||
settings. <br />
|
|
||||||
<strong
|
|
||||||
>We highly recommend that you update your timezone settings to your
|
|
||||||
current timezone.</strong
|
|
||||||
>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
Want to change your timezone setting from
|
|
||||||
<strong>{{ userTimezone }}</strong> to <strong>{{ timezone }}</strong
|
|
||||||
>.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #footer>
|
|
||||||
<SecondaryButton @click="cancel"> Cancel</SecondaryButton>
|
|
||||||
<PrimaryButton
|
|
||||||
class="ms-3"
|
|
||||||
:class="{ 'opacity-25': saving }"
|
|
||||||
:disabled="saving"
|
|
||||||
@click="submit()">
|
|
||||||
Update timezone
|
|
||||||
</PrimaryButton>
|
|
||||||
</template>
|
|
||||||
</DialogModal>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
|||||||
109
resources/js/packages/ui/src/TimezoneMismatchModal.vue
Normal file
109
resources/js/packages/ui/src/TimezoneMismatchModal.vue
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import SecondaryButton from './Buttons/SecondaryButton.vue';
|
||||||
|
import DialogModal from './DialogModal.vue';
|
||||||
|
import PrimaryButton from './Buttons/PrimaryButton.vue';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { getUserTimezone } from './utils/settings';
|
||||||
|
import { getDayJsInstance } from './utils/time';
|
||||||
|
import { useSessionStorage } from '@vueuse/core';
|
||||||
|
|
||||||
|
const show = defineModel('show', { default: false });
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
update: [timezone: string];
|
||||||
|
cancel: [];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
defineProps<{
|
||||||
|
saving?: boolean;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const timezone = ref('');
|
||||||
|
const userTimezone = ref('');
|
||||||
|
const shouldShow = ref(false);
|
||||||
|
|
||||||
|
const hideTimezoneMismatchModal = useSessionStorage<boolean>('hide-timezone-mismatch-modal', false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if timezone mismatch exists and should be shown
|
||||||
|
*/
|
||||||
|
function checkTimezoneMismatch(): boolean {
|
||||||
|
timezone.value = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||||
|
userTimezone.value = getUserTimezone();
|
||||||
|
|
||||||
|
const now = getDayJsInstance()();
|
||||||
|
|
||||||
|
const hasMismatch =
|
||||||
|
now.tz(timezone.value).format() !== now.tz(userTimezone.value).format() &&
|
||||||
|
!hideTimezoneMismatchModal.value;
|
||||||
|
|
||||||
|
shouldShow.value = hasMismatch;
|
||||||
|
return hasMismatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
checkTimezoneMismatch();
|
||||||
|
if (shouldShow.value) {
|
||||||
|
show.value = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function submit() {
|
||||||
|
emit('update', timezone.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cancel() {
|
||||||
|
show.value = false;
|
||||||
|
hideTimezoneMismatchModal.value = true;
|
||||||
|
emit('cancel');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expose methods for parent component
|
||||||
|
defineExpose({
|
||||||
|
checkTimezoneMismatch,
|
||||||
|
currentTimezone: timezone,
|
||||||
|
userTimezone,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<DialogModal closeable :show="show && shouldShow" @close="cancel">
|
||||||
|
<template #title>
|
||||||
|
<div class="flex justify-center">
|
||||||
|
<span> Timezone mismatch detected </span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #content>
|
||||||
|
<div class="flex items-center space-x-4">
|
||||||
|
<div class="col-span-6 sm:col-span-4 flex-1 space-y-2">
|
||||||
|
<p>
|
||||||
|
The timezone of your device does not match the timezone in your user
|
||||||
|
settings. <br />
|
||||||
|
<strong
|
||||||
|
>We highly recommend that you update your timezone settings to your
|
||||||
|
current timezone.</strong
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Want to change your timezone setting from
|
||||||
|
<strong>{{ userTimezone }}</strong> to <strong>{{ timezone }}</strong
|
||||||
|
>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #footer>
|
||||||
|
<SecondaryButton @click="cancel"> Cancel</SecondaryButton>
|
||||||
|
<PrimaryButton
|
||||||
|
class="ms-3"
|
||||||
|
:class="{ 'opacity-25': saving }"
|
||||||
|
:disabled="saving"
|
||||||
|
@click="submit()">
|
||||||
|
Update timezone
|
||||||
|
</PrimaryButton>
|
||||||
|
</template>
|
||||||
|
</DialogModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -38,6 +38,7 @@ import FullCalendarEventContent from './FullCalendar/FullCalendarEventContent.vu
|
|||||||
import FullCalendarDayHeader from './FullCalendar/FullCalendarDayHeader.vue';
|
import FullCalendarDayHeader from './FullCalendar/FullCalendarDayHeader.vue';
|
||||||
import TimeEntryCalendar from './FullCalendar/TimeEntryCalendar.vue';
|
import TimeEntryCalendar from './FullCalendar/TimeEntryCalendar.vue';
|
||||||
import DateRangePicker from './Input/DateRangePicker.vue';
|
import DateRangePicker from './Input/DateRangePicker.vue';
|
||||||
|
import TimezoneMismatchModal from './TimezoneMismatchModal.vue';
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './tooltip/index';
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './tooltip/index';
|
||||||
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './accordion/index';
|
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './accordion/index';
|
||||||
import { Popover, PopoverContent, PopoverTrigger, PopoverAnchor } from './popover/index';
|
import { Popover, PopoverContent, PopoverTrigger, PopoverAnchor } from './popover/index';
|
||||||
@@ -74,6 +75,7 @@ export {
|
|||||||
FullCalendarDayHeader,
|
FullCalendarDayHeader,
|
||||||
TimeEntryCalendar,
|
TimeEntryCalendar,
|
||||||
DateRangePicker,
|
DateRangePicker,
|
||||||
|
TimezoneMismatchModal,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
|
|||||||
Reference in New Issue
Block a user