feat: update styles
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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'],
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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.');
|
||||||
|
|||||||
@@ -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: '🔚 Ну всё, разгрузили всё, что было. Даже кладовщика разбудить не удалось.',
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -10,5 +10,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
plugins: [require("daisyui")],
|
plugins: [
|
||||||
|
require("daisyui"),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user