|
1 | 1 | <script setup lang="ts"> |
2 | | -import { computed, inject } from "vue"; |
| 2 | +import { onClickOutside, useDebounceFn } from "@vueuse/core"; |
| 3 | +import { computed, inject, nextTick, ref, useTemplateRef } from "vue"; |
3 | 4 |
|
4 | 5 | import { ApplicationNamespace, GlobalStatesContextKey } from "@/constants/application.ts"; |
| 6 | +import Configs from "@/lib/configs"; |
5 | 7 | import General from "@/lib/general"; |
| 8 | +import GlobalStateHelpers from "@/lib/global-state-helpers"; |
6 | 9 | import { log } from "@/lib/logging/scopes/log.ts"; |
7 | 10 | import type { ContextGlobalStatesType } from "@/types/application/global-states.type.ts"; |
8 | 11 | import type { AtAGlanceType } from "@/types/ui/at-a-glance.type.ts"; |
9 | 12 |
|
10 | 13 | const globalStates = inject<ContextGlobalStatesType>(GlobalStatesContextKey); |
11 | 14 |
|
| 15 | +const target = useTemplateRef<HTMLDivElement>("target"); |
| 16 | +
|
| 17 | +const editing = ref<keyof AtAGlanceType | undefined>(undefined); |
| 18 | +
|
12 | 19 | const currentGlance = computed((): AtAGlanceType => { |
13 | 20 | const configGlance: { |
14 | 21 | "title" : string | null | undefined; |
@@ -39,24 +46,73 @@ const currentGlance = computed((): AtAGlanceType => { |
39 | 46 | "subtitle": configGlance.subtitle, |
40 | 47 | }; |
41 | 48 | }); |
| 49 | +
|
| 50 | +const handleEdit = useDebounceFn(async (event: Event): Promise<void> => { |
| 51 | + const target = event?.target as HTMLInputElement; |
| 52 | + const value = target?.value; |
| 53 | + const key: keyof AtAGlanceType | undefined = editing.value; |
| 54 | +
|
| 55 | + if (!key || !value || !globalStates) { |
| 56 | + return; |
| 57 | + } |
| 58 | +
|
| 59 | + log.debug(`Setting the global 'At a Glance - ${key}' value to: ${value}`); |
| 60 | + GlobalStateHelpers.change("layout", { |
| 61 | + ...globalStates.layout, |
| 62 | + "atAGlance": { |
| 63 | + ...currentGlance.value, |
| 64 | + [key]: value, |
| 65 | + }, |
| 66 | + }); |
| 67 | +
|
| 68 | + // Global states didn't change yet - Vue batches them |
| 69 | + await nextTick(); |
| 70 | + // Global states have changed, now we can sync the config file |
| 71 | + await Configs.sync(); |
| 72 | +}, 300); |
| 73 | +
|
| 74 | +onClickOutside(target, () => { |
| 75 | + editing.value = undefined; |
| 76 | +}); |
42 | 77 | </script> |
43 | 78 |
|
44 | 79 | <template> |
45 | 80 | <div |
46 | 81 | id="__home-page__header-wrapper" |
| 82 | + ref="target" |
47 | 83 | class="flex flex-col gap-1 pt-4" |
48 | 84 | > |
49 | 85 | <div |
50 | 86 | id="__home-page__header-title" |
51 | | - class="w-fit cursor-pointer border border-transparent rounded-md p-2 text-3xl leading-none transition-[background-color,border-color] hover:border-[theme(colors.white/.3)] hover:bg-[theme(colors.white/.1)]" |
| 87 | + @click="() => editing = 'title'" |
| 88 | + class="relative w-fit cursor-pointer break-all border border-transparent rounded-md p-2 text-3xl leading-none transition-[background-color,border-color] hover:border-[theme(colors.white/.3)] hover:bg-[theme(colors.white/.1)]" |
52 | 89 | > |
53 | | - {{ currentGlance.title }} |
| 90 | + <p id="__home-page__header-title-text"> |
| 91 | + {{ currentGlance.title }} |
| 92 | + </p> |
| 93 | + <input |
| 94 | + v-if="editing === 'title'" |
| 95 | + id="__home-page__header-title-editor-wrapper" |
| 96 | + class="absolute left-0 top-14" |
| 97 | + :value="currentGlance.title" |
| 98 | + @input="handleEdit" |
| 99 | + /> |
54 | 100 | </div> |
55 | 101 | <div |
56 | 102 | id="__home-page__header-subtitle" |
57 | | - class="w-fit cursor-pointer border border-transparent rounded-md p-2 text-lg text-neutral-300 leading-none transition-[background-color,border-color] hover:border-[theme(colors.white/.3)] hover:bg-[theme(colors.white/.1)]" |
| 103 | + @click="() => editing = 'subtitle'" |
| 104 | + class="relative w-fit cursor-pointer break-all border border-transparent rounded-md p-2 text-lg text-neutral-300 leading-none transition-[background-color,border-color] hover:border-[theme(colors.white/.3)] hover:bg-[theme(colors.white/.1)]" |
58 | 105 | > |
59 | | - {{ currentGlance.subtitle }} |
| 106 | + <p id="__home-page__header-subtitle-text"> |
| 107 | + {{ currentGlance.subtitle }} |
| 108 | + </p> |
| 109 | + <input |
| 110 | + v-if="editing === 'subtitle'" |
| 111 | + id="__home-page__header-title-editor-wrapper" |
| 112 | + class="absolute left-0 top-10" |
| 113 | + :value="currentGlance.subtitle" |
| 114 | + @input="handleEdit" |
| 115 | + /> |
60 | 116 | </div> |
61 | 117 | </div> |
62 | 118 | </template> |
0 commit comments