Improve event card UI

master
John Montagu, the 4th Earl of Sandvich 2024-11-29 00:02:12 -08:00
parent e1c6a7bb14
commit ebbd969afd
Signed by: sandvich
GPG Key ID: 9A39BE37E602B22D
2 changed files with 73 additions and 15 deletions

View File

@ -1,15 +1,19 @@
<script setup lang="ts"> <script setup lang="ts">
import type { EventSchema } from "@/client"; import type { EventSchema, EventWithPlayerSchema } from "@/client";
import { useRosterStore } from "@/stores/roster";
import { useTeamsStore } from "@/stores/teams"; import { useTeamsStore } from "@/stores/teams";
import { useTeamsEventsStore } from "@/stores/teams/events";
import moment from "moment"; import moment from "moment";
import { computed } from "vue"; import { computed } from "vue";
const teamsStore = useTeamsStore(); const teamsStore = useTeamsStore();
const rosterStore = useRosterStore();
const teamEventsStore = useTeamsEventsStore();
const date = computed(() => moment(props.event.startTime)); const date = computed(() => moment(props.event.event.startTime));
const formattedTime = computed(() => { const formattedTime = computed(() => {
const team = teamsStore.teams[props.event.teamId]; const team = teamsStore.teams[props.event.event.teamId];
const offsetDate = date.value.clone().tz(team.tzTimezone); const offsetDate = date.value.clone().tz(team.tzTimezone);
return `${date.value.format("LT")} (${offsetDate.format("LT z")})`; return `${date.value.format("LT")} (${offsetDate.format("LT z")})`;
}); });
@ -23,8 +27,24 @@ const shortMonth = computed(() => {
}); });
const props = defineProps<{ const props = defineProps<{
event: EventSchema; event: EventWithPlayerSchema;
}>(); }>();
function attend() {
teamEventsStore.attendEvent(props.event.event.id);
}
function unattend() {
teamEventsStore.unattendEvent(props.event.event.id);
}
function attendOrUnattend() {
if (props.event.playerEvent?.hasConfirmed) {
unattend();
} else {
attend();
}
}
</script> </script>
<template> <template>
@ -39,7 +59,7 @@ const props = defineProps<{
</div> </div>
<div class="details"> <div class="details">
<div> <div>
<h3>{{ event.name }}</h3> <h3>{{ event.event.name }}</h3>
<div> <div>
<span> <span>
<i class="bi bi-clock-fill margin" /> <i class="bi bi-clock-fill margin" />
@ -48,11 +68,33 @@ const props = defineProps<{
</div> </div>
</div> </div>
<div class="subdetails"> <div class="subdetails">
<span v-if="event.description">{{ event.description }}</span> <span v-if="event.event.description">{{ event.event.description }}</span>
<em v-else class="subtext">No description provided.</em> <em v-else class="subtext">No description provided.</em>
<button class="class-info"> </div>
<i class="tf2class tf2-PocketScout margin" /> <div class="button-group">
Accept as Pocket Scout <button
@click="attendOrUnattend()"
v-if="event.playerEvent"
:class="{
'class-info': true,
'confirmed': event.playerEvent.hasConfirmed,
}"
>
<template v-if="!event.playerEvent.hasConfirmed">
<i class="bi bi-check2" />
Confirm
</template>
<template v-else>
<i class="bi bi-check2-all" />
Confirmed
</template>
<span v-if="event.playerEvent.role">
as {{ rosterStore.roleNames[event.playerEvent.role.role] }}
</span>
</button>
<button @click="attend" v-else>
<i class="bi bi-check2" />
Attend
</button> </button>
</div> </div>
</div> </div>
@ -62,11 +104,8 @@ const props = defineProps<{
<style scoped> <style scoped>
.event-card { .event-card {
display: flex; display: flex;
padding: 1rem;
align-items: center; align-items: center;
/*background-color: white;*/ /*background-color: white;*/
border: 1px solid var(--text);
border-radius: 8px;
align-items: stretch; align-items: stretch;
} }
@ -77,6 +116,10 @@ const props = defineProps<{
justify-content: center; justify-content: center;
line-height: 1; line-height: 1;
flex-basis: 4rem; flex-basis: 4rem;
padding: 1rem;
background-color: var(--text);
color: var(--base);
border-radius: 8px 0 0 8px;
} }
.date .month { .date .month {
@ -91,8 +134,12 @@ const props = defineProps<{
} }
.details { .details {
padding: 1rem;
border: 1px solid var(--text);
border-radius: 0 8px 8px 0;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%;
gap: 0.5rem; gap: 0.5rem;
} }
@ -110,4 +157,15 @@ const props = defineProps<{
font-size: 1.2rem; font-size: 1.2rem;
vertical-align: middle; vertical-align: middle;
} }
.button-group {
display: flex;
gap: 0.5rem;
justify-content: flex-end;
}
button.confirmed {
background-color: var(--text);
color: var(--base);
}
</style> </style>

View File

@ -1,15 +1,15 @@
<script setup lang="ts"> <script setup lang="ts">
import type { EventSchema } from "@/client"; import type { EventWithPlayerSchema } from "@/client";
import EventCard from "./EventCard.vue"; import EventCard from "./EventCard.vue";
const props = defineProps<{ const props = defineProps<{
events: EventSchema[]; events: EventWithPlayerSchema[];
}>(); }>();
</script> </script>
<template> <template>
<div class="events-list" v-if="props.events?.length > 0"> <div class="events-list" v-if="props.events?.length > 0">
<EventCard v-for="event in props.events" :key="event.id" :event="event" /> <EventCard v-for="event in props.events" :key="event.event.id" :event="event" />
</div> </div>
<div class="events-list" v-else> <div class="events-list" v-else>
<em class="subtext">No upcoming events.</em> <em class="subtext">No upcoming events.</em>