Files
thebet365/apps/admin/src/components/outright/CountryFlagSelect.vue

154 lines
3.2 KiB
Vue

<script setup lang="ts">
import { computed, ref } from 'vue';
import {
countryFlagUrl,
countryCrestUrl,
countryDisplayName,
countryOptionLabel,
getBuiltinCountry,
hasCountryCrest,
searchBuiltinCountries,
type BuiltinCountry,
} from '../../data/builtinCountries';
import { useAdminLocale } from '../../composables/useAdminLocale';
const props = defineProps<{
modelValue: string;
size?: 'small' | 'default' | 'large';
disabled?: boolean;
hidePreview?: boolean;
}>();
const emit = defineEmits<{
'update:modelValue': [code: string];
pick: [country: BuiltinCountry];
}>();
const { t, locale } = useAdminLocale();
const filterKeyword = ref('');
const options = computed(() => searchBuiltinCountries(filterKeyword.value, locale.value));
const selected = computed(() => getBuiltinCountry(props.modelValue));
function optionLabel(c: BuiltinCountry) {
return countryOptionLabel(c, locale.value);
}
function onFilter(q: string) {
filterKeyword.value = q;
}
function onChange(code: string | undefined) {
const value = code ?? '';
emit('update:modelValue', value);
const country = getBuiltinCountry(value);
if (country) emit('pick', country);
}
</script>
<template>
<div class="country-flag-select">
<el-select
:model-value="modelValue || undefined"
:size="size ?? 'small'"
:disabled="disabled"
filterable
clearable
:filter-method="onFilter"
:placeholder="t('outright.country_ph')"
class="country-select"
@update:model-value="onChange"
@visible-change="(v: boolean) => { if (v) filterKeyword = ''; }"
>
<el-option
v-for="c in options"
:key="c.code"
:label="optionLabel(c)"
:value="c.code"
>
<div class="country-option">
<img :src="countryFlagUrl(c)" alt="" class="country-option-flag" loading="lazy" />
<img
v-if="hasCountryCrest(c)"
:src="countryCrestUrl(c)"
alt=""
class="country-option-crest"
loading="lazy"
/>
<span class="country-option-name">{{ countryDisplayName(c, locale) }}</span>
<span class="country-option-code">{{ c.code }}</span>
</div>
</el-option>
</el-select>
<img
v-if="selected && !hidePreview"
:src="countryFlagUrl(selected)"
alt=""
class="country-preview"
loading="lazy"
/>
</div>
</template>
<style scoped>
.country-flag-select {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
min-width: 0;
}
.country-select {
flex: 1;
min-width: 0;
}
.country-preview {
width: 32px;
height: 22px;
object-fit: cover;
border-radius: 2px;
flex-shrink: 0;
background: #222;
}
.country-option {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.country-option-flag {
width: 24px;
height: 16px;
object-fit: cover;
border-radius: 2px;
flex-shrink: 0;
}
.country-option-crest {
width: 22px;
height: 22px;
object-fit: contain;
flex-shrink: 0;
}
.country-option-name {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 13px;
}
.country-option-code {
font-size: 11px;
color: #888;
flex-shrink: 0;
}
</style>