Compare commits
2
Commits
217fe01de8
...
5d9fe204e7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5d9fe204e7 | ||
|
|
1ad215e1bf |
Generated
+143
File diff suppressed because one or more lines are too long
+4
@@ -0,0 +1,4 @@
|
||||
<changelist name="Uncommitted_changes_before_Checkout_at_9_21_26,_1_17 PM_[Changes]" date="1789989456881" recycled="true" deleted="true">
|
||||
<option name="PATH" value="$PROJECT_DIR$/.idea/shelf/Uncommitted_changes_before_Checkout_at_9_21_26,_1_17 PM_[Changes]/shelved.patch" />
|
||||
<option name="DESCRIPTION" value="Uncommitted changes before Checkout at 9/21/26, 1:17 PM [Changes]" />
|
||||
</changelist>
|
||||
Generated
+61
-69
@@ -4,11 +4,8 @@
|
||||
<option name="autoReloadType" value="SELECTIVE" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="bb7b50a5-be9c-4cd7-a05b-979f0e91b173" name="Changes" comment="FAZ1">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/components/MobileShowcase.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/components/MobileShowcase.tsx" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/components/ShowcaseSection.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/components/ShowcaseSection.tsx" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/data/commerce.ts" beforeDir="false" afterPath="$PROJECT_DIR$/data/commerce.ts" afterDir="false" />
|
||||
<list default="true" id="bb7b50a5-be9c-4cd7-a05b-979f0e91b173" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/components/HorizontalShowcase.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/components/HorizontalShowcase.tsx" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
@@ -30,61 +27,61 @@
|
||||
</component>
|
||||
<component name="NextEditCompletionFeaturesState">
|
||||
<decayedCancelled>
|
||||
<entry key="MS100" value="1.0" />
|
||||
<entry key="MS500" value="1.0" />
|
||||
<entry key="S2" value="1.0" />
|
||||
<entry key="S5" value="1.0" />
|
||||
<entry key="S10" value="1.0" />
|
||||
<entry key="S30" value="1.0000004701758343" />
|
||||
<entry key="S60" value="1.0028638060052324" />
|
||||
<entry key="M2" value="1.228725374867468" />
|
||||
<entry key="M5" value="4.250728076454436" />
|
||||
<entry key="M10" value="9.057099856689712" />
|
||||
<entry key="M15" value="11.99587061191686" />
|
||||
<entry key="M30" value="16.11837076953653" />
|
||||
<entry key="H1" value="19.010632856516875" />
|
||||
<entry key="H2" value="23.538026208971672" />
|
||||
<entry key="H4" value="33.619941709812636" />
|
||||
<entry key="D1" value="60.82950176199853" />
|
||||
<entry key="W1" value="69.40165249199089" />
|
||||
<entry key="MS100" value="1.028605430515295" />
|
||||
<entry key="MS500" value="2.124649469580447" />
|
||||
<entry key="S2" value="5.757603075779661" />
|
||||
<entry key="S5" value="9.075791406095624" />
|
||||
<entry key="S10" value="11.490304279732543" />
|
||||
<entry key="S30" value="14.544855509715473" />
|
||||
<entry key="S60" value="15.928253142043944" />
|
||||
<entry key="M2" value="17.05794166660894" />
|
||||
<entry key="M5" value="18.240030198039076" />
|
||||
<entry key="M10" value="19.085397144523835" />
|
||||
<entry key="M15" value="19.539401536900623" />
|
||||
<entry key="M30" value="20.15328332293758" />
|
||||
<entry key="H1" value="20.794543104303607" />
|
||||
<entry key="H2" value="24.217320209573487" />
|
||||
<entry key="H4" value="33.81335646745446" />
|
||||
<entry key="D1" value="60.18887647810417" />
|
||||
<entry key="W1" value="68.4601968975454" />
|
||||
</decayedCancelled>
|
||||
<decayedSelected>
|
||||
<entry key="MS100" value="0.0" />
|
||||
<entry key="MS500" value="0.0" />
|
||||
<entry key="S2" value="2.3885730499652336E-137" />
|
||||
<entry key="S5" value="2.2452019521541863E-55" />
|
||||
<entry key="S10" value="4.73835620458634E-28" />
|
||||
<entry key="S30" value="7.79607309213201E-10" />
|
||||
<entry key="S60" value="2.7922225225741823E-5" />
|
||||
<entry key="M2" value="0.005311937671232334" />
|
||||
<entry key="M5" value="0.13786333322655445" />
|
||||
<entry key="M10" value="0.4731691462708206" />
|
||||
<entry key="M15" value="0.744029645841161" />
|
||||
<entry key="M30" value="1.2020499827667592" />
|
||||
<entry key="H1" value="1.5555942142762111" />
|
||||
<entry key="H2" value="1.9040941673772573" />
|
||||
<entry key="H4" value="2.417860494585188" />
|
||||
<entry key="D1" value="3.588294005920995" />
|
||||
<entry key="W1" value="3.9358582269860896" />
|
||||
<entry key="MS500" value="8.699625509373026E-98" />
|
||||
<entry key="S2" value="5.430941684423347E-25" />
|
||||
<entry key="S5" value="1.9676599943042008E-10" />
|
||||
<entry key="S10" value="1.4027330445612952E-5" />
|
||||
<entry key="S30" value="0.02411709586160527" />
|
||||
<entry key="S60" value="0.1553011170701436" />
|
||||
<entry key="M2" value="0.3961550964122234" />
|
||||
<entry key="M5" value="0.7735594310297959" />
|
||||
<entry key="M10" value="1.120827746179152" />
|
||||
<entry key="M15" value="1.3221230513291828" />
|
||||
<entry key="M30" value="1.6023719910246246" />
|
||||
<entry key="H1" value="1.7960429930071773" />
|
||||
<entry key="H2" value="2.045967012949897" />
|
||||
<entry key="H4" value="2.5063189725869783" />
|
||||
<entry key="D1" value="3.6098476224764395" />
|
||||
<entry key="W1" value="3.9392268953128196" />
|
||||
</decayedSelected>
|
||||
<decayedShown>
|
||||
<entry key="MS100" value="0.002107867649422708" />
|
||||
<entry key="MS500" value="0.29158734244711687" />
|
||||
<entry key="S2" value="0.7348389482848886" />
|
||||
<entry key="S5" value="0.8840500779329719" />
|
||||
<entry key="S10" value="0.9402393726774964" />
|
||||
<entry key="S30" value="0.9796697229086149" />
|
||||
<entry key="S60" value="0.99267069237379" />
|
||||
<entry key="M2" value="1.2287187163179756" />
|
||||
<entry key="M5" value="4.385011444628511" />
|
||||
<entry key="M10" value="9.52702268872706" />
|
||||
<entry key="M15" value="12.737053539335015" />
|
||||
<entry key="M30" value="17.318470096071508" />
|
||||
<entry key="H1" value="20.565060675354452" />
|
||||
<entry key="H2" value="25.441441430474942" />
|
||||
<entry key="H4" value="36.03738830839267" />
|
||||
<entry key="D1" value="64.41769767739929" />
|
||||
<entry key="W1" value="73.33749545723742" />
|
||||
<entry key="MS100" value="0.04871208675588815" />
|
||||
<entry key="MS500" value="1.5761328815881446" />
|
||||
<entry key="S2" value="5.568297668845106" />
|
||||
<entry key="S5" value="8.989731845795651" />
|
||||
<entry key="S10" value="11.439232203057065" />
|
||||
<entry key="S30" value="14.54354096178068" />
|
||||
<entry key="S60" value="16.064294199401182" />
|
||||
<entry key="M2" value="17.43942775764285" />
|
||||
<entry key="M5" value="19.00501566584518" />
|
||||
<entry key="M10" value="20.200966633195225" />
|
||||
<entry key="M15" value="20.857682272562908" />
|
||||
<entry key="M30" value="21.753511294575368" />
|
||||
<entry key="H1" value="22.589437021258547" />
|
||||
<entry key="H2" value="26.262649646152585" />
|
||||
<entry key="H4" value="36.319290758304845" />
|
||||
<entry key="D1" value="63.798632595714466" />
|
||||
<entry key="W1" value="72.39940953778996" />
|
||||
</decayedShown>
|
||||
</component>
|
||||
<component name="ProjectColorInfo">{
|
||||
@@ -215,7 +212,9 @@
|
||||
<workItem from="1789618878095" duration="14000" />
|
||||
<workItem from="1789618912128" duration="2222000" />
|
||||
<workItem from="1789622601965" duration="2006000" />
|
||||
<workItem from="1789963664956" duration="1333000" />
|
||||
<workItem from="1789973458932" duration="1450000" />
|
||||
<workItem from="1789981347522" duration="4504000" />
|
||||
<workItem from="1790050380142" duration="326000" />
|
||||
</task>
|
||||
<task id="LOCAL-00001" summary="update">
|
||||
<option name="closed" value="true" />
|
||||
@@ -545,23 +544,15 @@
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1789619546219</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00042" summary="FAZ1">
|
||||
<task id="LOCAL-00042" summary="Improve featured products layout and add support CTA">
|
||||
<option name="closed" value="true" />
|
||||
<created>1789900914642</created>
|
||||
<created>1789974962919</created>
|
||||
<option name="number" value="00042" />
|
||||
<option name="presentableId" value="LOCAL-00042" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1789900914642</updated>
|
||||
<updated>1789974962919</updated>
|
||||
</task>
|
||||
<task id="LOCAL-00043" summary="FAZ1">
|
||||
<option name="closed" value="true" />
|
||||
<created>1789900932562</created>
|
||||
<option name="number" value="00043" />
|
||||
<option name="presentableId" value="LOCAL-00043" />
|
||||
<option name="project" value="LOCAL" />
|
||||
<updated>1789900932562</updated>
|
||||
</task>
|
||||
<option name="localTasksCounter" value="44" />
|
||||
<option name="localTasksCounter" value="43" />
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
@@ -589,6 +580,7 @@
|
||||
<MESSAGE value="chore: format project automatically before starting dev server" />
|
||||
<MESSAGE value="chore: configure prettier for consistent WebStorm formatting" />
|
||||
<MESSAGE value="FAZ1" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="FAZ1" />
|
||||
<MESSAGE value="Improve featured products layout and add support CTA" />
|
||||
<option name="LAST_COMMIT_MESSAGE" value="Improve featured products layout and add support CTA" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,13 +1,10 @@
|
||||
'use client';
|
||||
|
||||
import {useEffect, useRef, useState} from 'react';
|
||||
import Link from 'next/link';
|
||||
import {useEffect, useRef} from 'react';
|
||||
import {gsap} from 'gsap';
|
||||
import {ScrollTrigger} from 'gsap/ScrollTrigger';
|
||||
import VendingCard from './VendingCard';
|
||||
import {showcaseVideoSrc} from '@/data/content';
|
||||
import {featuredMachines} from '@/data/products';
|
||||
import {commerceCopy} from '@/data/commerce';
|
||||
import {useLanguage} from '@/app/context/LanguageContext';
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
@@ -15,35 +12,21 @@ gsap.registerPlugin(ScrollTrigger);
|
||||
export default function HorizontalShowcase() {
|
||||
const sectionRef = useRef<HTMLElement>(null);
|
||||
const trackRef = useRef<HTMLDivElement>(null);
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
const {t, locale} = useLanguage();
|
||||
const copy = commerceCopy[locale];
|
||||
const [videoAvailable, setVideoAvailable] = useState(true);
|
||||
const backgroundRef = useRef<HTMLDivElement>(null);
|
||||
const {t} = useLanguage();
|
||||
|
||||
useEffect(() => {
|
||||
const ctx = gsap.context(() => {
|
||||
const track = trackRef.current;
|
||||
const section = sectionRef.current;
|
||||
const background = backgroundRef.current;
|
||||
|
||||
if (!track || !section) return;
|
||||
|
||||
const scrollDistance = () => Math.max(track.scrollWidth - window.innerWidth, 0);
|
||||
|
||||
let animationFrameId: number | null = null;
|
||||
let latestProgress = 0;
|
||||
|
||||
const syncVideo = (progress: number) => {
|
||||
latestProgress = progress;
|
||||
if (animationFrameId !== null) return;
|
||||
|
||||
animationFrameId = window.requestAnimationFrame(() => {
|
||||
const video = videoRef.current;
|
||||
if (video && Number.isFinite(video.duration) && video.duration > 0) {
|
||||
video.currentTime = latestProgress * video.duration;
|
||||
}
|
||||
animationFrameId = null;
|
||||
});
|
||||
};
|
||||
const backgroundColors = ['#062522', '#0b3d38', '#123d67', '#45235e', '#4a2c18'];
|
||||
const colorAtProgress = (progress: number) => gsap.utils.interpolate(backgroundColors, progress);
|
||||
|
||||
const horizontalTween = gsap.to(track, {
|
||||
x: () => -scrollDistance(),
|
||||
@@ -55,12 +38,16 @@ export default function HorizontalShowcase() {
|
||||
scrub: 1,
|
||||
pin: true,
|
||||
invalidateOnRefresh: true,
|
||||
onUpdate: self => syncVideo(self.progress),
|
||||
onUpdate: self => {
|
||||
if (!background) return;
|
||||
|
||||
background.style.backgroundColor = colorAtProgress(self.progress);
|
||||
background.style.backgroundPosition = `${self.progress * 100}% ${50 + self.progress * 30}%`;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return () => {
|
||||
if (animationFrameId !== null) window.cancelAnimationFrame(animationFrameId);
|
||||
horizontalTween.scrollTrigger?.kill();
|
||||
horizontalTween.kill();
|
||||
};
|
||||
@@ -71,18 +58,16 @@ export default function HorizontalShowcase() {
|
||||
|
||||
return (
|
||||
<section id="showcase" ref={sectionRef} className="relative w-full overflow-hidden">
|
||||
<div className="absolute inset-0 z-0">
|
||||
{videoAvailable && (
|
||||
<video
|
||||
ref={videoRef}
|
||||
src={showcaseVideoSrc}
|
||||
muted
|
||||
playsInline
|
||||
preload="auto"
|
||||
className="w-full h-full object-cover opacity-60"
|
||||
onError={() => setVideoAvailable(false)}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
ref={backgroundRef}
|
||||
className="absolute inset-0 z-0 bg-[#062522] transition-[background-color] duration-300"
|
||||
style={{
|
||||
backgroundImage:
|
||||
'radial-gradient(circle at 18% 22%, rgba(92, 204, 180, 0.42), transparent 31%), radial-gradient(circle at 78% 72%, rgba(255, 177, 92, 0.36), transparent 36%), linear-gradient(125deg, rgba(255,255,255,0.06), transparent 55%)',
|
||||
backgroundSize: '145% 145%, 145% 145%, 100% 100%',
|
||||
backgroundPosition: '0% 50%',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="absolute inset-0"
|
||||
style={{
|
||||
@@ -92,19 +77,10 @@ export default function HorizontalShowcase() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="relative z-20 h-40 pt-20 bg-page-85 backdrop-blur-md">
|
||||
<div className="max-w-7xl h-full mx-auto px-8 flex justify-between items-center gap-4">
|
||||
<h2 className="text-2xl font-bold text-primary">{copy.featuredProducts}</h2>
|
||||
<Link href="/products" className="text-brand-400 hover:underline">
|
||||
{copy.allProducts}
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
ref={trackRef}
|
||||
className="horizontal-track relative z-10 [&_.horizontal-panel]:h-full [&_.spotlight-stage]:max-h-[calc(100vh-12rem)]"
|
||||
style={{height: 'calc(100vh - 10rem)'}}
|
||||
className="horizontal-track relative z-10 [&_.horizontal-panel]:h-full [&_.spotlight-stage]:max-h-[calc(100vh-4rem)]"
|
||||
style={{height: '100vh'}}
|
||||
dir="ltr"
|
||||
>
|
||||
{featuredMachines(t.machines).map(machine => (
|
||||
|
||||
@@ -14,10 +14,7 @@ export default function MobileShowcase() {
|
||||
<section id="showcase" className="relative w-full py-8 px-4" dir={dir}>
|
||||
<div className="flex flex-col gap-4 pb-4">
|
||||
{featuredMachines(t.machines).map(machine => (
|
||||
<article
|
||||
key={machine.id}
|
||||
className="w-full bg-surface border border-subtle rounded-2xl p-4"
|
||||
>
|
||||
<article key={machine.id} className="w-full bg-surface border border-subtle rounded-2xl p-4">
|
||||
<div className="flex gap-4 items-center">
|
||||
{/*<Link href={`/products/${machine.id}`} className="flex gap-4 items-center">*/}
|
||||
<img src={machine.image} alt={machine.name} className="w-24 h-28 object-contain shrink-0" />
|
||||
|
||||
Reference in New Issue
Block a user