Files
webapp/app/pages/index.vue
2026-01-07 09:10:35 +07:00

196 lines
8.3 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<Stack gap="12">
<Section variant="hero">
<Stack gap="6">
<Heading :level="1" tone="inverse">{{ $t('search.title') }}</Heading>
<Text tone="inverse">{{ $t('search.description') }}</Text>
<Card padding="lg">
<Stack gap="6">
<!-- Search form -->
<Grid :cols="1" :md="4" :gap="4">
<Stack gap="2">
<Text tag="p" size="base" weight="semibold">{{ $t('search.product_label') }}</Text>
<FieldButton
:value="searchStore.searchForm.product"
:placeholder="$t('search.product_placeholder')"
@click="navigateTo(localePath('/goods'))"
/>
</Stack>
<Stack gap="2">
<Text tag="p" size="base" weight="semibold">{{ $t('search.quantity_label') }}</Text>
<Input
type="number"
v-model="searchStore.searchForm.quantity"
:placeholder="$t('search.quantity_placeholder')"
/>
</Stack>
<Stack gap="2">
<Text tag="p" size="base" weight="semibold">{{ $t('search.location_label') }}</Text>
<FieldButton
:value="searchStore.searchForm.location"
:placeholder="$t('search.location_placeholder')"
@click="navigateTo(localePath({ path: '/select-location', query: { mode: 'search' } }))"
/>
</Stack>
<Stack gap="2" align="stretch">
<Text tag="p" size="base" weight="semibold" tone="muted"> </Text>
<Button type="button" @click="handleSearch">
{{ searchError ? $t('search.error') : $t('search.search_button') }}
</Button>
</Stack>
</Grid>
</Stack>
</Card>
<Stack v-if="popularExamples.length" gap="2" align="center">
<Text tone="inverse" size="sm">{{ $t('search.popular_requests') }}</Text>
<Stack direction="row" gap="2" justify="center" align="center" class="flex-wrap text-center">
<button
v-for="example in popularExamples"
:key="`${example.product}-${example.location}`"
type="button"
class="badge badge-dash badge-primary text-sm"
@click="fillExample(example)"
>
{{ example.product }} {{ example.quantity }}{{ $t('search.units.tons_short') }} {{ example.location }}
</button>
</Stack>
</Stack>
</Stack>
</Section>
<Section variant="plain">
<Stack gap="8" align="center">
<Heading :level="2">{{ $t('roles.title') }}</Heading>
<Text align="center" tone="muted">{{ $t('about.description') }}</Text>
<Grid :cols="1" :lg="3" :gap="6">
<Card padding="lg">
<Stack gap="4" align="center">
<IconCircle tone="primary">🏭</IconCircle>
<Heading :level="3">{{ $t('roles.producers.title') }}</Heading>
<Text tone="muted" align="center">{{ $t('roles.producers.description') }}</Text>
<Stack tag="ul" gap="1">
<li> {{ $t('roles.producers.benefit1') }}</li>
<li> {{ $t('roles.producers.benefit2') }}</li>
<li> {{ $t('roles.producers.benefit3') }}</li>
<li> {{ $t('roles.producers.benefit4') }}</li>
</Stack>
<Button :full-width="true" variant="outline">{{ $t('roles.producers.cta') }}</Button>
</Stack>
</Card>
<Card padding="lg">
<Stack gap="4" align="center">
<IconCircle tone="primary">🏢</IconCircle>
<Heading :level="3">{{ $t('roles.buyers.title') }}</Heading>
<Text tone="muted" align="center">{{ $t('roles.buyers.description') }}</Text>
<Stack tag="ul" gap="1">
<li> {{ $t('roles.buyers.benefit1') }}</li>
<li> {{ $t('roles.buyers.benefit2') }}</li>
<li> {{ $t('roles.buyers.benefit3') }}</li>
<li> {{ $t('roles.buyers.benefit4') }}</li>
</Stack>
<Button :full-width="true" variant="outline">{{ $t('roles.buyers.cta') }}</Button>
</Stack>
</Card>
<Card padding="lg">
<Stack gap="4" align="center">
<IconCircle tone="primary"></IconCircle>
<Heading :level="3">{{ $t('roles.services.title') }}</Heading>
<Text tone="muted" align="center">{{ $t('roles.services.description') }}</Text>
<Stack tag="ul" gap="1">
<li> {{ $t('roles.services.benefit1') }}</li>
<li> {{ $t('roles.services.benefit2') }}</li>
<li> {{ $t('roles.services.benefit3') }}</li>
<li> {{ $t('roles.services.benefit4') }}</li>
</Stack>
<Button :full-width="true" variant="outline">{{ $t('roles.services.cta') }}</Button>
</Stack>
</Card>
</Grid>
</Stack>
</Section>
<Section variant="plain">
<Stack gap="6" align="center">
<Heading :level="2">{{ $t('howto.title') }}</Heading>
<Grid :cols="1" :md="3" :gap="6">
<Card padding="lg">
<Stack gap="3" align="center">
<IconCircle tone="primary">🔍</IconCircle>
<Heading :level="3" weight="semibold">{{ $t('howto.step1.title') }}</Heading>
<Text tone="muted" align="center">{{ $t('howto.step1.description') }}</Text>
</Stack>
</Card>
<Card padding="lg">
<Stack gap="3" align="center">
<IconCircle tone="primary">🤝</IconCircle>
<Heading :level="3" weight="semibold">{{ $t('howto.step2.title') }}</Heading>
<Text tone="muted" align="center">{{ $t('howto.step2.description') }}</Text>
</Stack>
</Card>
<Card padding="lg">
<Stack gap="3" align="center">
<IconCircle tone="primary"></IconCircle>
<Heading :level="3" weight="semibold">{{ $t('howto.step3.title') }}</Heading>
<Text tone="muted" align="center">{{ $t('howto.step3.description') }}</Text>
</Stack>
</Card>
</Grid>
</Stack>
</Section>
</Stack>
</template>
<script setup>
const { t } = useI18n()
const searchStore = useSearchStore()
const searchError = ref('')
const localePath = useLocalePath()
const popularExamples = computed(() => ([
{ product: t('search.examples.metal_sheet.product'), quantity: 120, location: t('search.examples.metal_sheet.location') },
{ product: t('search.examples.green_coffee.product'), quantity: 200, location: t('search.examples.green_coffee.location') },
{ product: t('search.examples.wheat.product'), quantity: 500, location: t('search.examples.wheat.location') },
{ product: t('search.examples.cocoa.product'), quantity: 150, location: t('search.examples.cocoa.location') },
]))
const handleSearch = () => {
const location = (searchStore.searchForm.location || '').trim()
const productText = (searchStore.searchForm.product || '').trim()
const hasProduct = !!(searchStore.searchForm.productUuid || productText)
if (!location) {
searchError.value = t('search.validation.fill_product_location')
setTimeout(() => (searchError.value = ''), 2000)
return
}
if (!hasProduct) {
navigateTo(localePath('/goods'))
return
}
const query = {
productUuid: searchStore.searchForm.productUuid || undefined,
product: productText || undefined,
quantity: searchStore.searchForm.quantity || undefined,
locationUuid: searchStore.searchForm.locationUuid || undefined,
location: searchStore.searchForm.location || undefined
}
navigateTo(localePath({ path: '/request', query }))
}
const fillExample = (example) => {
searchStore.searchForm.product = example.product
searchStore.searchForm.quantity = example.quantity
searchStore.searchForm.location = example.location
}
</script>