feat: add fulscreen mode, dark mode

This commit is contained in:
Nikita Kiselev
2025-07-12 10:06:07 +03:00
parent 1e454b8f23
commit 252854e67e
9 changed files with 82 additions and 22 deletions

View File

@@ -55,6 +55,7 @@ class ProductsHandler
}
)
->forPage($page, $perPage)
->orderBy('date_added', 'DESC')
->get();
$productIds = Arr::pluck($products, 'product_id');

View File

@@ -1,14 +1,15 @@
<!doctype html>
<html lang="en">
<html lang="ru">
<head>
<meta charset="UTF-8"/>
<link rel="icon" type="image/svg+xml" href="/vite.svg"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<title>Vite + Vue</title>
</head>
<body>
<div id="app"></div>
<script src="https://telegram.org/js/telegram-web-app.js?58"></script>
<script type="module" src="/src/main.js"></script>
</body>
</html>

12
spa/package-lock.json generated
View File

@@ -11,7 +11,8 @@
"@heroicons/vue": "^2.2.0",
"@tailwindcss/vite": "^4.1.11",
"ofetch": "^1.4.1",
"vue": "^3.5.17"
"vue": "^3.5.17",
"vue-tg": "^0.9.0-beta.10"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.0",
@@ -2089,6 +2090,15 @@
}
}
},
"node_modules/vue-tg": {
"version": "0.9.0-beta.10",
"resolved": "https://registry.npmjs.org/vue-tg/-/vue-tg-0.9.0-beta.10.tgz",
"integrity": "sha512-ymcOZ4bUa1x+2nveAeNaVWiFsl8E7Itudyz4DKxYVwpE7ApZYwO/go9dchTKP4NIUaUDSeRqYro6Cmlh8xhjYA==",
"license": "MIT",
"peerDependencies": {
"vue": "^3"
}
},
"node_modules/yallist": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",

View File

@@ -4,7 +4,7 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --host",
"build": "vite build",
"preview": "vite preview"
},
@@ -12,7 +12,8 @@
"@heroicons/vue": "^2.2.0",
"@tailwindcss/vite": "^4.1.11",
"ofetch": "^1.4.1",
"vue": "^3.5.17"
"vue": "^3.5.17",
"vue-tg": "^0.9.0-beta.10"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.0",

View File

@@ -1,6 +1,8 @@
<template>
<FullscreenViewport v-if="platform === 'ios' && platform === 'android'"/>
<div
class="hero min-h-screen"
class="hero min-h-screen relative"
style="background-image: url(https://img.daisyui.com/images/stock/photo-1507358522600-9f71e620c44e.webp);"
>
<div class="hero-overlay"></div>
@@ -8,7 +10,7 @@
<div class="max-w-md">
<h1 class="mb-5 text-5xl font-bold">Товарняк</h1>
<p class="mb-5">
Магазин, который гордо продаёт то, что другие прячут.
Мы гордо продаём то, что другие боятся.
</p>
<button class="btn btn-primary" @click="scrollToProducts">
Показать товар лицом
@@ -24,6 +26,10 @@
<path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
</svg>
</div>
<div class="absolute text-gray-400 left-3 bottom-3">
{{ platform }}
</div>
</div>
</div>
</div>
@@ -36,13 +42,28 @@
<script setup>
import ProductList from "./components/ProductList.vue";
import {onMounted, ref} from "vue";
import { useWebAppViewport } from 'vue-tg';
import { useMiniApp, FullscreenViewport } from 'vue-tg';
const tg = useMiniApp();
const platform = ref();
platform.value = tg.platform;
// const backButton = useBackButton();
// backButton.show();
const goodsRef = ref();
function scrollToProducts() {
goodsRef.value?.scrollIntoView({ behavior: 'smooth' });
}
const { disableVerticalSwipes } = useWebAppViewport();
disableVerticalSwipes();
onMounted(() => {
window.Telegram?.WebApp?.expand();
})
});
</script>

View File

@@ -1,5 +1,5 @@
<template>
<div class="bg-white">
<div class="bg-base-100">
<div class="mx-auto max-w-2xl px-4 py-16 sm:px-6 sm:py-24 lg:max-w-7xl lg:px-8">
<h2 class="sr-only">Products</h2>
@@ -11,8 +11,8 @@
</div>
</div>
<h3 class="mt-4 text-sm text-gray-700">{{ product.name }}</h3>
<p class="mt-1 text-lg font-medium text-gray-900">{{ product.price }}</p>
<h3 class="mt-4 text-sm">{{ product.name }}</h3>
<p class="mt-1 text-lg font-medium">{{ product.price }}</p>
</a>
</div>
</div>
@@ -22,6 +22,9 @@
<script setup>
import {$fetch} from 'ofetch';
import {onMounted, ref} from "vue";
import { useHapticFeedback } from 'vue-tg';
const hapticFeedback = useHapticFeedback();
const products = ref([]);
@@ -37,14 +40,8 @@ function onScroll(e) {
const delta = Math.abs(scrollLeft - lastScrollLeft);
if (delta > 30) {
hapticFeedback();
hapticFeedback.impactOccurred('soft');
lastScrollLeft = scrollLeft;
}
}
function hapticFeedback(strength = 'light') {
if (window.Telegram.WebApp.version >= '6.1') {
window.Telegram.WebApp.HapticFeedback.impactOccurred(strength);
}
}
</script>

View File

@@ -1,8 +1,27 @@
import { createApp } from 'vue'
import App from './App.vue'
import './style.css'
import { VueTelegramPlugin } from 'vue-tg';
createApp(App).mount('#app')
const tg = window.Telegram.WebApp;
const app = createApp(App);
app.use(VueTelegramPlugin);
app.mount('#app');
import { useMiniApp, useTheme, onThemeChanged } from 'vue-tg';
const theme = useTheme();
const tg = useMiniApp();
onThemeChanged(() => {
// handle theme update
})
theme.onChange(() => {
document.documentElement.setAttribute('data-theme', theme.colorScheme.value);
});
document.documentElement.setAttribute('data-theme', theme.colorScheme.value);
tg.ready();

View File

@@ -1,2 +1,10 @@
@import "tailwindcss";
@plugin "daisyui";
@plugin "daisyui" {
themes: light --default, dark --prefersdark;
}
html, body {
overscroll-behavior-y: none;
-webkit-overflow-scrolling: auto;
}

View File

@@ -14,6 +14,8 @@ export default defineConfig({
},
server: {
host: true,
allowedHosts: ["tg.nikitakiselev.ru"],
proxy: {
'/index.php': {
target: 'http://localhost:8000',