lint:fix
This commit is contained in:
parent
1adac2836b
commit
83d1faaa38
@ -26,7 +26,7 @@ export default function AddConsultantButton() {
|
|||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
// Устанавливаем флаг навигации чтобы заблокировать повторные нажатия
|
// Устанавливаем флаг навигации чтобы заблокировать повторные нажатия
|
||||||
setIsNavigating(true);
|
setIsNavigating(true);
|
||||||
|
|
||||||
// Переходим на следующую страницу или на главную
|
// Переходим на следующую страницу или на главную
|
||||||
if (navigation.hasNext) {
|
if (navigation.hasNext) {
|
||||||
await navigation.goToNext();
|
await navigation.goToNext();
|
||||||
|
|||||||
@ -23,9 +23,9 @@ export default function AddConsultantPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Progress
|
<Progress
|
||||||
items={progressItems}
|
items={progressItems}
|
||||||
activeItemIndex={navigation.currentIndex}
|
activeItemIndex={navigation.currentIndex}
|
||||||
/>
|
/>
|
||||||
<Typography as="h2" size="xl" weight="semiBold" className={styles.title}>
|
<Typography as="h2" size="xl" weight="semiBold" className={styles.title}>
|
||||||
{t("title")}
|
{t("title")}
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export default function AddGuidesButton() {
|
|||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
// Устанавливаем флаг навигации чтобы заблокировать повторные нажатия
|
// Устанавливаем флаг навигации чтобы заблокировать повторные нажатия
|
||||||
setIsNavigating(true);
|
setIsNavigating(true);
|
||||||
|
|
||||||
// Переходим на следующую страницу или на главную
|
// Переходим на следующую страницу или на главную
|
||||||
if (navigation.hasNext) {
|
if (navigation.hasNext) {
|
||||||
await navigation.goToNext();
|
await navigation.goToNext();
|
||||||
|
|||||||
@ -26,9 +26,9 @@ export default function AddGuidesPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ProductSelectionProvider>
|
<ProductSelectionProvider>
|
||||||
<Progress
|
<Progress
|
||||||
items={progressItems}
|
items={progressItems}
|
||||||
activeItemIndex={navigation.currentIndex}
|
activeItemIndex={navigation.currentIndex}
|
||||||
/>
|
/>
|
||||||
<Typography as="h2" size="xl" weight="semiBold" className={styles.title}>
|
<Typography as="h2" size="xl" weight="semiBold" className={styles.title}>
|
||||||
{t("title")}
|
{t("title")}
|
||||||
|
|||||||
@ -30,11 +30,11 @@ export default function Progress({ items, activeItemIndex }: IProgressProps) {
|
|||||||
// Фиксированные отступы от краев (центр кружочка = 50px от края)
|
// Фиксированные отступы от краев (центр кружочка = 50px от края)
|
||||||
const edgeOffset = 50; // 50px от края до центра кружочка
|
const edgeOffset = 50; // 50px от края до центра кружочка
|
||||||
const totalItems = allItems.length;
|
const totalItems = allItems.length;
|
||||||
|
|
||||||
// Рассчитываем позицию каждого элемента с равными отступами
|
// Рассчитываем позицию каждого элемента с равными отступами
|
||||||
const calculateItemPosition = (index: number) => {
|
const calculateItemPosition = (index: number) => {
|
||||||
if (totalItems === 1) return 50; // Центрируем если один элемент
|
if (totalItems === 1) return 50; // Центрируем если один элемент
|
||||||
|
|
||||||
// Распределяем элементы равномерно между краями
|
// Распределяем элементы равномерно между краями
|
||||||
const availableWidth = containerWidth - (edgeOffset * 2);
|
const availableWidth = containerWidth - (edgeOffset * 2);
|
||||||
const spacing = availableWidth / (totalItems - 1);
|
const spacing = availableWidth / (totalItems - 1);
|
||||||
@ -47,14 +47,14 @@ export default function Progress({ items, activeItemIndex }: IProgressProps) {
|
|||||||
// Находим все элементы прогресс бара
|
// Находим все элементы прогресс бара
|
||||||
const items = elementRef.current.querySelectorAll(`.${styles.item}`);
|
const items = elementRef.current.querySelectorAll(`.${styles.item}`);
|
||||||
let maxHeight = 0;
|
let maxHeight = 0;
|
||||||
|
|
||||||
items.forEach((item) => {
|
items.forEach((item) => {
|
||||||
const height = (item as HTMLElement).offsetHeight;
|
const height = (item as HTMLElement).offsetHeight;
|
||||||
if (height > maxHeight) {
|
if (height > maxHeight) {
|
||||||
maxHeight = height;
|
maxHeight = height;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setContainerHeight(maxHeight);
|
setContainerHeight(maxHeight);
|
||||||
}
|
}
|
||||||
}, [allItems, containerWidth]);
|
}, [allItems, containerWidth]);
|
||||||
@ -79,12 +79,12 @@ export default function Progress({ items, activeItemIndex }: IProgressProps) {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={clsx(styles.stickyWrapper, isScrolled && styles.scrolled)}
|
className={clsx(styles.stickyWrapper, isScrolled && styles.scrolled)}
|
||||||
ref={wrapperRef}
|
ref={wrapperRef}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={styles.container}
|
className={styles.container}
|
||||||
ref={elementRef}
|
ref={elementRef}
|
||||||
style={{
|
style={{
|
||||||
minHeight: containerHeight > 0 ? `${containerHeight}px` : undefined,
|
minHeight: containerHeight > 0 ? `${containerHeight}px` : undefined,
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export default function VideoGuidesButton() {
|
|||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
// Устанавливаем флаг навигации чтобы заблокировать повторные нажатия
|
// Устанавливаем флаг навигации чтобы заблокировать повторные нажатия
|
||||||
setIsNavigating(true);
|
setIsNavigating(true);
|
||||||
|
|
||||||
// Переходим на следующую страницу или на главную
|
// Переходим на следующую страницу или на главную
|
||||||
if (navigation.hasNext) {
|
if (navigation.hasNext) {
|
||||||
await navigation.goToNext();
|
await navigation.goToNext();
|
||||||
|
|||||||
@ -7,10 +7,10 @@ import {
|
|||||||
AdditionalPurchaseBanner,
|
AdditionalPurchaseBanner,
|
||||||
ProductSelectionProvider,
|
ProductSelectionProvider,
|
||||||
Progress,
|
Progress,
|
||||||
|
useMultiPageNavigationContext,
|
||||||
VideoGuidesButton,
|
VideoGuidesButton,
|
||||||
VideoGuidesOffers,
|
VideoGuidesOffers,
|
||||||
VideoGuidesOffersSkeleton,
|
VideoGuidesOffersSkeleton,
|
||||||
useMultiPageNavigationContext,
|
|
||||||
} from "@/components/domains/additional-purchases";
|
} from "@/components/domains/additional-purchases";
|
||||||
import { Typography } from "@/components/ui";
|
import { Typography } from "@/components/ui";
|
||||||
|
|
||||||
@ -27,9 +27,9 @@ export default function VideoGuidesPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ProductSelectionProvider>
|
<ProductSelectionProvider>
|
||||||
<Progress
|
<Progress
|
||||||
items={progressItems}
|
items={progressItems}
|
||||||
activeItemIndex={navigation.currentIndex}
|
activeItemIndex={navigation.currentIndex}
|
||||||
/>
|
/>
|
||||||
<AdditionalPurchaseBanner />
|
<AdditionalPurchaseBanner />
|
||||||
<Typography as="h1" className={styles.title}>
|
<Typography as="h1" className={styles.title}>
|
||||||
|
|||||||
@ -101,7 +101,7 @@ export default function VideoGuideCard(props: VideoGuideCardProps) {
|
|||||||
</Typography>
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
className={styles.buyButton}
|
className={styles.buyButton}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
@ -29,7 +29,7 @@ function VideoGuideCardWrapper({ videoGuide }: { videoGuide: VideoGuide }) {
|
|||||||
const isClickable = videoGuide.isPurchased && videoGuide.videoLink;
|
const isClickable = videoGuide.isPurchased && videoGuide.videoLink;
|
||||||
|
|
||||||
const cardElement = (
|
const cardElement = (
|
||||||
<VideoGuideCard
|
<VideoGuideCard
|
||||||
name={videoGuide.name}
|
name={videoGuide.name}
|
||||||
description={videoGuide.description}
|
description={videoGuide.description}
|
||||||
imageUrl={videoGuide.imageUrl}
|
imageUrl={videoGuide.imageUrl}
|
||||||
@ -46,8 +46,8 @@ function VideoGuideCardWrapper({ videoGuide }: { videoGuide: VideoGuide }) {
|
|||||||
|
|
||||||
if (isClickable) {
|
if (isClickable) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
href={href}
|
href={href}
|
||||||
key={`video-guide-${videoGuide.id}`}
|
key={`video-guide-${videoGuide.id}`}
|
||||||
>
|
>
|
||||||
{cardElement}
|
{cardElement}
|
||||||
@ -69,7 +69,7 @@ export default function VideoGuidesSection({ videoGuides }: VideoGuidesSectionPr
|
|||||||
<Section title="Video Guides" contentClassName={styles.sectionContent}>
|
<Section title="Video Guides" contentClassName={styles.sectionContent}>
|
||||||
<Grid columns={columns} className={styles.grid}>
|
<Grid columns={columns} className={styles.grid}>
|
||||||
{videoGuides.map(videoGuide => (
|
{videoGuides.map(videoGuide => (
|
||||||
<VideoGuideCardWrapper
|
<VideoGuideCardWrapper
|
||||||
key={`video-guide-${videoGuide.id}`}
|
key={`video-guide-${videoGuide.id}`}
|
||||||
videoGuide={videoGuide}
|
videoGuide={videoGuide}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -22,7 +22,7 @@ export default function VideoGuideView({ name, description, videoLink }: VideoGu
|
|||||||
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/,
|
/(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&\n?#]+)/,
|
||||||
/^([a-zA-Z0-9_-]{11})$/ // Direct video ID
|
/^([a-zA-Z0-9_-]{11})$/ // Direct video ID
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const pattern of patterns) {
|
for (const pattern of patterns) {
|
||||||
const match = url.match(pattern);
|
const match = url.match(pattern);
|
||||||
if (match) return match[1];
|
if (match) return match[1];
|
||||||
@ -31,7 +31,7 @@ export default function VideoGuideView({ name, description, videoLink }: VideoGu
|
|||||||
};
|
};
|
||||||
|
|
||||||
const videoId = getYouTubeVideoId(videoLink);
|
const videoId = getYouTubeVideoId(videoLink);
|
||||||
const embedUrl = videoId
|
const embedUrl = videoId
|
||||||
? `https://www.youtube.com/embed/${videoId}?rel=0&modestbranding=1`
|
? `https://www.youtube.com/embed/${videoId}?rel=0&modestbranding=1`
|
||||||
: videoLink;
|
: videoLink;
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ export const loadCompatibility = () =>
|
|||||||
export const loadMeditations = () =>
|
export const loadMeditations = () =>
|
||||||
loadDashboard().then(d => d.meditations || []);
|
loadDashboard().then(d => d.meditations || []);
|
||||||
|
|
||||||
export const loadPalms = () =>
|
export const loadPalms = () =>
|
||||||
loadDashboard().then(d => d.palmActions || []);
|
loadDashboard().then(d => d.palmActions || []);
|
||||||
|
|
||||||
export const loadPortraits = () =>
|
export const loadPortraits = () =>
|
||||||
|
|||||||
@ -42,7 +42,7 @@ export function useVideoGuidePurchase(options: UseVideoGuidePurchaseOptions) {
|
|||||||
startTransition(() => {
|
startTransition(() => {
|
||||||
router.refresh();
|
router.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Убираем наш флаг, но isPending продолжит показывать loader
|
// Убираем наш флаг, но isPending продолжит показывать loader
|
||||||
setIsProcessingPurchase(false);
|
setIsProcessingPurchase(false);
|
||||||
},
|
},
|
||||||
@ -59,10 +59,10 @@ export function useVideoGuidePurchase(options: UseVideoGuidePurchaseOptions) {
|
|||||||
const handlePurchase = useCallback(async () => {
|
const handlePurchase = useCallback(async () => {
|
||||||
// Сначала проверяем, не куплен ли уже продукт
|
// Сначала проверяем, не куплен ли уже продукт
|
||||||
setIsCheckingPurchase(true);
|
setIsCheckingPurchase(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await checkVideoGuidePurchase(productKey);
|
const result = await checkVideoGuidePurchase(productKey);
|
||||||
|
|
||||||
if (result.data && result.data.isPurchased) {
|
if (result.data && result.data.isPurchased) {
|
||||||
// Продукт уже куплен! Показываем сообщение и обновляем страницу
|
// Продукт уже куплен! Показываем сообщение и обновляем страницу
|
||||||
addToast({
|
addToast({
|
||||||
@ -70,26 +70,26 @@ export function useVideoGuidePurchase(options: UseVideoGuidePurchaseOptions) {
|
|||||||
message: "You already own this video guide!",
|
message: "You already own this video guide!",
|
||||||
duration: 3000,
|
duration: 3000,
|
||||||
});
|
});
|
||||||
|
|
||||||
setIsCheckingPurchase(false);
|
setIsCheckingPurchase(false);
|
||||||
|
|
||||||
// Включаем лоадер на всей карточке
|
// Включаем лоадер на всей карточке
|
||||||
setIsProcessingPurchase(true);
|
setIsProcessingPurchase(true);
|
||||||
|
|
||||||
// Даем небольшую задержку для плавного UX
|
// Даем небольшую задержку для плавного UX
|
||||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||||
|
|
||||||
// Обновляем данные dashboard в transition
|
// Обновляем данные dashboard в transition
|
||||||
// isPending будет true пока данные загружаются
|
// isPending будет true пока данные загружаются
|
||||||
startTransition(() => {
|
startTransition(() => {
|
||||||
router.refresh();
|
router.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Убираем наш флаг, но isPending продолжит показывать loader
|
// Убираем наш флаг, но isPending продолжит показывать loader
|
||||||
setIsProcessingPurchase(false);
|
setIsProcessingPurchase(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Продукт не куплен, продолжаем с checkout
|
// Продукт не куплен, продолжаем с checkout
|
||||||
setIsCheckingPurchase(false);
|
setIsCheckingPurchase(false);
|
||||||
handleSingleCheckout({
|
handleSingleCheckout({
|
||||||
@ -99,7 +99,7 @@ export function useVideoGuidePurchase(options: UseVideoGuidePurchaseOptions) {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error checking purchase status:", error);
|
console.error("Error checking purchase status:", error);
|
||||||
setIsCheckingPurchase(false);
|
setIsCheckingPurchase(false);
|
||||||
|
|
||||||
// Даже если проверка не удалась, продолжаем с checkout
|
// Даже если проверка не удалась, продолжаем с checkout
|
||||||
// чтобы не блокировать покупку
|
// чтобы не блокировать покупку
|
||||||
handleSingleCheckout({
|
handleSingleCheckout({
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user