109 lines
2.7 KiB
Vue
109 lines
2.7 KiB
Vue
<script setup lang="ts">
|
|
// TODO: buttons should take in account opacity
|
|
|
|
import Background from "./Background.vue";
|
|
import Buttons from "./Buttons.vue";
|
|
import ButtonSelector from "~/components/Common/ButtonSelector.vue";
|
|
|
|
const store = useContactStore();
|
|
const confirmationModal = useConfirmationModal();
|
|
|
|
const ACTIONS = {
|
|
github: ["Open", "Github profile", "https://github.com/pihkaal"],
|
|
email: ["Copy", "Email", "hello@pihkaal.me"],
|
|
website: ["Copy", "Website link", "https://pihkaal.me"],
|
|
cv: ["Open", "CV", "https://pihkaal.me/cv"],
|
|
} as const satisfies Record<
|
|
string,
|
|
[action: "Copy" | "Open", verb: string, content: string]
|
|
>;
|
|
|
|
const { selected, selectorPosition } = useButtonNavigation({
|
|
buttons: {
|
|
github: [26, 27, 202, 42],
|
|
email: [26, 59, 202, 42],
|
|
website: [26, 91, 202, 42],
|
|
cv: [26, 123, 202, 42],
|
|
},
|
|
navigation: {
|
|
github: {
|
|
down: "email",
|
|
},
|
|
email: {
|
|
up: "github",
|
|
down: "website",
|
|
},
|
|
website: {
|
|
up: "email",
|
|
down: "cv",
|
|
},
|
|
cv: {
|
|
up: "website",
|
|
},
|
|
},
|
|
initialButton: "github",
|
|
onButtonClick: (button) => {
|
|
actionateButton(button);
|
|
},
|
|
disabled: computed(() => store.isIntro || store.isOutro),
|
|
});
|
|
|
|
const actionateButton = async (button: (typeof selected)["value"]) => {
|
|
const [action, verb, content] = ACTIONS[button];
|
|
if (action === "Copy") {
|
|
try {
|
|
await navigator.clipboard.writeText(content);
|
|
store.pushNotification(`${verb} copied to clipboard`);
|
|
} catch (error) {
|
|
console.error("Failed to copy to clipboard:", error);
|
|
}
|
|
} else {
|
|
const url = content.replace(/^https?:\/\//, "");
|
|
confirmationModal.open({
|
|
text: `Open ${url}?`,
|
|
onConfirm: async () => {
|
|
store.pushNotification(`${verb} opened`);
|
|
await sleep(100);
|
|
await navigateTo(content, { open: { target: "_blank " } });
|
|
},
|
|
});
|
|
}
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<Background />
|
|
|
|
<Buttons />
|
|
<ButtonSelector
|
|
:rect="selectorPosition"
|
|
:opacity="
|
|
store.isIntro ? store.intro.stage3Opacity : store.outro.stage1Opacity
|
|
"
|
|
/>
|
|
|
|
<CommonBars
|
|
title="Choose a Chat Room to join."
|
|
:opacity="
|
|
store.isIntro ? store.intro.stage3Opacity : store.outro.stage2Opacity
|
|
"
|
|
:y-offset="store.isIntro ? store.intro.barOffsetY : 0"
|
|
/>
|
|
<CommonConfirmationModal />
|
|
<CommonButtons
|
|
:y-offset="
|
|
store.isIntro ? store.intro.barOffsetY : confirmationModal.buttonsYOffset
|
|
"
|
|
:opacity="
|
|
store.isIntro
|
|
? store.intro.stage3Opacity
|
|
: store.isOutro
|
|
? store.outro.stage2Opacity
|
|
: 1
|
|
"
|
|
b-label="Quit"
|
|
:a-label="ACTIONS[selected][0]"
|
|
@activate-b="store.animateOutro()"
|
|
/>
|
|
</template>
|