@@ -21,15 +21,14 @@
v-for="item in desktopActions"
:key="item.type"
class="px-4"
- :color="item.color"
+ :color="item.color ?? undefined"
:disabled="item.type === 'next' && !isValid"
- large
- :outlined="item.variant === 'outlined'"
- :text="item.variant === 'text'"
+ size="large"
:title="Object.keys(item.label).length ? translate(item.label) : translate(item.text)"
+ :variant="item.variant"
@click="action(item.type, foodOrMealId, item.params)"
>
-
+
{{ item.icon }}
{{ translate(item.text) }}
@@ -40,20 +39,56 @@
-
+
-
diff --git a/apps/survey/src/components/prompts/layouts/use-layout.ts b/apps/survey/src/components/prompts/layouts/use-layout.ts
new file mode 100644
index 0000000000..2762c73410
--- /dev/null
+++ b/apps/survey/src/components/prompts/layouts/use-layout.ts
@@ -0,0 +1,118 @@
+import get from 'lodash/get';
+import set from 'lodash/set';
+import { computed, onBeforeMount, type SetupContext } from 'vue';
+
+import type { Prompt } from '@intake24/common/prompts';
+import type { PromptSection } from '@intake24/common/surveys';
+import type { FoodState, MealState } from '@intake24/common/types';
+import { defaultMessages, useI18n } from '@intake24/i18n';
+import { useFoodUtils, useMealUtils, usePromptUtils } from '@intake24/survey/composables';
+import { useSurvey } from '@intake24/survey/stores';
+
+export type UseLayoutProps = {
+ prompt: Prompt;
+ section: PromptSection;
+ food?: FoodState;
+ meal?: MealState;
+ isValid?: boolean;
+};
+
+export function useLayout(props: UseLayoutProps, ctx: SetupContext<'action'[]>) {
+ const { i18n: globalI18n, translate } = useI18n();
+ const { action, isInMultiPrompt, params, type } = usePromptUtils(props, ctx);
+ const { foodName } = useFoodUtils(props);
+ const { mealName, mealTime, mealNameWithTime } = useMealUtils(props);
+ const survey = useSurvey();
+
+ const meals = computed(() => survey.data.meals);
+ const showSummary = computed(() => {
+ if (props.prompt.component === 'submit-prompt' && props.prompt.review.mobile !== false)
+ return false;
+
+ if (survey.hasFinished)
+ return false;
+
+ return !['preMeals'].includes(props.section);
+ });
+
+ const loadPromptTranslations = () => {
+ const messages = globalI18n.getLocaleMessage(globalI18n.locale.value);
+
+ const defaultPromptMessages = get(
+ defaultMessages.getMessages(globalI18n.locale.value),
+ `prompts.${type.value}`,
+ );
+
+ if (defaultPromptMessages === undefined) {
+ console.error(`Failed to load default translation messages using key "prompts.${type.value}", locale "${globalI18n.locale.value}". Please update the translation files!`);
+ }
+ else {
+ Object.entries(defaultPromptMessages).forEach(([key, value]) => {
+ set(messages, `prompts.${type.value}.${key}`, props.prompt.i18n[key]?.[globalI18n.locale.value] ?? value);
+ });
+ }
+
+ globalI18n.setLocaleMessage(globalI18n.locale.value, messages);
+ };
+
+ const foodOrMealId = computed(() => props.food?.id ?? props.meal?.id);
+ const desktopActions = computed(() => props.prompt.actions?.items.filter(action => action.layout.includes('desktop')) ?? []);
+ const hasDefaultSlot = computed(() => !!ctx.slots.default);
+ const hasActionsSlot = computed(() => !!ctx.slots.actions);
+ const hasNavActionsSlot = computed(() => !!ctx.slots['nav-actions']);
+ const mobileActions = computed(() => props.prompt.actions?.items.filter(action => action.layout.includes('mobile')) ?? []);
+
+ const i18n = computed(() => (
+
+ /*
+ * Workaround for multi-prompt i18n
+ * - at the moment scheme prompt i18n is merged into the vue-i18n instance messages, so it can be used directly
+ * - this approach allows use of vue-i18n component to interpolate the i18n strings
+ * - however multi-prompt is displaying multiple prompts at once, so same prompt types override each other
+ * - TODO: implement own vue-i18n component and merge the i18n outside of the vue-i18n instance?
+ */
+ {
+ /* name: this.$t(`prompts.${this.type}.name`, this.params),
+ text: this.$t(`prompts.${this.type}.text`, this.params),
+ description: this.translatePath(`prompts.${this.type}.description`, this.params, true), */
+ name: translate(props.prompt.i18n.name, {
+ params: params.value,
+ path: `prompts.${type.value}.name`,
+ }),
+ text: translate(props.prompt.i18n.text, {
+ params: params.value,
+ path: `prompts.${type.value}.text`,
+ }),
+ description: translate(props.prompt.i18n.description, {
+ params: params.value,
+ path: `prompts.${type.value}.description`,
+ sanitize: true,
+ }),
+ }
+ ));
+
+ onBeforeMount(() => {
+ loadPromptTranslations();
+ });
+
+ return {
+ action,
+ desktopActions,
+ foodName,
+ foodOrMealId,
+ hasActionsSlot,
+ hasDefaultSlot,
+ hasNavActionsSlot,
+ i18n,
+ isInMultiPrompt,
+ mealName,
+ mealTime,
+ mealNameWithTime,
+ mobileActions,
+ params,
+ showSummary,
+ translate,
+ type,
+ meals,
+ };
+}
diff --git a/apps/survey/src/components/prompts/multi-prompt.vue b/apps/survey/src/components/prompts/multi-prompt.vue
index 62bfdce138..5a9332815f 100644
--- a/apps/survey/src/components/prompts/multi-prompt.vue
+++ b/apps/survey/src/components/prompts/multi-prompt.vue
@@ -3,7 +3,7 @@
v-bind="{ food, meal, prompt: prompt.prompts[panel ?? 0], section, isValid }"
@action="action"
>
-
+
()],
props: {
- value: {
+ modelValue: {
type: Array as PropType<(CustomPromptAnswer | undefined)[]>,
required: true,
},
},
- emits: ['input'],
+ emits: ['action', 'update:modelValue'],
setup(props, ctx) {
const isAnswerRequired = (prompt: Prompt) =>
@@ -60,15 +60,15 @@ export default defineComponent({
const isValid = computed(
() =>
- !props.value.some(
+ !props.modelValue.some(
(answer, idx) => answer === undefined && isAnswerRequired(props.prompt.prompts[idx]),
),
);
const panel = ref(0);
const state = computed({
- get: () => props.value,
- set: value => ctx.emit('input', value),
+ get: () => props.modelValue,
+ set: value => ctx.emit('update:modelValue', value),
});
const confirm = () => {
@@ -82,7 +82,7 @@ export default defineComponent({
if (state.value[idx] === undefined && !isAnswerRequired(prompt))
state.value[idx] = null;
- for (const [index, answer] of Object.entries(props.value)) {
+ for (const [index, answer] of Object.entries(props.modelValue)) {
if (answer === undefined) {
panel.value = Number.parseInt(index);
return;
diff --git a/apps/survey/src/components/prompts/partials/AsServedSelector.vue b/apps/survey/src/components/prompts/partials/AsServedSelector.vue
index 336f25668f..6c42da471b 100644
--- a/apps/survey/src/components/prompts/partials/AsServedSelector.vue
+++ b/apps/survey/src/components/prompts/partials/AsServedSelector.vue
@@ -1,14 +1,14 @@
-
+
-
+
{{ thumbnailWeight }}
@@ -16,51 +16,55 @@
-
+
-
-
+
+
- $decrement
+
+ $decrement
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
- $increment
+
+ $increment
+
@@ -68,7 +72,7 @@
-
+
{{ $t(`prompts.asServed.${type}.confirm`) }}
@@ -104,13 +108,13 @@ export default defineComponent({
type: String as PropType<'serving' | 'leftovers'>,
default: 'serving',
},
- value: {
+ modelValue: {
type: Object as PropType,
default: null,
},
},
- emits: ['confirm', 'input'],
+ emits: ['confirm', 'update:modelValue'],
setup(props) {
const denominator = 4;
@@ -125,13 +129,13 @@ export default defineComponent({
maxNumerator: denominator,
denominator,
weight,
- value: denominator,
+ modelValue: denominator,
});
const lessWeightFactor = (
show: boolean,
weight: number,
- value?: number,
+ modelValue?: number,
): WeightFactorProps => ({
show,
type: props.type,
@@ -140,10 +144,10 @@ export default defineComponent({
maxNumerator: denominator - 1,
denominator,
weight,
- value: value ?? denominator - 1,
+ modelValue: modelValue ?? denominator - 1,
});
- const moreWeightFactor = (show: boolean, weight: number, value?: number): WeightFactorProps => {
+ const moreWeightFactor = (show: boolean, weight: number, modelValue?: number): WeightFactorProps => {
let minNumerator = denominator + 1;
let maxNumerator = denominator * 5;
@@ -151,7 +155,7 @@ export default defineComponent({
if ((minNumerator / denominator) * weight >= props.maxWeight) {
minNumerator = denominator;
maxNumerator = denominator;
- value = denominator;
+ modelValue = denominator;
}
else {
maxNumerator = denominator;
@@ -173,7 +177,7 @@ export default defineComponent({
maxNumerator,
denominator,
weight,
- value: value ?? denominator + 1,
+ modelValue: modelValue ?? denominator + 1,
};
};
@@ -233,7 +237,7 @@ export default defineComponent({
return ((this.denominator + 1) / this.denominator) * weight < this.maxWeight;
},
weightFactor(): number {
- return this.weightFactorProps.value / this.weightFactorProps.denominator;
+ return this.weightFactorProps.modelValue / this.weightFactorProps.denominator;
},
},
@@ -274,14 +278,14 @@ export default defineComponent({
);
}
- if (this.value?.index !== undefined)
- this.setSelection(this.value.index, true);
+ if (this.modelValue?.index !== undefined)
+ this.setSelection(this.modelValue.index, true);
else this.setSelection(Math.floor(this.asServedData.images.length / 2));
},
initWeightFactor(asServedData: AsServedSetResponse, objectIdx: number) {
const objectWeight = asServedData.images[objectIdx].weight;
- const initWeight = this.value?.weight;
+ const initWeight = this.modelValue?.weight;
if (initWeight === undefined)
return;
@@ -348,7 +352,7 @@ export default defineComponent({
},
updateWeightFactor(value: number) {
- this.weightFactorProps.value = value;
+ this.weightFactorProps.modelValue = value;
this.update();
},
@@ -371,7 +375,7 @@ export default defineComponent({
imageUrl: asServedData.images[objectIdx].mainImageUrl,
};
- this.$emit('input', state);
+ this.$emit('update:modelValue', state);
},
confirm() {
diff --git a/apps/survey/src/components/prompts/partials/AsServedWeightFactor.vue b/apps/survey/src/components/prompts/partials/AsServedWeightFactor.vue
index 0ad0902eb5..8c68a79a28 100644
--- a/apps/survey/src/components/prompts/partials/AsServedWeightFactor.vue
+++ b/apps/survey/src/components/prompts/partials/AsServedWeightFactor.vue
@@ -1,26 +1,26 @@
-
-
+
+
$increment
-
-
+
{{ whole }}
@@ -28,7 +28,7 @@
{{ fraction }}
-
+
{{ $t(`prompts.asServed.weightFactor.${subType}`) }}
@@ -41,9 +41,9 @@
color="secondary"
:disabled="numerator === minNumerator"
icon
- large
- outlined
+ size="large"
:title="$t(`prompts.asServed.${type}.less`)"
+ variant="outlined"
@click="update(-1)"
>
@@ -51,14 +51,14 @@
@@ -74,7 +74,6 @@
diff --git a/apps/survey/src/components/prompts/standard/ReadyMealPrompt.vue b/apps/survey/src/components/prompts/standard/ReadyMealPrompt.vue
index 4e9aee36da..ae4129e71f 100644
--- a/apps/survey/src/components/prompts/standard/ReadyMealPrompt.vue
+++ b/apps/survey/src/components/prompts/standard/ReadyMealPrompt.vue
@@ -1,10 +1,10 @@
-
+
-
+
{{ idx + 1 }}
{{ food.name }}
@@ -45,23 +45,23 @@ export default defineComponent({
type: Object as PropType,
required: true,
},
- value: {
+ modelValue: {
type: Array as PropType,
required: true,
},
},
- emits: ['input'],
+ emits: ['action', 'update:modelValue'],
setup(props, ctx) {
const { action } = usePromptUtils(props, ctx);
const state = computed({
get() {
- return props.value;
+ return props.modelValue;
},
set(value) {
- ctx.emit('input', value);
+ ctx.emit('update:modelValue', value);
},
});
const isValid = computed(() => state.value.every(food => food.value !== undefined));
diff --git a/apps/survey/src/components/prompts/standard/RecallDatePrompt.vue b/apps/survey/src/components/prompts/standard/RecallDatePrompt.vue
index 0c6808a02a..5d26233010 100644
--- a/apps/survey/src/components/prompts/standard/RecallDatePrompt.vue
+++ b/apps/survey/src/components/prompts/standard/RecallDatePrompt.vue
@@ -4,7 +4,7 @@
@@ -32,13 +32,13 @@ export default defineComponent({
mixins: [createBasePrompt<'recall-date-prompt'>()],
props: {
- value: {
+ modelValue: {
type: String as PropType,
default: null,
},
},
- emits: ['input'],
+ emits: ['action', 'update:modelValue'],
setup(props, ctx) {
const { action, customPromptLayout } = usePromptUtils(props, ctx);
diff --git a/apps/survey/src/components/prompts/standard/RedirectPrompt.vue b/apps/survey/src/components/prompts/standard/RedirectPrompt.vue
index 2741374629..09e595007f 100644
--- a/apps/survey/src/components/prompts/standard/RedirectPrompt.vue
+++ b/apps/survey/src/components/prompts/standard/RedirectPrompt.vue
@@ -7,9 +7,9 @@
v-if="prompt.timer"
class="mb-6"
color="secondary"
+ :model-value="timerValue"
:rotate="-90"
:size="200"
- :value="timerValue"
:width="20"
>
@@ -22,11 +22,11 @@
-
+
$home
{{ $t('common.home') }}
@@ -36,11 +36,11 @@
class="px-4"
color="primary"
:disabled="!feedbackAvailable"
- large
- outlined
+ size="large"
:to="{ name: 'feedback-home', params: { surveyId } }"
+ variant="outlined"
>
-
+
$feedback
{{ $t('recall.actions.feedback') }}
@@ -51,12 +51,12 @@
class="px-4"
color="primary"
:href="followUpUrl"
- large
- outlined
+ size="large"
:target="prompt.target"
:title="promptI18n.goTo"
+ variant="outlined"
>
-
+
$redirect
{{ promptI18n.goTo }}
@@ -77,8 +77,8 @@
v-if="feedbackEnabled"
color="primary"
:disabled="!feedbackAvailable"
- text
:to="{ name: 'feedback-home', params: { surveyId } }"
+ variant="text"
>
{{ $t('recall.actions.nav.feedback') }}
@@ -88,7 +88,7 @@
-
+
{{ promptI18n.goTo }}
@@ -101,7 +101,7 @@
@@ -109,7 +109,7 @@
diff --git a/apps/survey/src/views/survey/error.vue b/apps/survey/src/views/survey/error.vue
index 908ad12928..76407c4d94 100644
--- a/apps/survey/src/views/survey/error.vue
+++ b/apps/survey/src/views/survey/error.vue
@@ -8,7 +8,7 @@
-
+
fas fa-exclamation-triangle
@@ -27,7 +27,7 @@
:to="{ name: 'survey-home', params: { surveyId } }"
>
-
+
fas fa-sync-alt
diff --git a/apps/survey/src/views/survey/generate-user.vue b/apps/survey/src/views/survey/generate-user.vue
index aaede1907f..fff119c70c 100644
--- a/apps/survey/src/views/survey/generate-user.vue
+++ b/apps/survey/src/views/survey/generate-user.vue
@@ -1,66 +1,70 @@
-
-
-
+
+
+
{{ $t('survey.generateUser.info1') }}
{{ $t('survey.generateUser.info2') }}
-
+
{{ $t('survey.generateUser._') }}
-
+
+ variant="outlined"
+ >
+
+
+ {{ showPassword ? 'fas fa-eye' : 'fas fa-eye-slash' }}
+
+
+
-
+
{{ $t(`survey.generateUser.${status}`, { surveyId: survey?.name ?? surveyId }) }}
-
+
{{ $t('survey.generateUser.link') }}
-
+
-
-
+
+
{{ $t('common.action.continue') }}
-
+
-
-
+
+
fas fa-angles-left
{{ $t('common.login.back') }}
@@ -70,116 +74,91 @@
-
diff --git a/apps/survey/src/views/survey/home.vue b/apps/survey/src/views/survey/home.vue
index 6eb4573ed6..7c682d6f7a 100644
--- a/apps/survey/src/views/survey/home.vue
+++ b/apps/survey/src/views/survey/home.vue
@@ -1,90 +1,87 @@
-
-
+
+
-
+
-
+
{{ $t('survey.welcome._') }}
- {{ $t('survey.welcome.subtitle') }}
+
+ {{ $t('survey.welcome.subtitle') }}
+
-
- {{ $t('survey.info') }}
+
+ {{ $t('survey.info') }}
-
- {{ $t('survey._') }}
-
- {{ parameters?.name }}
-
-
+ {{ $t('survey._') }}
+
+ {{ parameters?.name }}
+
-
- {{ $t('survey.states._') }}
-
- {{ $t(`survey.states.${parameters?.state}`) }}
-
-
+ {{ $t('survey.states._') }}
+
+ {{ $t(`survey.states.${parameters?.state}`) }}
+
-
- {{ $t('recall.info') }}
+
+ {{ $t('recall.info') }}
-
-
+
+
fas fa-ban
-
-
-
- {{ $t(`recall.limitReached.${dailyLimitReached ? 'daily' : 'total'}`) }}
-
-
+
+
+ {{ $t(`recall.limitReached.${dailyLimitReached ? 'daily' : 'total'}`) }}
+
-
-
+
+
$check
-
-
-
- {{ $t('recall.finishedAt', { finishedAt: endTime?.toLocaleString() }) }}
-
-
-
-
-
- fas fa-beat fa-play
-
- {{ $t('recall.start.another') }}
-
-
+
+
+ {{ $t('recall.finishedAt', { finishedAt: endTime?.toLocaleString() }) }}
+
+
+
+
+
+ fas fa-beat fa-play
+
+ {{ $t('recall.start.another') }}
+
+
+
-
+
-
+
fas fa-beat fa-play
{{ $t('recall.start.another') }}
@@ -93,70 +90,68 @@
-
-
+
+
$pause
-
-
-
- {{ $t('recall.startedAt', { startedAt: startTime?.toLocaleString() }) }}
-
-
-
-
-
- $pause
-
- {{ $t('recall.continue') }}
-
-
-
-
-
- $cancel
-
- {{ $t('recall.abort._') }}
-
-
- {{ $t('recall.abort.confirm') }}
-
-
+
+
+ {{ $t('recall.startedAt', { startedAt: startTime?.toLocaleString() }) }}
+
+
+
+
+
+ $pause
+
+ {{ $t('recall.continue') }}
+
+
+
+
+
+ $cancel
+
+ {{ $t('recall.abort._') }}
+
+
+ {{ $t('recall.abort.confirm') }}
+
+
+
-
+
-
+
-
+
$cancel
{{ $t('recall.abort._') }}
@@ -167,13 +162,13 @@
-
+
$pause
{{ $t('recall.continue') }}
@@ -182,39 +177,39 @@
-
-
+
+
$start
-
-
- {{ $t('recall.none') }}
-
-
-
-
- $start
-
- {{ $t('recall.start._') }}
-
-
+
+ {{ $t('recall.none') }}
+
+
+
+
+ $start
+
+ {{ $t('recall.start._') }}
+
+
+
-
+
-
+
$start
{{ $t('recall.start._') }}
@@ -226,41 +221,41 @@
-
- {{ $t('feedback.info') }}
+
+ {{ $t('feedback.info') }}
-
-
+
+
$feedback
-
-
- {{ $t('feedback.status.available') }}
-
-
-
-
- $feedback
-
- {{ $t(`feedback._`) }}
-
-
+
+ {{ $t('feedback.status.available') }}
+
+
+
+
+ $feedback
+
+ {{ $t(`feedback._`) }}
+
+
+
-
+
-
+
$feedback
{{ $t(`feedback._`) }}
@@ -268,36 +263,34 @@
-
-
+
+
$info
-
-
-
- {{
- $t('feedback.status.lowRecalls', {
- minRecalls: parameters?.numberOfSubmissionsForFeedback,
- })
- }}
-
-
+
+
+ {{
+ $t('feedback.status.lowRecalls', {
+ minRecalls: parameters?.numberOfSubmissionsForFeedback,
+ })
+ }}
+
-
+
{{ $t('recall.submissions.past') }}
-
+
@@ -312,16 +305,14 @@
-
-
+
+
$survey
-
-
-
- {{ $t('recall.submissions.none') }}
-
-
+
+
+ {{ $t('recall.submissions.none') }}
+
diff --git a/apps/survey/src/views/survey/login.vue b/apps/survey/src/views/survey/login.vue
index 91a8ae7b27..a368344743 100644
--- a/apps/survey/src/views/survey/login.vue
+++ b/apps/survey/src/views/survey/login.vue
@@ -1,18 +1,18 @@
-
+
{{ survey?.name }}
- {{ $t('common.login.subtitle').toString() }}
+ {{ $t('common.login.subtitle') }}
-
+
@@ -24,31 +24,35 @@
hide-details="auto"
:label="$t('common.username')"
name="username"
- outlined
prepend-inner-icon="fas fa-user"
required
+ variant="outlined"
/>
+ variant="outlined"
+ >
+
+
+ {{ showPassword ? 'fas fa-eye' : 'fas fa-eye-slash' }}
+
+
+
-
+
{{ $t('common.login._') }}
@@ -64,7 +68,7 @@
-
+
{{ `No account?` }}
@@ -77,10 +81,10 @@
{{ $t('survey.generateUser._') }}
@@ -93,97 +97,77 @@
-
diff --git a/apps/survey/src/views/survey/profile.vue b/apps/survey/src/views/survey/profile.vue
index b6c17aaeed..b9d4e0508b 100644
--- a/apps/survey/src/views/survey/profile.vue
+++ b/apps/survey/src/views/survey/profile.vue
@@ -1,99 +1,85 @@
-
-
+
+
-
-
- {{ $t('profile.info') }}
+
+
+ {{ $t('profile.info') }}
-
-
- fas fa-user
-
-
-
- {{ $t('common.name') }}
-
- {{ user?.name || $t('common.not.provided') }}
-
-
+
+
+
+ {{ $t('common.name') }}
+
+ {{ user?.name || $t('common.not.provided') }}
+
-
-
- fas fa-id-badge
-
-
-
- {{ $t('profile.provider') }}
-
- {{ profile.subject.provider || $t('common.not.provided') }}
-
-
+
+
+
+ {{ $t('profile.provider') }}
+
+ {{ profile.subject.provider || $t('common.not.provided') }}
+
-
-
- fas fa-key
-
-
-
- {{ $t('profile.providerId') }}
-
- {{ profile.subject.providerKey || $t('common.not.provided') }}
-
-
+
+
+
+ {{ $t('profile.providerId') }}
+
+ {{ profile.subject.providerKey || $t('common.not.provided') }}
+
-
- {{ $t('profile.settings') }}
+
+ {{ $t('profile.settings') }}
-
-
- fas fa-language
-
-
-
-
-
-
- {{ item.englishName }}
-
-
-
- {{ item.englishName }}
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ item.raw.englishName }}
+
+
-
-
+
+
- {{ $t('common.logout._') }}
-
+ {{ $t('common.logout._') }}
+
$logout
@@ -110,7 +96,7 @@
diff --git a/packages/ui/src/barcodes/quagga/quagga-input.vue b/packages/ui/src/barcodes/quagga/quagga-input.vue
index 6c3c8bad31..fb3be81c92 100644
--- a/packages/ui/src/barcodes/quagga/quagga-input.vue
+++ b/packages/ui/src/barcodes/quagga/quagga-input.vue
@@ -1,11 +1,11 @@
-
+
fas fa-barcode
@@ -44,7 +44,7 @@ const props = defineProps({
const emit = defineEmits<{
(e: 'detected', value: string): void;
- (e: 'update:model-value', value: string | null): void;
+ (e: 'update:modelValue', value: string | null): void;
}>();
const barcode = useVModel(props, 'modelValue', emit);
diff --git a/packages/ui/src/barcodes/quagga/quagga-reader.vue b/packages/ui/src/barcodes/quagga/quagga-reader.vue
index 9308918fa0..82c8a3d55f 100644
--- a/packages/ui/src/barcodes/quagga/quagga-reader.vue
+++ b/packages/ui/src/barcodes/quagga/quagga-reader.vue
@@ -1,15 +1,13 @@
-
+
-
- $close
-
+
Scan barcode
@@ -17,7 +15,7 @@
fas fa-crosshairs
-
+
>();
const reader = ref>();
-// @ts-expect-error should allow vue instance?
const { height, width } = useElementSize(card);
const initializing = ref(false);
diff --git a/packages/ui/src/barcodes/strich/strich-input.vue b/packages/ui/src/barcodes/strich/strich-input.vue
index 3551f51dce..c90dae1e91 100644
--- a/packages/ui/src/barcodes/strich/strich-input.vue
+++ b/packages/ui/src/barcodes/strich/strich-input.vue
@@ -1,11 +1,11 @@
-
+
fas fa-barcode
@@ -38,7 +38,7 @@ const props = defineProps({
const emit = defineEmits<{
(e: 'detected', value: string): void;
- (e: 'update:model-value', value: string | null): void;
+ (e: 'update:modelValue', value: string | null): void;
}>();
const barcode = useVModel(props, 'modelValue', emit);
diff --git a/packages/ui/src/barcodes/strich/strich-reader.vue b/packages/ui/src/barcodes/strich/strich-reader.vue
index e26e9a6b29..141f69946e 100644
--- a/packages/ui/src/barcodes/strich/strich-reader.vue
+++ b/packages/ui/src/barcodes/strich/strich-reader.vue
@@ -2,15 +2,13 @@
-
+
-
- $close
-
+
Scan barcode
>();
const reader = ref>();
-// @ts-expect-error should allow vue instance?
const { height, width } = useElementSize(card);
let barcodeReader: BarcodeReader | undefined;
diff --git a/packages/ui/src/captcha/captcha.vue b/packages/ui/src/captcha/captcha.vue
index 52e50ce89c..d12c0e33f1 100644
--- a/packages/ui/src/captcha/captcha.vue
+++ b/packages/ui/src/captcha/captcha.vue
@@ -7,7 +7,7 @@
ref="captcha"
:sitekey="sitekey"
size="invisible"
- @challengeExpired="expired"
+ @challenge-expired="expired"
@expired="expired"
@verify="verified"
/>
@@ -30,53 +30,52 @@
-
diff --git a/packages/ui/src/components/app-info.vue b/packages/ui/src/components/app-info.vue
index 02f9f131fa..8489f80aaf 100644
--- a/packages/ui/src/components/app-info.vue
+++ b/packages/ui/src/components/app-info.vue
@@ -1,25 +1,19 @@
-
- {{ $t('common.app.info') }}
+
+ {{ $t('common.app.info') }}
-
-
- fas fa-code-branch
-
-
-
- {{ $t('common.app._') }}: {{ app.name }}
-
- {{ $t('common.app.build') }}: {{ app.build.fullVersion }}
-
-
-
-
-
- far fa-clipboard
-
-
-
+
+
+
+ {{ $t('common.app._') }}: {{ app.name }}
+
+ {{ $t('common.app.build') }}: {{ app.build.fullVersion }}
+
+
+
+
+
+
diff --git a/packages/ui/src/components/dialogs/confirm-dialog.vue b/packages/ui/src/components/dialogs/confirm-dialog.vue
index a22ba49056..fc9828f845 100644
--- a/packages/ui/src/components/dialogs/confirm-dialog.vue
+++ b/packages/ui/src/components/dialogs/confirm-dialog.vue
@@ -1,20 +1,22 @@
-
-
+
+
-
+
{{ iconLeft }}
@@ -37,18 +39,18 @@
-
+
- {{ `DELETE ${typedConfirm}` }}
+ {{ `DELETE ${typedConfirm}` }}
-
+
@@ -59,18 +61,18 @@
block
class="mb-3"
:color="color"
- large
+ size="large"
:title="confirmLabel"
@click.stop="confirm"
>
-
+
{{ confirmIcon }}
{{ confirmLabel }}
-
-
+
+
{{ cancelIcon }}
{{ cancelLabel }}
@@ -79,145 +81,133 @@
-
diff --git a/packages/ui/src/components/layouts/app-entry-screen.vue b/packages/ui/src/components/layouts/app-entry-screen.vue
index 9d9fc66dc5..1486067db6 100644
--- a/packages/ui/src/components/layouts/app-entry-screen.vue
+++ b/packages/ui/src/components/layouts/app-entry-screen.vue
@@ -1,30 +1,30 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+
+
+
+
+ {{ subtitle }}
+
-
-
- {{ title }}
-
-
-
-
-
- {{ subtitle }}
-
-
-
-
-
+
+
+
+