diff --git a/frontend/src/definitions.ts b/frontend/src/definitions.ts index 4b423ca6..e438b394 100644 --- a/frontend/src/definitions.ts +++ b/frontend/src/definitions.ts @@ -275,6 +275,10 @@ export enum MetricEvents { WaitingListEmailRemoved = 'apmt.signup.email-removed', } +export enum Dismissibles { + BetaWarning = 'beta-warning' +} + export default { AlertSchemes, BookingCalendarView, @@ -304,4 +308,5 @@ export default { TableDataType, TooltipPosition, WaitingListAction, + Dismissibles, }; diff --git a/frontend/src/locales/de.json b/frontend/src/locales/de.json index 6e7c33fa..3be95c17 100644 --- a/frontend/src/locales/de.json +++ b/frontend/src/locales/de.json @@ -357,6 +357,21 @@ "shareMyLink": "Meinen Link teilen", "reportBug": "Fehler melden" }, + "notices": { + "betaWarning": { + "heading": "Da wir aktuell in der Beta-Phase sind, hier einige Tips um Probleme zu umgehen:", + "list": [ + "Überprüfe den Spam Ordner, da einige Emails dort landen könnten", + "Falls Zoom Meetings nicht in der Kalender-Einladung auftauchen, bitte trenne die Verbindung im {connectedAccounts} Abschnitt der Einstellungen, und stelle sie erneut her", + "Sollte es noch weitere Probleme geben, nutze das {contactUs}, oder kommt in unseren {matrixChannel}" + ], + "linkText": { + "connectedAccounts": "Verbundene Konten", + "contactUs": "Kontaktformular", + "matrixChannel": "Matrix Kanal" + } + } + }, "placeholder": { "biWeeklyCafeDates": "Zweiwöchentliche Café-Treffen …", "emailAddress": "max.muster{'@'}beispiel.de", diff --git a/frontend/src/locales/en.json b/frontend/src/locales/en.json index b0ddc6ac..509b979e 100644 --- a/frontend/src/locales/en.json +++ b/frontend/src/locales/en.json @@ -357,6 +357,21 @@ "shareMyLink": "Share my link", "reportBug": "Report Bug" }, + "notices": { + "betaWarning": { + "heading": "As we're currently in beta, we do have some issues we're dealing with:", + "list": [ + "Please check your spam folder as some emails might end up there", + "If Zoom meetings don't appear in your appointment invite, please disconnect and reconnect your zoom account in the {connectedAccounts} section of the settings", + "If you experience other issues, please use the {contactUs} form, or join us on our {matrixChannel}" + ], + "linkText": { + "connectedAccounts": "Connected Accounts", + "contactUs": "contact us", + "matrixChannel": "Matrix Channel" + } + } + }, "placeholder": { "biWeeklyCafeDates": "Bi-weekly Café Dates…", "emailAddress": "john.doe{'@'}example.com", diff --git a/frontend/src/models.ts b/frontend/src/models.ts index e465d649..0c790d1c 100644 --- a/frontend/src/models.ts +++ b/frontend/src/models.ts @@ -229,6 +229,14 @@ export type User = { uniqueHash: string; }; +/** + * User activity as in the things they do within our application + * Used to store the state of dismissables and such. + */ +export type UserActivity = { + dismissedBetaWarning: boolean, +}; + export type Subscriber = { id?: number; username: string; diff --git a/frontend/src/stores/user-activity-store.ts b/frontend/src/stores/user-activity-store.ts new file mode 100644 index 00000000..d0c1dc78 --- /dev/null +++ b/frontend/src/stores/user-activity-store.ts @@ -0,0 +1,23 @@ +import { defineStore } from 'pinia'; +import { UserActivity } from '@/models'; +import { useLocalStorage } from '@vueuse/core'; +import { Dismissibles } from '@/definitions'; + +const initialUserActivityObject = { + dismissedBetaWarning: false, +} as UserActivity; + +/** + * A place to store the state of UI elements, like a dismissible message or if we want something to stay minimized. + */ +export const useUserActivityStore = defineStore('user-activity', () => { + const data = useLocalStorage('tba/user-activity', initialUserActivityObject); + + const dismiss = (dismissible: Dismissibles) => { + if (dismissible === Dismissibles.BetaWarning) { + data.value.dismissedBetaWarning = true; + } + }; + + return { dismiss, data }; +}); diff --git a/frontend/src/views/ScheduleView.vue b/frontend/src/views/ScheduleView.vue index e79090b3..c538c29d 100644 --- a/frontend/src/views/ScheduleView.vue +++ b/frontend/src/views/ScheduleView.vue @@ -2,7 +2,7 @@ import { BookingCalendarView, DateFormatStrings, - DEFAULT_SLOT_DURATION, + DEFAULT_SLOT_DURATION, Dismissibles, EventLocationType, MeetingLinkProviderType, } from '@/definitions'; @@ -23,10 +23,13 @@ import { } from '@/models'; import ScheduleCreation from '@/components/ScheduleCreation.vue'; import CalendarQalendar from '@/components/CalendarQalendar.vue'; +import NoticeBar from '@/tbpro/elements/NoticeBar.vue'; +import PrimaryButton from '@/tbpro/elements/PrimaryButton.vue'; // stores import { useAppointmentStore } from '@/stores/appointment-store'; import { useCalendarStore } from '@/stores/calendar-store'; +import { useUserActivityStore } from '@/stores/user-activity-store'; const { t } = useI18n(); const route = useRoute(); @@ -36,8 +39,10 @@ const refresh = inject(refreshKey); const appointmentStore = useAppointmentStore(); const calendarStore = useCalendarStore(); +const userActivityStore = useUserActivityStore(); const { pendingAppointments } = storeToRefs(appointmentStore); const { connectedCalendars } = storeToRefs(calendarStore); +const { data: userActivityData } = storeToRefs(userActivityStore); // current selected date, if not in route: defaults to now const activeDate = ref(route.params.date ? dj(route.params.date as string) : dj()); @@ -146,9 +151,43 @@ onMounted(async () => { const eventsTo = dj(activeDate.value).endOf('month').format('YYYY-MM-DD'); await getRemoteEvents(eventsFrom, eventsTo); }); + +const dismiss = () => { + userActivityStore.dismiss(Dismissibles.BetaWarning); +}; +