Skip to content

Commit 0fd6468

Browse files
committed
carousel enhancements and some dep upgrades
1 parent 712ed18 commit 0fd6468

File tree

11 files changed

+398
-353
lines changed

11 files changed

+398
-353
lines changed

app/globals.css

+24
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,28 @@
3333
100% {
3434
transform: translateX(-50%);
3535
}
36+
}
37+
38+
39+
.swiper-container-borders {
40+
position: relative;
41+
}
42+
43+
.swiper-container-borders::before,
44+
.swiper-container-borders::after {
45+
content: "";
46+
position: absolute;
47+
top: 0;
48+
z-index: 2;
49+
height: 100%;
50+
width: 3px;
51+
background-color: white;
52+
}
53+
54+
.swiper-container-borders::before {
55+
left: 0;
56+
}
57+
58+
.swiper-container-borders::after {
59+
right: 0;
3660
}

app/page.tsx

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
import { SimpleHero } from 'components/hero/simple-hero';
22
import FeaturedItems from 'components/homepage/featured-items-grid';
3+
import { getCollectionProducts } from 'lib/shopify';
34

45
export const metadata = {
5-
description: 'Moda Alternativa.',
6+
description: 'cuatro 52 skateshop',
67
openGraph: {
78
type: 'website'
89
}
910
};
1011

11-
export default function HomePage() {
12+
export default async function HomePage() {
13+
const featuredProducts = await getCollectionProducts({
14+
collection: 'hidden-productos-destacados'
15+
});
1216
return (
1317
<>
14-
<div className="w-full bg-f-green">
18+
<div className="w-full">
1519
<SimpleHero />
1620
</div>
17-
<div className="w-full bg-f-green-light">
18-
<FeaturedItems />
21+
<div className="mx-auto w-full max-w-[1920px] px-4 py-6 md:py-12">
22+
<FeaturedItems products={featuredProducts} />
1923
</div>
20-
{/* <div className="w-full bg-f-green-light">
21-
<Ticker text="Breaking news: This ticker now loops continuously without ever stopping!" />
22-
</div> */}
2324
{/* <Footer /> */}
2425
</>
2526
);

components/cart/actions.ts

+1-9
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,9 @@ export async function updateItemQuantity(
9999
export async function redirectToCheckout() {
100100
let cartId = (await cookies()).get('cartId')?.value;
101101

102-
if (!cartId) {
103-
return 'Missing cart ID';
104-
}
105-
106102
let cart = await getCart(cartId);
107103

108-
if (!cart) {
109-
return 'Error fetching cart';
110-
}
111-
112-
redirect(cart.checkoutUrl);
104+
redirect(cart!.checkoutUrl);
113105
}
114106

115107
export async function createCartAndSetCookie() {

components/ctas/underline/index.tsx

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use client';
2+
3+
import { motion, useAnimationControls } from 'framer-motion';
4+
import Link from 'next/link';
5+
import { ReactNode } from 'react';
6+
7+
interface AnimatedUnderlineLinkProps {
8+
href: string;
9+
children: ReactNode;
10+
className?: string;
11+
}
12+
13+
export default function AnimatedUnderlineLink({
14+
href,
15+
children,
16+
className = ''
17+
}: AnimatedUnderlineLinkProps) {
18+
const controls = useAnimationControls();
19+
20+
return (
21+
<div
22+
className="relative inline-block"
23+
onMouseEnter={() => controls.start({ scaleX: 0 })}
24+
onMouseLeave={() => controls.start({ scaleX: 1 })}
25+
>
26+
<Link href={href} className={className}>
27+
{children}
28+
</Link>
29+
<motion.span
30+
className="absolute bottom-0 left-0 h-[2px] w-full bg-452-blue-light"
31+
initial={{ scaleX: 1 }}
32+
animate={controls}
33+
transition={{ duration: 0.3, ease: 'easeInOut' }}
34+
style={{ originX: 1 }}
35+
/>
36+
</div>
37+
);
38+
}

components/grid/tile.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export function GridTileImage({
2121
<div
2222
className={clsx('group flex h-full w-full items-center justify-center overflow-hidden', {
2323
relative: label,
24-
'border-2 border-f-orange': active,
24+
'border-f-orange border-2': active,
2525
'border-neutral-200': !active
2626
})}
2727
>

components/hero/simple-hero.tsx

+8-6
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ export async function SimpleHero() {
1515
priority={true}
1616
/>
1717
</div>
18-
<div className="absolute bottom-8 left-8 z-10 flex max-w-[90%] flex-col gap-4 md:max-w-[500px]">
19-
<h1 className="font-oswald mb-5 text-3xl font-semibold uppercase leading-9 tracking-wide text-white md:text-5xl md:leading-[1.2]">
20-
Conectando lo mejor del skate en México
21-
</h1>
22-
<div>
23-
<MainCta href="/search">Ver todos los productos</MainCta>
18+
<div className="relative mx-auto w-full max-w-[1920px]">
19+
<div className="absolute bottom-8 left-8 z-10 flex max-w-[90%] flex-col gap-4 md:max-w-[500px]">
20+
<h1 className="mb-5 font-oswald text-3xl font-semibold uppercase leading-9 tracking-wide text-white md:text-5xl md:leading-[1.2]">
21+
Conectando lo mejor del skate en México
22+
</h1>
23+
<div>
24+
<MainCta href="/search">Ver todos los productos</MainCta>
25+
</div>
2426
</div>
2527
</div>
2628
</section>
+83-74
Original file line numberDiff line numberDiff line change
@@ -1,80 +1,89 @@
1-
import { GridTileImage } from 'components/grid/tile';
2-
import { getCollectionProducts } from 'lib/shopify';
3-
import type { Product } from 'lib/shopify/types';
1+
'use client';
2+
3+
import { ArrowLongLeftIcon, ArrowLongRightIcon, ArrowRightIcon } from '@heroicons/react/24/outline';
4+
import UnderlineLink from 'components/ctas/underline';
5+
import Price from 'components/price';
6+
import { Product } from 'lib/shopify/types';
7+
import Image from 'next/image';
48
import Link from 'next/link';
9+
import 'swiper/css';
10+
import 'swiper/css/a11y';
11+
import 'swiper/css/navigation';
12+
import { A11y, Navigation } from 'swiper/modules';
13+
import { Swiper, SwiperSlide } from 'swiper/react';
514

6-
function Item({
7-
item,
8-
size,
9-
priority
10-
}: {
11-
item: Product;
12-
size: 'full' | 'half';
13-
priority?: boolean;
14-
}) {
15+
export default function FeaturedItems({ products }: { products: Product[] }) {
1516
return (
16-
<div
17-
className={size === 'full' ? 'md:col-span-4 md:row-span-2' : 'md:col-span-2 md:row-span-1'}
18-
>
19-
<Link
20-
className="relative block aspect-square h-full w-full"
21-
href={`/product/${item.handle}`}
22-
prefetch={true}
23-
>
24-
<GridTileImage
25-
src={item.featuredImage.url}
26-
fill
27-
sizes={
28-
size === 'full' ? '(min-width: 768px) 66vw, 100vw' : '(min-width: 768px) 33vw, 100vw'
17+
<>
18+
<div className="flex flex-col items-center justify-between pb-4 md:flex-row md:pb-8">
19+
<h2 className="font-oswald text-3xl font-semibold uppercase text-452-blue-light md:text-5xl">
20+
Lo más vendido
21+
</h2>
22+
<UnderlineLink href="search/" className="text-xl uppercase text-452-blue-light">
23+
Ver Todo <ArrowRightIcon className="relative -top-[2px] ml-2 inline-block w-6" />
24+
</UnderlineLink>
25+
</div>
26+
<Swiper
27+
className="swiper-container-borders"
28+
modules={[Navigation, A11y]}
29+
spaceBetween={20}
30+
watchSlidesProgress
31+
slidesPerView={1.25}
32+
breakpoints={{
33+
640: {
34+
slidesPerView: 2.25
35+
},
36+
768: {
37+
slidesPerView: 3.35
38+
},
39+
1024: {
40+
slidesPerView: 4
2941
}
30-
priority={priority}
31-
alt={item.title}
32-
label={{
33-
position: size === 'full' ? 'center' : 'bottom',
34-
title: item.title as string,
35-
amount: item.priceRange.maxVariantPrice.amount,
36-
currencyCode: item.priceRange.maxVariantPrice.currencyCode
37-
}}
38-
/>
39-
</Link>
40-
</div>
41-
);
42-
}
43-
44-
const FeaturedItems = async () => {
45-
const homepageItems = await getCollectionProducts({
46-
collection: 'hidden-homepage-featured-items'
47-
});
48-
49-
if (!homepageItems[0] || !homepageItems[1] || !homepageItems[2]) return null;
50-
51-
const [firstProduct, secondProduct, thirdProduct] = homepageItems;
52-
53-
const menu = Array.from({ length: 3 }, (_, index) => ({
54-
id: index + 1,
55-
name: `Linea ${index + 1}`,
56-
link: `linea/${index + 1}`
57-
}));
58-
return (
59-
<section className="container flex flex-col gap-4 py-4 md:gap-6 md:py-9">
60-
<div className="menu-container mb-6 flex flex-row flex-wrap items-center justify-center gap-4 md:gap-8">
61-
{menu.map((item) => (
62-
<Link
63-
key={item.id}
64-
href={item.link}
65-
className="text-base text-f-orange hover:text-f-orange/80"
66-
>
67-
{item.name}
68-
</Link>
42+
}}
43+
navigation={{
44+
nextEl: '.custom-button-next',
45+
prevEl: '.custom-button-prev'
46+
}}
47+
>
48+
{products.map((product) => (
49+
<SwiperSlide className="border-x-2 border-452-blue-light" key={product.handle}>
50+
<Link className="block" href={`/product/${product.handle}`} prefetch={true}>
51+
<div className="relative aspect-square">
52+
<Image
53+
className="object-cover"
54+
src={product.featuredImage.url}
55+
fill
56+
sizes={
57+
'(min-width: 1024px) 25vw, (min-width: 768px) 33.333vw, (min-width: 640px) 50vw, 100vw'
58+
}
59+
priority={true}
60+
alt={product.title}
61+
/>
62+
</div>
63+
<div className="flex min-h-[10rem] flex-col gap-4 p-4 font-oswald text-base text-452-blue-light md:min-h-[15rem] md:gap-6 lg:text-2xl">
64+
<h3 className="truncate leading-none tracking-wide">{product.title}</h3>
65+
<Price
66+
className="flex-none font-chakra"
67+
amount={product.priceRange.maxVariantPrice.amount}
68+
currencyCode={product.priceRange.maxVariantPrice.currencyCode}
69+
currencyCodeClassName="hidden @[275px]/label:inline"
70+
/>
71+
</div>
72+
</Link>
73+
</SwiperSlide>
6974
))}
70-
</div>
71-
<section className="grid max-w-screen-2xl gap-4 pb-4 md:grid-cols-6 md:grid-rows-2 xl:max-h-[calc(100vh-200px)]">
72-
<Item size="full" item={firstProduct} priority={true} />
73-
<Item size="half" item={secondProduct} priority={true} />
74-
<Item size="half" item={thirdProduct} />
75-
</section>
76-
</section>
75+
<div
76+
className="absolute bottom-0 z-10 flex w-full flex-row justify-between border-y-2 border-452-blue-light py-2"
77+
slot="container-end"
78+
>
79+
<button className="custom-button-prev ml-2 text-452-blue-light disabled:opacity-50 md:ml-4">
80+
<ArrowLongLeftIcon className="w-10" />
81+
</button>
82+
<button className="custom-button-next mr-2 text-452-blue-light disabled:opacity-50 md:mr-4">
83+
<ArrowLongRightIcon className="w-10" />
84+
</button>
85+
</div>
86+
</Swiper>
87+
</>
7788
);
78-
};
79-
80-
export default FeaturedItems;
89+
}

components/label.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const Label = ({
1818
'lg:px-20 lg:pb-[35%]': position === 'center'
1919
})}
2020
>
21-
<div className="font-oswald bg-f-orange/50 text-f-green-light flex items-center rounded-sm p-1 text-sm backdrop-blur-md lg:text-base">
21+
<div className="bg-f-orange/50 text-f-green-light flex items-center rounded-sm p-1 font-honk text-sm backdrop-blur-md lg:text-base">
2222
<h3 className="mr-4 line-clamp-2 flex-grow pl-2 leading-none tracking-tight">{title}</h3>
2323
<Price
2424
className="bg-f-brown-dark/80 flex-none rounded-sm p-2 font-chakra"

package.json

+17-27
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,38 @@
11
{
22
"private": true,
3-
"engines": {
4-
"node": ">=20",
5-
"pnpm": ">=9"
6-
},
73
"scripts": {
8-
"dev": "next dev --turbo",
4+
"dev": "next dev --turbopack",
95
"build": "next build",
106
"start": "next start",
117
"prettier": "prettier --write --ignore-unknown .",
128
"prettier:check": "prettier --check --ignore-unknown .",
139
"test": "pnpm prettier:check"
1410
},
1511
"dependencies": {
16-
"@headlessui/react": "^2.1.2",
17-
"@heroicons/react": "^2.1.5",
12+
"@headlessui/react": "^2.2.0",
13+
"@heroicons/react": "^2.2.0",
1814
"clsx": "^2.1.1",
1915
"framer-motion": "12.0.0-alpha.0",
2016
"geist": "^1.3.1",
21-
"next": "15.0.2",
22-
"react": "19.0.0-rc-0bc30748-20241028",
23-
"react-dom": "19.0.0-rc-0bc30748-20241028",
17+
"next": "15.0.4",
18+
"react": "19.0.0",
19+
"react-dom": "19.0.0",
20+
"sonner": "^1.7.0",
2421
"server-only": "^0.0.1",
25-
"sonner": "^1.5.0",
2622
"swiper": "^11.1.15"
2723
},
2824
"devDependencies": {
2925
"@tailwindcss/container-queries": "^0.1.1",
30-
"@tailwindcss/typography": "^0.5.13",
31-
"@types/node": "20.14.12",
32-
"@types/react": "npm:types-react@19.0.0-rc.1",
33-
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
34-
"autoprefixer": "^10.4.19",
35-
"postcss": "^8.4.39",
36-
"prettier": "3.3.3",
37-
"prettier-plugin-tailwindcss": "^0.6.5",
38-
"tailwindcss": "^3.4.6",
39-
"typescript": "5.5.4"
40-
},
41-
"pnpm": {
42-
"overrides": {
43-
"@types/react": "npm:types-react@19.0.0-rc.1",
44-
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
45-
}
26+
"@tailwindcss/typography": "^0.5.15",
27+
"@types/node": "22.10.1",
28+
"@types/react": "19.0.0",
29+
"@types/react-dom": "19.0.1",
30+
"autoprefixer": "^10.4.20",
31+
"postcss": "^8.4.49",
32+
"prettier": "3.4.2",
33+
"prettier-plugin-tailwindcss": "^0.6.9",
34+
"tailwindcss": "^3.4.16",
35+
"typescript": "5.7.2"
4636
},
4737
"packageManager": "pnpm@9.14.4+sha512.c8180b3fbe4e4bca02c94234717896b5529740a6cbadf19fa78254270403ea2f27d4e1d46a08a0f56c89b63dc8ebfd3ee53326da720273794e6200fcf0d184ab"
4838
}

0 commit comments

Comments
 (0)