Skip to content

Commit

Permalink
#74 added navigation to speaker details page
Browse files Browse the repository at this point in the history
  • Loading branch information
fcamblor committed Apr 3, 2024
1 parent fca041f commit 481d6ee
Show file tree
Hide file tree
Showing 7 changed files with 145 additions and 2 deletions.
16 changes: 15 additions & 1 deletion mobile/src/components/speaker-card/SpeakerCard.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<!-- TODO #74 Dev Card Speaker List -->
<ion-card class="speakerCard">
<ion-card class="speakerCard" @click="$emit('speaker-clicked', speaker)">
<div class="speakerCard-head">
<div class="avatarContainer">
<ion-thumbnail class="avatar _large">
Expand Down Expand Up @@ -49,13 +49,27 @@
import SpeakerLikeButton from "@/components/speaker-card/SpeakerLikeButton.vue";
import SpeakerResumeTalk from "@/components/speaker-card/SpeakerResumeTalk.vue";
import SpeakerInfoButton from "@/components/speaker-card/SpeakerInfoButton.vue";
import {VoxxrinTalk} from "@/models/VoxxrinTalk";
import {SpeakerId, VoxxrinSimpleSpeaker} from "@/models/VoxxrinSpeaker";
const { LL } = typesafeI18n()
defineEmits<{
(e: 'speaker-clicked', speaker: VoxxrinSimpleSpeaker): void,
}>()
const route = useRoute();
const eventId = ref(new EventId(getRouteParamsValue(route, 'eventId')));
const {conferenceDescriptor: confDescriptor} = useSharedConferenceDescriptor(eventId);
const baseUrl = import.meta.env.BASE_URL;
const speaker: VoxxrinSimpleSpeaker = {
id: new SpeakerId('42'),
fullName: "Frédéric Camblor",
companyName: "4SH",
photoUrl: "https://lh3.googleusercontent.com/a/AAcHTtdsbTGnaxXmrzSi178m_qpxj9c-z12qoL7SLB6cjUSfZhaQ=s96-c",
}
</script>

<style lang="scss">
Expand Down
2 changes: 2 additions & 0 deletions mobile/src/i18n/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ const en = {
App_settings: "App settings",
Configure_my_preferences_app: "Configure my preferences app",
Frequently_asked_questions: "Frequently asked questions",
Speaker_details: "Speaker details",
Close_speaker_details: "Close speaker details"
} satisfies BaseTranslation

export default en
16 changes: 16 additions & 0 deletions mobile/src/i18n/i18n-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,14 @@ type RootTranslation = {
* F​r​e​q​u​e​n​t​l​y​ ​a​s​k​e​d​ ​q​u​e​s​t​i​o​n​s
*/
Frequently_asked_questions: string
/**
* S​p​e​a​k​e​r​ ​d​e​t​a​i​l​s
*/
Speaker_details: string
/**
* C​l​o​s​e​ ​s​p​e​a​k​e​r​ ​d​e​t​a​i​l​s
*/
Close_speaker_details: string
}

export type TranslationFunctions = {
Expand Down Expand Up @@ -1029,6 +1037,14 @@ export type TranslationFunctions = {
* Frequently asked questions
*/
Frequently_asked_questions: () => LocalizedString
/**
* Speaker details
*/
Speaker_details: () => LocalizedString
/**
* Close speaker details
*/
Close_speaker_details: () => LocalizedString
}

export type Formatters = {
Expand Down
1 change: 1 addition & 0 deletions mobile/src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const routes: Array<RouteRecordRaw> = [
{ path: '/events/:eventId/embedded-schedule', component: () => import('@/views/event/EmbeddedSchedulePage.vue') },
{ path: '/events/:eventId/new-feedback-for-timeslot/:timeslotId', component: () => preloadedPage('NewFeedbackPage') },
{ path: '/events/:eventId/rate-talk/:talkId', component: () => preloadedPage('RateTalkPage') },
{ path: '/events/:eventId/speakers/:speakerId/details', component: () => preloadedPage('SpeakerDetailsPage') },
{ path: '/events/:eventId/talks/:talkId/details', component: () => preloadedPage('TalkDetailsPage') },
{ path: '/events/:eventId/talks/:talkId/asFeedbackViewer/:secretFeedbacksViewerToken', component: () => preloadedPage('_BaseEventDetailsPages'), children: [
{ path: '', redirect: (route) => `/events/${route.params.eventId}/talks/${route.params.talkId}/asFeedbackViewer/${route.params.secretFeedbacksViewerToken}/details` },
Expand Down
2 changes: 2 additions & 0 deletions mobile/src/router/preloaded-pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import InfosPage from "@/views/event/InfosPage.vue";
import NewFeedbackPage from '@/views/feedbacks/NewFeedbackPage.vue';
import RateTalkPage from '@/views/feedbacks/RateTalkPage.vue';
import TalkDetailsPage from '@/views/TalkDetailsPage.vue';
import SpeakerDetailsPage from '@/views/SpeakerDetailsPage.vue';
import _BaseEventDetailsPages from '@/views/event/details/_BaseEventDetailsPages.vue';
import TalkFeedbacksPage from '@/views/user/TalkFeedbacksPage.vue';
import UserDashboardPage from '@/views/user/UserDashboardPage.vue';
Expand Down Expand Up @@ -41,6 +42,7 @@ const modules = {
MyPersonalDataPage,
UserTokenRegistrationPage,
FAQPage,
SpeakerDetailsPage
} as const;

export type PreloadedModules = typeof modules;
Expand Down
88 changes: 88 additions & 0 deletions mobile/src/views/SpeakerDetailsPage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<template>
<ion-page>
<ion-content v-themed-event-styles="confDescriptor" :fullscreen="true" v-if="confDescriptor && detailedSpeaker">
<ion-header class="stickyHeader">
<ion-toolbar>
<ion-button class="stickyHeader-close" shape="round" slot="start" size="small" fill="outline" @click="closeAndNavigateBack()"
:aria-label="LL.Close_speaker_details()">
<ion-icon src="/assets/icons/solid/close.svg"></ion-icon>
</ion-button>
<ion-title class="stickyHeader-title" slot="start" >{{ LL.Speaker_details() }}</ion-title>
</ion-toolbar>
</ion-header>

<div class="talkDetails">
{{detailedSpeaker.fullName}}
</div>
</ion-content>
</ion-page>
</template>

<script setup lang="ts">
import {useRoute} from "vue-router";
import {EventId} from "@/models/VoxxrinEvent";
import {getRouteParamsValue, isRefDefined, toManagedRef as toRef, managedRef as ref} from "@/views/vue-utils";
import {
useUserEventTalkNotes,
useUserTalkNoteActions,
} from "@/state/useUserTalkNotes";
import {TalkId} from "@/models/VoxxrinTalk";
import {useSharedEventTalk} from "@/state/useEventTalk";
import {computed, toValue} from "vue";
import {typesafeI18n} from "@/i18n/i18n-vue";
import {IonBadge, IonAvatar, IonText, useIonRouter} from "@ionic/vue";
import {business} from "ionicons/icons";
import {useSharedConferenceDescriptor} from "@/state/useConferenceDescriptor";
import VoxDivider from "@/components/ui/VoxDivider.vue";
import {goBackOrNavigateTo} from "@/router";
import TalkDetailsHeader from "@/components/talk-details/TalkDetailsHeader.vue";
import {useEventTalkStats} from "@/state/useEventTalkStats";
import {Logger} from "@/services/Logger";
import {SpeakerId, VoxxrinDetailedSpeaker} from "@/models/VoxxrinSpeaker";
const LOGGER = Logger.named("TalkDetailsPage");
const ionRouter = useIonRouter();
function closeAndNavigateBack() {
goBackOrNavigateTo(ionRouter, `/events/${eventId.value.value}/speakers`, 0 /* talk details page is always opened through popups */)
}
const route = useRoute();
const eventId = ref(new EventId(getRouteParamsValue(route, 'eventId')));
const speakerId = ref(new TalkId(getRouteParamsValue(route, 'speakerId')));
const {conferenceDescriptor: confDescriptor} = useSharedConferenceDescriptor(eventId);
const { LL } = typesafeI18n()
const detailedSpeaker: VoxxrinDetailedSpeaker = {
id: new SpeakerId('42'),
fullName: "Frédéric Camblor",
companyName: "4SH",
photoUrl: "https://lh3.googleusercontent.com/a/AAcHTtdsbTGnaxXmrzSi178m_qpxj9c-z12qoL7SLB6cjUSfZhaQ=s96-c",
bio: `Retired Bordeaux JUG leader and co-creator of the BDX I/O conference in 2014, Frédéric enjoys mixing with different tech communities and learning new things.
Web developer at 4SH by day, and OSS commiter by night, he has created/contributed to some more or less well known projects: Voxxrin app, Vitemadose frontend during COVID Pandemic, Devoxx France CFP, RestX framework, as well as some (old) Jenkins plugins.
As a big fan of strong typing, he loves Typescript, but also like doing all kinds of stuff in Google Spreadsheets.`,
social: [
{type:'twitter', url: 'https://www.twitter.com/fcamblor'}
]
}
</script>

<style lang="scss" scoped>
ion-header {
ion-toolbar {
padding-top: 0;
&:before, &:after {
position: absolute;
content: '';
z-index: 1;
}
}
}
.speakerDetails {
}
</style>
22 changes: 21 additions & 1 deletion mobile/src/views/event/SpeakersDirectoryPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
</ion-toolbar>
</ion-header>

<SpeakerCard></SpeakerCard>
<speaker-card @speaker-clicked="openSpeakerDetails($event)"></speaker-card>
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button class="btnGoToTicketing" :aria-label="LL.Go_To_Ticketing()">
<ion-icon :icon="ticket" aria-hidden="true"></ion-icon>
Expand All @@ -39,12 +39,32 @@
import PoweredVoxxrin from "@/components/ui/PoweredVoxxrin.vue";
import SpeakerCard from "@/components/speaker-card/SpeakerCard.vue";
import ListModeSwitch from "@/components/ui/ListModeSwitch.vue";
import {useTabbedPageNav} from "@/state/useTabbedPageNav";
import {VoxxrinSimpleSpeaker} from "@/models/VoxxrinSpeaker";
const { LL } = typesafeI18n()
const route = useRoute();
const eventId = ref(new EventId(getRouteParamsValue(route, 'eventId')));
const {conferenceDescriptor: confDescriptor} = useSharedConferenceDescriptor(eventId);
const { triggerTabbedPageNavigate } = useTabbedPageNav();
const baseUrl = import.meta.env.BASE_URL;
async function openSpeakerDetails(speaker: VoxxrinSimpleSpeaker) {
if(speaker) {
// TODO: Re-enable this once *tabbed* talk details as feedback viewer routing has been fixed
// const talkFeedbackViewerToken = toValue(talkFeedbackViewerTokensRef)?.find(t => t.talkId.isSameThan(talk.id));
// const url = talkFeedbackViewerToken
// ?`/events/${eventId.value.value}/talks/${talk.id.value}/asFeedbackViewer/${talkFeedbackViewerToken.secretToken}/details`
// :`/events/${eventId.value.value}/talks/${talk.id.value}/details`
const url = `/events/${eventId.value.value}/speakers/${speaker.id.value}/details`
triggerTabbedPageNavigate(url, "forward", "push");
}
}
function toggleSearchField() {
}
</script>

<style lang="scss" scoped>
Expand Down

0 comments on commit 481d6ee

Please sign in to comment.