refactor: simplify yclients API integration and improve UI components

remove unused abonements API configuration and endpoints
add escape key handler for drawer component
implement text truncation for service descriptions
sync swiper navigation between service tabs and content
add static gym rental service to services list
This commit is contained in:
Yuu Ottosoka
2025-09-13 20:40:20 +03:00
parent 5eb7407520
commit 2f4e0d59aa
6 changed files with 65 additions and 62 deletions

View File

@@ -1,15 +1,25 @@
import type { servicesSchema } from '@/content.config'
import type { z } from 'astro/zod'
import {
YCLIENTS_TOKEN,
YCLIENTS_API_URL,
YCLIENTS_ABONEMENTS_API_URL,
YCLIENTS_ABONEMENTS_TOKEN,
} from 'astro:env/server'
import { YCLIENTS_TOKEN, YCLIENTS_API_URL } from 'astro:env/server'
type HTML = string
const currencyFormatter = Intl.NumberFormat('ru', { currency: 'rub' })
const RENT_GYM_SERVICE: z.infer<typeof servicesSchema> = {
title: 'Аренда зала',
charachteristics: [
{
title: 'Разовое посещение',
description: 'Разовое посещение студии для самостоятельной тренировки',
price: `${currencyFormatter.format(1500)} ₽`,
link: {
title: 'Записаться',
href: 'https://n1381542.yclients.com/company/1254211/activity/select?o=act',
},
},
],
}
export type YclientsBookinRawResponse = {
category: {
id: number
@@ -57,58 +67,29 @@ const fetcher = <R>(...[path, options = {}]: Parameters<typeof fetch>): Promise<
}).then((res) => res.json() as Promise<R>)
export const yclientsClient = {
getAbonements: (): Promise<z.infer<typeof servicesSchema.shape.charachteristics>> =>
fetcher<YclientsAbonementsRawResponse>(
`${YCLIENTS_ABONEMENTS_API_URL}/chain/1259425/online_sale/loyalty`,
{
method: 'GET',
headers: {
Authorization: `Bearer ${YCLIENTS_ABONEMENTS_TOKEN}`,
},
}
).then((res) =>
res.data.loyalty_abonement_types.map((rawItem) => ({
title: rawItem.online_sale_title,
description: rawItem.online_sale_description,
price: `${currencyFormatter.format(rawItem.online_sale_price)} ₽`,
link: {
title: 'Купить абонемент',
href: `https://o9998.yclients.com/subscriptions/${rawItem.id}`,
},
}))
),
async getServices(): Promise<z.infer<typeof servicesSchema>[]> {
const [booking, abonements] = await Promise.all([
fetcher<YclientsBookinRawResponse>(`${YCLIENTS_API_URL}/book_services/1254211`, {
const booking = await fetcher<YclientsBookinRawResponse>(
`${YCLIENTS_API_URL}/book_services/1254211`,
{
method: 'GET',
}),
this.getAbonements(),
])
}
)
const personalServicesCatergory = booking.category.find((category) => category.id === 18760529)
const abonementsCategory = booking.category.find((category) => category.id === 19562190)
const personalServiceCharachteristics = booking.services
.filter((service) => service.category_id === 18760529)
.map((service) => ({
title: service.title,
price: `${currencyFormatter.format(service.price_min)} ₽`,
description: service.comment,
link: {
title: 'Записаться',
href: `https://n1381542.yclients.com/company/1254211/personal/select-services?o=s${service.id}`,
},
}))
const services = booking.category.map((categoryItem) => ({
title: categoryItem.title,
charachteristics: booking.services
.filter((service) => service.category_id === categoryItem.id)
.map((service) => ({
title: service.title,
price: `${currencyFormatter.format(service.price_min)} ₽`,
description: service.comment,
link: {
title: 'Записаться',
href: `https://n1381542.yclients.com/company/1254211/personal/select-services?o=s${service.id}`,
},
})),
}))
return [
{
title: personalServicesCatergory?.title || '',
charachteristics: personalServiceCharachteristics,
},
{
title: abonementsCategory?.title || '',
charachteristics: abonements,
},
]
return [services[0], RENT_GYM_SERVICE, ...services.slice(1)]
},
}