-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(orgs viewable, better structuring, improved components, etc.)
- Loading branch information
Showing
19 changed files
with
1,237 additions
and
540 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
<script setup lang="ts"> | ||
import { type Ref, ref } from 'vue'; | ||
import Organ from '../models/Organ'; | ||
import PopDropDown from './PopDropDown.vue'; | ||
const props = defineProps<{ | ||
/** | ||
* The organ to display in the banner. | ||
*/ | ||
organ: Organ|null; | ||
/** | ||
* The name to display in the banner. | ||
*/ | ||
name?: string; | ||
/** | ||
* The origin date of the organ. | ||
*/ | ||
from?: Date; | ||
/** | ||
* The end date of the organ. | ||
*/ | ||
to?: Date; | ||
/** | ||
* The age of the organ. | ||
*/ | ||
age?: number; | ||
/** | ||
* The social media links to display in the banner. | ||
*/ | ||
socials?: {[name: string]: string[]}; | ||
/** | ||
* Whether to show social media links. | ||
*/ | ||
showSocials?: boolean; | ||
/** | ||
* Whether to show the banner in a small size. | ||
*/ | ||
small?: boolean; | ||
/** | ||
* Whether to show the banner in an extra small size. | ||
*/ | ||
extraSmall?: boolean; | ||
}>(); | ||
const icons: {[name: string]: { icon: string, title: string, }} = { | ||
phone: { icon: 'fa-solid fa-phone', title: 'Phone', }, | ||
email: { icon: 'fa-solid fa-envelope', title: 'Email', }, | ||
facebook: { icon: 'fa-brands fa-facebook', title: 'Facebook', }, | ||
instagram: { icon: 'fa-brands fa-instagram', title: 'Instagram', }, | ||
twitter: { icon: 'fa-brands fa-twitter', title: 'Twitter', }, | ||
telegram: { icon: 'fa-brands fa-telegram', title: 'Telegram', }, | ||
linkedin: { icon: 'fa-brands fa-linkedin', title: 'LinkedIn', }, | ||
xing: { icon: 'fa-brands fa-xing', title: 'Xing', }, | ||
youtube: { icon: 'fa-brands fa-youtube', title: 'YouTube', }, | ||
tiktok: { icon: 'fa-brands fa-tiktok', title: 'TikTok', }, | ||
website: { icon: 'fa-solid fa-globe', title: 'Website', }, | ||
other: { icon: 'fa-solid fa-hashtag', title: 'Other', }, | ||
}; | ||
const copyLink = (link: string) => { | ||
navigator.clipboard.writeText(link); | ||
}; | ||
const socialsShown: Ref<{[name: string]: boolean}> = ref({}); | ||
if (props.socials) { | ||
Object.keys(props.socials).forEach((name) => { | ||
socialsShown.value[name] = false; | ||
}); | ||
} | ||
</script> | ||
|
||
<template> | ||
<div | ||
:class="[ | ||
'banner', | ||
props.small||props.extraSmall ? 'small' : '', | ||
props.extraSmall ? 'extra-small' : '', | ||
]" | ||
> | ||
<div | ||
v-if="props.extraSmall" | ||
class="banner-image" | ||
> | ||
<img | ||
:src="props.organ ? props.organ.pic.src() : '/john-doe.png'" | ||
:alt="props.name ? props.name : 'Organ image'" | ||
/> | ||
</div> | ||
<div | ||
class="banner-facts" | ||
v-if="props.organ" | ||
> | ||
<h1 v-if="!(props.small||props.extraSmall)"> | ||
{{ props.name }} | ||
</h1> | ||
<h3 v-else> | ||
{{ props.name }} | ||
</h3> | ||
<div class="banner-birth-death"> | ||
<span v-if="props.from"> | ||
<font-awesome-icon icon="fa-solid fa-baby" /> | ||
{{ props.from.toLocaleDateString('en-us', { weekday:undefined, year:"numeric", month:"short", day:"numeric"}) }} | ||
</span> | ||
<span v-if="props.to"> | ||
<font-awesome-icon icon="fa-solid fa-skull" /> | ||
{{ props.to.toLocaleDateString('en-us', { weekday:undefined, year:"numeric", month:"short", day:"numeric"}) }} | ||
</span> | ||
<span v-if="props.age"> | ||
(Age: {{ props.age }}) | ||
</span> | ||
</div> | ||
<div v-if="props.showSocials && props.socials" class="banner-socials"> | ||
<template | ||
v-for="name in Object.keys(props.socials)" | ||
:key="name" | ||
> | ||
<font-awesome-icon | ||
:icon="icons[name].icon" | ||
:title="icons[name].title" | ||
:style="{ color: socialsShown[name] ? 'var(--color-text-focus)' : 'var(--color-text)' }" | ||
@click="() => { | ||
Object.keys(socialsShown) | ||
.filter(key => key !== name) | ||
.forEach((key) => { | ||
socialsShown[key] = false; | ||
}); | ||
socialsShown[name] = !socialsShown[name]; | ||
}" | ||
/> | ||
<PopDropDown | ||
:shown="socialsShown[name]" | ||
> | ||
<div | ||
v-for="link in props.socials[name]" | ||
:key="link" | ||
class="banner-socials-link" | ||
> | ||
<font-awesome-icon | ||
icon="fa-solid fa-copy" | ||
title="Copy link to clipboard" | ||
@click="() => copyLink(link)" | ||
/> | ||
<a | ||
:href="link" | ||
_target="blank" | ||
>{{ link }}</a> | ||
</div> | ||
</PopDropDown> | ||
</template> | ||
</div> | ||
</div> | ||
<div | ||
class="banner-facts" | ||
v-else | ||
> | ||
<h1 v-if="!props.small"> | ||
<i>Organ doesn't exist (anymore) ...</i> | ||
</h1> | ||
<h3 v-else> | ||
<i>Organ doesn't exist (anymore) ...</i> | ||
</h3> | ||
</div> | ||
<div | ||
v-if="!props.extraSmall" | ||
class="banner-image" | ||
> | ||
<img | ||
:src="props.organ ? props.organ.pic.src() : '/john-doe.png'" | ||
:alt="props.name ? props.name : 'Organ image'" | ||
/> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<style scoped> | ||
.banner { | ||
display: flex; | ||
justify-content: stretch; | ||
align-items: center; | ||
gap: 1em; | ||
border-bottom: 2px solid var(--color-border); | ||
padding: 1.5em; | ||
} | ||
.banner.small { | ||
padding: 1em; | ||
} | ||
.banner.extra-small { | ||
border: none; | ||
} | ||
.banner-facts { | ||
flex-grow: 1; | ||
flex-basis: 0; | ||
} | ||
.banner-image img { | ||
width: auto; | ||
height: 12em; | ||
border-radius: 5px; | ||
} | ||
.small .banner-image img { | ||
height: 4em; | ||
} | ||
.extra-small .banner-image img { | ||
height: 2em; | ||
} | ||
.banner-facts h1 { | ||
font-size: 2em; | ||
} | ||
.banner-birth-death { | ||
display: flex; | ||
justify-content: flex-start; | ||
align-items: center; | ||
gap: 1em; | ||
margin-top: .2em; | ||
padding: 0 .5em; | ||
} | ||
.small .banner-birth-death { | ||
padding: 0; | ||
gap: .5em; | ||
} | ||
.extra-small .banner-birth-death { | ||
font-size: .8em; | ||
} | ||
.banner-birth-death span { | ||
display: flex; | ||
justify-content: flex-start; | ||
align-items: center; | ||
gap: .5em; | ||
} | ||
.banner-socials { | ||
display: flex; | ||
justify-content: flex-start; | ||
align-items: center; | ||
gap: .4em; | ||
font-size: 1.1em; | ||
flex-wrap: wrap; | ||
color: var(--color-text); | ||
padding: .5em; | ||
margin-top: .5em; | ||
background-color: var(--color-background-mute); | ||
user-select: none; | ||
} | ||
.banner-socials svg { | ||
cursor: pointer; | ||
transition: color .2s; | ||
} | ||
.banner-socials svg:hover { | ||
color: var(--color-text-focus); | ||
} | ||
.banner-socials-link { | ||
display: flex; | ||
justify-content: flex-start; | ||
align-items: center; | ||
gap: .5em; | ||
padding: .1em; | ||
} | ||
.banner-socials a { | ||
font-size: .9em; | ||
color: var(--color-text); | ||
text-decoration: none; | ||
} | ||
</style> |
Oops, something went wrong.