update
This commit is contained in:
Generated
+7
-1
@@ -1,7 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="bb7b50a5-be9c-4cd7-a05b-979f0e91b173" name="Changes" comment="update" />
|
<list default="true" id="bb7b50a5-be9c-4cd7-a05b-979f0e91b173" name="Changes" comment="update">
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/app/page.jsx" beforeDir="false" afterPath="$PROJECT_DIR$/app/page.jsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/components/MapSection.jsx" beforeDir="false" afterPath="$PROJECT_DIR$/components/MapSection.jsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/components/VendingCard.jsx" beforeDir="false" afterPath="$PROJECT_DIR$/components/VendingCard.jsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/data/content.js" beforeDir="false" afterPath="$PROJECT_DIR$/data/content.js" afterDir="false" />
|
||||||
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||||
|
|||||||
+3
-3
@@ -33,15 +33,15 @@ export default function HomePage() {
|
|||||||
|
|
||||||
<AboutSection/>
|
<AboutSection/>
|
||||||
|
|
||||||
<CatalogSection/>
|
{/*<CatalogSection/>*/}
|
||||||
|
|
||||||
<LocationsSection/>
|
<LocationsSection/>
|
||||||
|
|
||||||
<IntroVideoSection/>
|
<IntroVideoSection/>
|
||||||
|
|
||||||
<MapSection/>
|
{/*<MapSection/>*/}
|
||||||
|
|
||||||
<TicketForm/>
|
{/*<TicketForm/>*/}
|
||||||
|
|
||||||
<Footer/>
|
<Footer/>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -95,8 +95,7 @@ export default function MapSection() {
|
|||||||
|
|
||||||
<div className="grid lg:grid-cols-[1.3fr,1fr] gap-6">
|
<div className="grid lg:grid-cols-[1.3fr,1fr] gap-6">
|
||||||
<div className="rounded-2xl overflow-hidden border border-subtle h-[360px] lg:h-auto min-h-[360px]">
|
<div className="rounded-2xl overflow-hidden border border-subtle h-[360px] lg:h-auto min-h-[360px]">
|
||||||
{/*<MapThumb coords={pins[0].coords} mapStyle={mapStyle} alt={pins[0].label} />*/}
|
<MapThumb coords={pins[0].coords} mapStyle={mapStyle} alt={pins[0].label}/>
|
||||||
<Image src="/images/map.png" alt="روبات مارکت" width={600} height={600} className={"object-contain"} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
|
|||||||
+108
-105
@@ -3,121 +3,124 @@
|
|||||||
// کارت نمایش هر دستگاه داخل ویترین: شامل جلوه اسپاتلایت (هاور روی عکس دستگاه رنگ جایگزین را نشان میدهد)،
|
// کارت نمایش هر دستگاه داخل ویترین: شامل جلوه اسپاتلایت (هاور روی عکس دستگاه رنگ جایگزین را نشان میدهد)،
|
||||||
// آیتمهای شناور، گیف+توضیحات، و دکمههای افزودن به سبد / مشاهده سریع / علاقهمندی.
|
// آیتمهای شناور، گیف+توضیحات، و دکمههای افزودن به سبد / مشاهده سریع / علاقهمندی.
|
||||||
|
|
||||||
import { useRef, useState } from 'react';
|
import {useRef, useState} from 'react';
|
||||||
import { Button, Tooltip, message } from 'antd';
|
import {Button, Tooltip, message} from 'antd';
|
||||||
import { ShoppingCartOutlined, EyeOutlined, HeartOutlined, HeartFilled } from '@ant-design/icons';
|
import {ShoppingCartOutlined, EyeOutlined, HeartOutlined, HeartFilled} from '@ant-design/icons';
|
||||||
import { useDispatch } from 'react-redux';
|
import {useDispatch} from 'react-redux';
|
||||||
import { addToCart } from '@/store/cartSlice';
|
import {addToCart} from '@/store/cartSlice';
|
||||||
import { useLanguage } from '@/app/context/LanguageContext';
|
import {useLanguage} from '@/app/context/LanguageContext';
|
||||||
import FloatingItems from './FloatingItems';
|
import FloatingItems from './FloatingItems';
|
||||||
import { floatingSnacks } from '@/data/content';
|
import {floatingSnacks} from '@/data/content';
|
||||||
|
|
||||||
export default function VendingCard({ machine, onQuickView }) {
|
export default function VendingCard({machine, onQuickView}) {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { t, dir } = useLanguage();
|
const {t, dir} = useLanguage();
|
||||||
const [wishlisted, setWishlisted] = useState(false);
|
const [wishlisted, setWishlisted] = useState(false);
|
||||||
const stageRef = useRef(null);
|
const stageRef = useRef(null);
|
||||||
const lensRef = useRef(null);
|
const lensRef = useRef(null);
|
||||||
const revealRef = useRef(null);
|
const revealRef = useRef(null);
|
||||||
|
|
||||||
const handleMouseMove = (e) => {
|
const handleMouseMove = (e) => {
|
||||||
const stage = stageRef.current;
|
const stage = stageRef.current;
|
||||||
if (!stage) return;
|
if (!stage) return;
|
||||||
const rect = stage.getBoundingClientRect();
|
const rect = stage.getBoundingClientRect();
|
||||||
const x = e.clientX - rect.left;
|
const x = e.clientX - rect.left;
|
||||||
const y = e.clientY - rect.top;
|
const y = e.clientY - rect.top;
|
||||||
|
|
||||||
if (lensRef.current) {
|
if (lensRef.current) {
|
||||||
lensRef.current.style.transform = `translate(${x}px, ${y}px) translate(-50%, -50%)`;
|
lensRef.current.style.transform = `translate(${x}px, ${y}px) translate(-50%, -50%)`;
|
||||||
}
|
}
|
||||||
if (revealRef.current) {
|
if (revealRef.current) {
|
||||||
revealRef.current.style.clipPath = `circle(95px at ${x}px ${y}px)`;
|
revealRef.current.style.clipPath = `circle(95px at ${x}px ${y}px)`;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseLeave = () => {
|
const handleMouseLeave = () => {
|
||||||
if (revealRef.current) revealRef.current.style.clipPath = 'circle(0px at 50% 50%)';
|
if (revealRef.current) revealRef.current.style.clipPath = 'circle(0px at 50% 50%)';
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddToCart = () => {
|
const handleAddToCart = () => {
|
||||||
dispatch(
|
dispatch(
|
||||||
addToCart({
|
addToCart({
|
||||||
id: machine.id,
|
id: machine.id,
|
||||||
name: machine.name,
|
name: machine.name,
|
||||||
priceNumeric: machine.priceNumeric,
|
priceNumeric: machine.priceNumeric,
|
||||||
priceLabel: machine.priceLabel,
|
priceLabel: machine.priceLabel,
|
||||||
image: machine.image,
|
image: machine.image,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
message.success(t.cart.addToast(machine.name));
|
message.success(t.cart.addToast(machine.name));
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="horizontal-panel flex items-center justify-center px-6 md:px-16" dir={dir}>
|
<div className="horizontal-panel flex items-center justify-center px-6 md:px-16" dir={dir}>
|
||||||
<div className="relative z-10 max-w-6xl w-full grid md:grid-cols-2 gap-10 items-center">
|
<div className="relative z-10 max-w-6xl w-full grid md:grid-cols-2 gap-0 md:gap-10 items-center">
|
||||||
<div
|
<div
|
||||||
ref={stageRef}
|
ref={stageRef}
|
||||||
onMouseMove={handleMouseMove}
|
onMouseMove={handleMouseMove}
|
||||||
onMouseLeave={handleMouseLeave}
|
onMouseLeave={handleMouseLeave}
|
||||||
className="spotlight-stage relative h-[420px] md:h-[560px] flex items-center justify-center"
|
className="spotlight-stage relative h-48 md:h-[500px] flex items-center justify-center"
|
||||||
>
|
>
|
||||||
<FloatingItems items={floatingSnacks} />
|
<FloatingItems items={floatingSnacks}/>
|
||||||
|
|
||||||
<img src={machine.image} alt={machine.name} className="base-layer z-10" />
|
<img src={machine.image} alt={machine.name} className="base-layer z-10"/>
|
||||||
<img
|
<img
|
||||||
ref={revealRef}
|
ref={revealRef}
|
||||||
src={machine.imageAlt}
|
src={machine.imageAlt}
|
||||||
alt={`${machine.name} - ${t.machineActions.altVariant}`}
|
alt={`${machine.name} - ${t.machineActions.altVariant}`}
|
||||||
className="reveal-layer z-20"
|
className="reveal-layer z-20"
|
||||||
/>
|
/>
|
||||||
<div ref={lensRef} className="spotlight-lens" />
|
<div ref={lensRef} className="spotlight-lens"/>
|
||||||
|
|
||||||
<span className="absolute top-3 z-30 text-[11px] px-3 py-1 rounded-full bg-brand/15 border border-subtle text-brand-400 start-3">
|
<span
|
||||||
|
className="absolute hidden md:block top-3 z-30 text-[11px] px-3 py-1 rounded-full bg-brand/15 border border-subtle text-brand-400 start-3">
|
||||||
{t.machineActions.hoverHint}
|
{t.machineActions.hoverHint}
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col justify-center items-center gap-5 ">
|
||||||
|
<span className="text-brand-400 text-sm font-semibold tracking-wide">{machine.shortLabel}</span>
|
||||||
|
<h3 className="text-2xl md:text-4xl font-extrabold text-primary">{machine.name}</h3>
|
||||||
|
|
||||||
|
<div
|
||||||
|
className="grid grid-cols-[auto,1fr] gap-4 items-start bg-surface border border-subtle rounded-2xl p-4">
|
||||||
|
<img
|
||||||
|
src={machine.gif}
|
||||||
|
alt={t.machineActions.gifAlt(machine.name)}
|
||||||
|
className="w-28 h-14 md:w-32 md:h-24 object-cover rounded-lg border border-subtle"
|
||||||
|
/>
|
||||||
|
<p className="text-sm md:text-base text-secondary md:leading-7">{machine.description}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul className="flex flex-wrap gap-2">
|
||||||
|
{machine.highlights.map((h) => (
|
||||||
|
<li key={h}
|
||||||
|
className="text-xs md:text-sm text-brand-400 bg-brand/10 border border-subtle rounded-full px-3 py-1">
|
||||||
|
{h}
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p className="text-xl md:text-2xl font-bold text-primary mt-2">{machine.priceLabel}</p>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap items-center gap-2 mt-2 ">
|
||||||
|
<Button type="primary" size="large" icon={<ShoppingCartOutlined/>} onClick={handleAddToCart}>
|
||||||
|
{t.machineActions.addToCart}
|
||||||
|
</Button>
|
||||||
|
<Button size="large" icon={<EyeOutlined/>} onClick={() => onQuickView?.(machine)}>
|
||||||
|
{t.machineActions.quickView}
|
||||||
|
</Button>
|
||||||
|
{/*<Tooltip title={wishlisted ? t.machineActions.wishlistRemove : t.machineActions.wishlistAdd}>*/}
|
||||||
|
{/* <Button*/}
|
||||||
|
{/* size="large"*/}
|
||||||
|
{/* shape="circle"*/}
|
||||||
|
{/* icon={wishlisted ? <HeartFilled className="text-brand-400"/> : <HeartOutlined/>}*/}
|
||||||
|
{/* onClick={() => setWishlisted((v) => !v)}*/}
|
||||||
|
{/* />*/}
|
||||||
|
{/*</Tooltip>*/}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
);
|
||||||
<div className="flex flex-col gap-5">
|
|
||||||
<span className="text-brand-400 text-sm font-semibold tracking-wide">{machine.shortLabel}</span>
|
|
||||||
<h3 className="text-2xl md:text-4xl font-extrabold text-primary">{machine.name}</h3>
|
|
||||||
|
|
||||||
<div className="grid grid-cols-[auto,1fr] gap-4 items-start bg-surface border border-subtle rounded-2xl p-4">
|
|
||||||
<img
|
|
||||||
src={machine.gif}
|
|
||||||
alt={t.machineActions.gifAlt(machine.name)}
|
|
||||||
className="w-28 h-20 md:w-32 md:h-24 object-cover rounded-lg border border-subtle"
|
|
||||||
/>
|
|
||||||
<p className="text-sm md:text-base text-secondary leading-7">{machine.description}</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<ul className="flex flex-wrap gap-2">
|
|
||||||
{machine.highlights.map((h) => (
|
|
||||||
<li key={h} className="text-xs md:text-sm text-brand-400 bg-brand/10 border border-subtle rounded-full px-3 py-1">
|
|
||||||
{h}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p className="text-xl md:text-2xl font-bold text-primary mt-2">{machine.priceLabel}</p>
|
|
||||||
|
|
||||||
<div className="flex flex-wrap items-center gap-3 mt-2">
|
|
||||||
<Button type="primary" size="large" icon={<ShoppingCartOutlined />} onClick={handleAddToCart}>
|
|
||||||
{t.machineActions.addToCart}
|
|
||||||
</Button>
|
|
||||||
<Button size="large" icon={<EyeOutlined />} onClick={() => onQuickView?.(machine)}>
|
|
||||||
{t.machineActions.quickView}
|
|
||||||
</Button>
|
|
||||||
<Tooltip title={wishlisted ? t.machineActions.wishlistRemove : t.machineActions.wishlistAdd}>
|
|
||||||
<Button
|
|
||||||
size="large"
|
|
||||||
shape="circle"
|
|
||||||
icon={wishlisted ? <HeartFilled className="text-brand-400" /> : <HeartOutlined />}
|
|
||||||
onClick={() => setWishlisted((v) => !v)}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -667,12 +667,12 @@ export const content = {
|
|||||||
|
|
||||||
// Locale-independent asset config (positions/paths only — same in both languages).
|
// Locale-independent asset config (positions/paths only — same in both languages).
|
||||||
export const floatingSnacks = [
|
export const floatingSnacks = [
|
||||||
{id: 'chips-1', image: '/images/snacks/item-1.png', size: 125, top: '5%', left: '-5%', duration: 5.5, delay: 0},
|
{id: 'chips-1', image: '/images/snacks/item-1.png', size: 60, top: '5%', left: '-5%', duration: 5.5, delay: 0},
|
||||||
{id: 'soda-1', image: '/images/snacks/item-2.png', size: 85, top: '68%', left: '2%', duration: 6.2, delay: 0.6},
|
{id: 'soda-1', image: '/images/snacks/item-2.png', size: 55, top: '68%', left: '2%', duration: 6.2, delay: 0.6},
|
||||||
{id: 'chips-2', image: '/images/snacks/item-3.png', size: 95, top: '10%', left: '85%', duration: 4.8, delay: 0.3},
|
{id: 'chips-2', image: '/images/snacks/item-3.png', size: 65, top: '10%', left: '85%', duration: 4.8, delay: 0.3},
|
||||||
{id: 'soda-2', image: '/images/snacks/item-4.png', size: 105, top: '72%', left: '88%', duration: 5.9, delay: 0.9},
|
{id: 'soda-2', image: '/images/snacks/item-4.png', size: 55, top: '72%', left: '88%', duration: 5.9, delay: 0.9},
|
||||||
{id: 'chips-3', image: '/images/snacks/item-5.png', size: 90, top: '42%', left: '90%', duration: 6.6, delay: 1.2},
|
{id: 'chips-3', image: '/images/snacks/item-5.png', size: 50, top: '42%', left: '90%', duration: 6.6, delay: 1.2},
|
||||||
{id: 'soda-3', image: '/images/snacks/item-6.png', size: 95, top: '46%', left: '-4%', duration: 5.1, delay: 1.5},
|
{id: 'soda-3', image: '/images/snacks/item-6.png', size: 55, top: '46%', left: '-4%', duration: 5.1, delay: 1.5},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const showcaseVideoSrc = '/video/showcase-placeholder.mp4';
|
export const showcaseVideoSrc = '/video/showcase-placeholder.mp4';
|
||||||
|
|||||||
Reference in New Issue
Block a user