101 lines
2.9 KiB
Vue
101 lines
2.9 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from "vue";
|
|
|
|
export interface Props {
|
|
// Number of steps including the start and end badge
|
|
steps: number;
|
|
// Current step, starting at 0 for the start badge
|
|
currentStep: number;
|
|
startBadgeText?: string;
|
|
endBadgeText?: string;
|
|
baseUrl?: string;
|
|
queryParam?: string;
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
startBadgeText: undefined,
|
|
endBadgeText: undefined,
|
|
baseUrl: undefined,
|
|
queryParam: "page",
|
|
});
|
|
|
|
const hasStartBadge = computed(() => typeof props.startBadgeText !== "undefined");
|
|
const hasEndBadge = computed(() => typeof props.endBadgeText !== "undefined");
|
|
|
|
const numNumberSteps = computed(
|
|
() => props.steps - Number(hasStartBadge.value) - Number(hasEndBadge.value)
|
|
);
|
|
|
|
function getPillClasses(step: number) {
|
|
if (step + Number(hasStartBadge.value) == props.currentStep) {
|
|
return "bg-sky-500 text-bold";
|
|
} else if (step < props.currentStep) {
|
|
return "bg-green-500";
|
|
}
|
|
return "border";
|
|
}
|
|
|
|
const startBadgeClasses = computed(() => {
|
|
if (0 === props.currentStep) {
|
|
return "bg-sky-500 text-bold";
|
|
}
|
|
return "bg-green-500";
|
|
});
|
|
|
|
const endBadgeClasses = computed(() => {
|
|
if (props.steps === props.currentStep + 1) {
|
|
return "bg-sky-500 text-bold";
|
|
} else if (props.steps === props.currentStep) {
|
|
return "bg-green-500 text-bold";
|
|
}
|
|
return "border";
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex flex-row text-sm">
|
|
<div
|
|
v-if="props.startBadgeText"
|
|
class="inline-flex h-7 items-center justify-center whitespace-nowrap rounded-3xl px-3 text-sm"
|
|
:class="startBadgeClasses"
|
|
>
|
|
<router-link v-if="props.baseUrl" :to="`${props.baseUrl}?${props.queryParam}=0`">
|
|
{{ props.startBadgeText }}
|
|
</router-link>
|
|
<span v-else>{{ props.startBadgeText }}</span>
|
|
</div>
|
|
<div v-for="(_, step) in numNumberSteps" :key="step" class="flex flex-row">
|
|
<hr
|
|
v-if="hasStartBadge || step !== 0"
|
|
class="w-8 self-center border border-gray-400"
|
|
/>
|
|
<div
|
|
class="inline-flex h-7 w-7 items-center justify-center rounded-full px-3 py-1 text-sm"
|
|
:class="getPillClasses(step)"
|
|
>
|
|
<router-link
|
|
v-if="props.baseUrl"
|
|
:to="`${props.baseUrl}?${props.queryParam}=${step + 1}`"
|
|
>
|
|
{{ step + 1 }}
|
|
</router-link>
|
|
<span v-else>{{ step + 1 }}</span>
|
|
</div>
|
|
</div>
|
|
<hr v-if="hasEndBadge" class="w-8 self-center border border-gray-400" />
|
|
<div
|
|
v-if="endBadgeText"
|
|
class="inline-flex h-7 items-center justify-center whitespace-nowrap rounded-3xl px-3 text-sm"
|
|
:class="endBadgeClasses"
|
|
>
|
|
<router-link
|
|
v-if="props.baseUrl"
|
|
:to="`${props.baseUrl}?${props.queryParam}=${steps - 1}`"
|
|
>
|
|
{{ props.endBadgeText }}
|
|
</router-link>
|
|
<span v-else>{{ props.endBadgeText }}</span>
|
|
</div>
|
|
</div>
|
|
</template>
|