feat: update styles

This commit is contained in:
2025-08-08 17:13:41 +03:00
parent 5f785e82e6
commit ca3a59f43a
11 changed files with 93 additions and 32 deletions

View File

@@ -22,6 +22,8 @@ services:
- XDEBUG_CLIENT_PORT=9003 - XDEBUG_CLIENT_PORT=9003
- XDEBUG_DISCOVER_CLIENT_HOST=false - XDEBUG_DISCOVER_CLIENT_HOST=false
- PHP_IDE_CONFIG=serverName=orbstack - PHP_IDE_CONFIG=serverName=orbstack
- php.session.gc_maxlifetime=28800
- php.session.cookie_lifetime=0
mysql: mysql:
image: mariadb:10.2.7 image: mariadb:10.2.7

View File

@@ -47,7 +47,7 @@ class ImageTool implements ImageToolInterface
$image = $this->manager->make($fullOldPath) $image = $this->manager->make($fullOldPath)
->resize($width, $height, function ($constraint) { ->resize($width, $height, function ($constraint) {
$constraint->aspectRatio(); $constraint->aspectRatio();
$constraint->upsize(); // $constraint->upsize();
}) })
->resizeCanvas($width, $height, 'center', false, null); ->resizeCanvas($width, $height, 'center', false, null);

View File

@@ -57,8 +57,8 @@ class ProductsHandler
$mainpageProducts = $params['mainpageProducts']; $mainpageProducts = $params['mainpageProducts'];
$languageId = 1; $languageId = 1;
$categoryName = ''; $categoryName = '';
$imageWidth = 184; $imageWidth = 300;
$imageHeight = 245; $imageHeight = 300;
if ($categoryId) { if ($categoryId) {
$categoryName = $this->queryBuilder->newQuery() $categoryName = $this->queryBuilder->newQuery()
@@ -243,6 +243,8 @@ class ProductsHandler
$languageId = 1; $languageId = 1;
$imageWidth = 500; $imageWidth = 500;
$imageHeight = 500; $imageHeight = 500;
$imageFullWidth = 1000;
$imageFullHeight = 1000;
$product = $this->queryBuilder->newQuery() $product = $this->queryBuilder->newQuery()
->select([ ->select([
@@ -299,7 +301,7 @@ class ProductsHandler
[$width, $height] = $this->ocImageTool->getRealSize($imagePath); [$width, $height] = $this->ocImageTool->getRealSize($imagePath);
$images[] = [ $images[] = [
'thumbnailURL' => $this->ocImageTool->resize($imagePath, $imageWidth, $imageHeight, 'placeholder.png'), 'thumbnailURL' => $this->ocImageTool->resize($imagePath, $imageWidth, $imageHeight, 'placeholder.png'),
'largeURL' => $this->ocImageTool->getUrl($imagePath), 'largeURL' => $this->ocImageTool->resize($imagePath, $imageFullWidth, $imageFullHeight, 'placeholder.png'),
'width' => $width, 'width' => $width,
'height' => $height, 'height' => $height,
'alt' => $product['product_name'], 'alt' => $product['product_name'],

View File

@@ -1,11 +1,11 @@
<template> <template>
<div class="fixed z-200 top-0 inset-0 flex justify-center align-center flex-col h-full bg-black"> <div class="fullscreen-image-viewer fixed z-200 top-0 inset-0 flex justify-center align-center flex-col h-full bg-black">
<Swiper <Swiper
:zoom="true" :zoom="true"
:navigation="true" :navigation="true"
:pagination="{ :pagination="{
type: 'fraction', type: 'fraction',
}" }"
:activeIndex="activeIndex" :activeIndex="activeIndex"
:modules="[Zoom, Navigation, Pagination]" :modules="[Zoom, Navigation, Pagination]"
class="mySwiper w-full h-full" class="mySwiper w-full h-full"
@@ -13,7 +13,7 @@
> >
<SwiperSlide v-for="image in images"> <SwiperSlide v-for="image in images">
<div class="swiper-zoom-container"> <div class="swiper-zoom-container">
<img :src="image.largeURL" :alt="image.alt"/> <img :src="image.largeURL" :alt="image.alt" class="w-full h-full"/>
</div> </div>
</SwiperSlide> </SwiperSlide>
</Swiper> </Swiper>
@@ -65,3 +65,15 @@ function onClose() {
emits('close'); emits('close');
} }
</script> </script>
<style>
.fullscreen-image-viewer .swiper-button-next,
.fullscreen-image-viewer .swiper-button-prev {
color: white;
mix-blend-mode: difference;
}
.fullscreen-image-viewer .swiper-pagination-fraction {
bottom: calc(var(--tg-safe-area-inset-bottom, 0) + var(--tg-content-safe-area-inset-bottom, 0));
}
</style>

View File

@@ -1,20 +1,24 @@
<template> <template>
<swiper-container ref="swiperEl" pagination="true"> <swiper-container ref="swiperEl" init="false" pagination-dynamic-bullets="true">
<swiper-slide <swiper-slide
v-for="image in images" v-for="image in images"
lazy lazy
class="bg-base-100 overflow-hidden"
style="aspect-ratio:1/1; border-radius:12px;"
> >
<img <img
:src="image.url" :src="image.url"
:alt="image.alt" :alt="image.alt"
loading="lazy" loading="lazy"
class="w-full h-full"
style="object-fit: contain"
/> />
</swiper-slide> </swiper-slide>
</swiper-container> </swiper-container>
</template> </template>
<script setup> <script setup>
import {onMounted, ref} from "vue"; import {onMounted, onUnmounted, ref} from "vue";
const props = defineProps({ const props = defineProps({
images: { images: {
@@ -23,24 +27,30 @@ const props = defineProps({
}, },
}); });
const params = {
injectStyles: [`
.swiper-pagination {
position: relative;
padding-top: 15px;
}
`],
pagination: {
clickable: true,
},
}
const swiperEl = ref(null); const swiperEl = ref(null);
let haptic = true; onUnmounted(() => {
});
onMounted(async () => { onMounted(async () => {
swiperEl.value?.addEventListener('swiperactiveindexchange', (event) => { swiperEl.value?.addEventListener('swiperactiveindexchange', (event) => {
window.Telegram.WebApp.HapticFeedback.selectionChanged(); window.Telegram.WebApp.HapticFeedback.selectionChanged();
}); });
swiperEl.value?.addEventListener('swiperprogress', (num) => { Object.assign(swiperEl.value, params);
if (haptic === false) return; swiperEl.value.initialize();
//window.Telegram.WebApp.HapticFeedback.impactOccurred('light');
haptic = false;
setTimeout(() => haptic = true, 50);
});
swiperEl.value?.addEventListener('swiperreachend', (event) => {
//window.Telegram.WebApp.HapticFeedback.impactOccurred('medium');
});
}); });
</script> </script>

View File

@@ -4,17 +4,17 @@
<div v-if="productsStore.products.data.length > 0"> <div v-if="productsStore.products.data.length > 0">
<div <div
class="grid grid-cols-2 gap-x-6 gap-y-10 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8" class="products-grid grid grid-cols-2 gap-x-5 gap-y-5 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8"
> >
<RouterLink <RouterLink
v-for="product in productsStore.products.data" v-for="product in productsStore.products.data"
:key="product.id" :key="product.id"
class="group" class="product-grid-card group"
:to="`/product/${product.id}`" :to="`/product/${product.id}`"
@click="haptic" @click="haptic"
> >
<ProductImageSwiper :images="product.images"/> <ProductImageSwiper :images="product.images"/>
<h3 class="mt-4 text-sm">{{ product.name }}</h3> <h3 class="product-title mt-4 text-sm">{{ product.name }}</h3>
<p class="mt-1 text-lg font-medium">{{ product.price }}</p> <p class="mt-1 text-lg font-medium">{{ product.price }}</p>
</RouterLink> </RouterLink>
<div ref="bottom" style="height: 1px;"></div> <div ref="bottom" style="height: 1px;"></div>
@@ -134,3 +134,12 @@ onMounted(async () => {
} }
}) })
</script> </script>
<style scoped>
.product-grid-card .product-title {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: var(--product_list_title_max_lines, 3);
overflow: hidden;
}
</style>

View File

@@ -11,7 +11,6 @@ import ApplicationError from "@/ApplicationError.vue";
import AppMetaInitializer from "@/utils/AppMetaInitializer.ts"; import AppMetaInitializer from "@/utils/AppMetaInitializer.ts";
import {injectYaMetrika} from "@/utils/yaMetrika.js"; import {injectYaMetrika} from "@/utils/yaMetrika.js";
import { register } from 'swiper/element/bundle'; import { register } from 'swiper/element/bundle';
import 'swiper/element/bundle'; import 'swiper/element/bundle';
import 'swiper/css/bundle'; import 'swiper/css/bundle';
@@ -44,6 +43,10 @@ settings.load()
document.documentElement.setAttribute('data-theme', settings.theme[this.colorScheme]); document.documentElement.setAttribute('data-theme', settings.theme[this.colorScheme]);
}); });
} }
for (const key in settings.theme.variables) {
document.documentElement.style.setProperty(key, settings.theme.variables[key]);
}
}) })
.then(() => { .then(() => {
console.log('Load front page categories and products.'); console.log('Load front page categories and products.');

View File

@@ -16,6 +16,9 @@ export const useSettingsStore = defineStore('settings', {
theme: { theme: {
light: 'light', light: 'light',
dark: 'dark', dark: 'dark',
variables: {
'--product_list_title_max_lines': 2,
}
}, },
noMoreProductsMessage: '🔚 Ну всё, разгрузили всё, что было. Даже кладовщика разбудить не удалось.', noMoreProductsMessage: '🔚 Ну всё, разгрузили всё, что было. Даже кладовщика разбудить не удалось.',
}), }),

View File

@@ -13,7 +13,7 @@ html {
--swiper-navigation-color: var(--color-primary); --swiper-navigation-color: var(--color-primary);
--swiper-pagination-bullet-inactive-color: var(--color-base-content); --swiper-pagination-bullet-inactive-color: var(--color-base-content);
--swiper-pagination-fraction-color: var(--color-neutral-content); --swiper-pagination-fraction-color: var(--color-neutral-content);
--swiper-pagination-bottom: var(--tg-safe-area-inset-bottom); --product_list_title_max_lines: 1;
} }
.swiper-pagination-bullets { .swiper-pagination-bullets {
@@ -43,4 +43,8 @@ html {
.swiper-pagination-bullets > .swiper-pagination-bullet { .swiper-pagination-bullets > .swiper-pagination-bullet {
background-color: red; background-color: red;
color: red; color: red;
}
.swiper-pagination-bullets {
top: 10px;
} }

View File

@@ -1,9 +1,7 @@
<template> <template>
<div class="pb-10"> <div class="pb-10">
<div> <div>
<swiper-container <swiper-container ref="swiperEl" init="false">
pagination="true"
>
<swiper-slide <swiper-slide
v-for="(image, index) in product.images" v-for="(image, index) in product.images"
lazy="true" lazy="true"
@@ -205,6 +203,8 @@ function onPopState() {
} }
} }
const swiperEl = ref(null);
onUnmounted(() => { onUnmounted(() => {
window.removeEventListener('popstate', onPopState); window.removeEventListener('popstate', onPopState);
}); });
@@ -215,8 +215,7 @@ onMounted(async () => {
window.addEventListener('popstate', onPopState); window.addEventListener('popstate', onPopState);
const swiperEl = document.querySelector('swiper-container'); swiperEl.value.addEventListener('swiperslidermove', (event) => {
swiperEl.addEventListener('swiperslidermove', (event) => {
if (!canVibrate) return; if (!canVibrate) return;
window.Telegram.WebApp.HapticFeedback.impactOccurred('soft'); window.Telegram.WebApp.HapticFeedback.impactOccurred('soft');
canVibrate = false; canVibrate = false;
@@ -224,5 +223,20 @@ onMounted(async () => {
canVibrate = true; canVibrate = true;
}, 50); }, 50);
}); });
Object.assign(swiperEl.value, {
injectStyles: [`
.swiper-pagination {
position: relative;
padding-top: 15px;
}
`],
pagination: {
dynamicBullets: true,
clickable: true,
},
});
swiperEl.value.initialize();
}); });
</script> </script>

View File

@@ -10,5 +10,7 @@ module.exports = {
}, },
}, },
}, },
plugins: [require("daisyui")], plugins: [
require("daisyui"),
],
}; };