mirror of
https://github.com/vercel/commerce.git
synced 2025-05-19 07:56:59 +00:00
wip: Saving work
This commit is contained in:
parent
ce40640353
commit
2319ed72db
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
@ -4,6 +4,7 @@ import localFont from 'next/font/local';
|
|||||||
import { ReactNode, Suspense } from 'react';
|
import { ReactNode, Suspense } from 'react';
|
||||||
|
|
||||||
import { LanguageProvider } from 'app/context/language-context';
|
import { LanguageProvider } from 'app/context/language-context';
|
||||||
|
import { getDictionary } from 'dictionaries';
|
||||||
import './globals.css';
|
import './globals.css';
|
||||||
|
|
||||||
const { TWITTER_CREATOR, TWITTER_SITE, SITE_NAME } = process.env;
|
const { TWITTER_CREATOR, TWITTER_SITE, SITE_NAME } = process.env;
|
||||||
@ -38,12 +39,6 @@ const cinzel = localFont({
|
|||||||
variable: '--font-cinzel'
|
variable: '--font-cinzel'
|
||||||
});
|
});
|
||||||
|
|
||||||
const mincho = localFont({
|
|
||||||
src: '../fonts/A-OTF-A1MinchoStd-Bold.otf',
|
|
||||||
display: 'swap',
|
|
||||||
variable: '--font-cinzel'
|
|
||||||
});
|
|
||||||
|
|
||||||
const alpina = localFont({
|
const alpina = localFont({
|
||||||
src: [
|
src: [
|
||||||
{
|
{
|
||||||
@ -60,6 +55,12 @@ const alpina = localFont({
|
|||||||
variable: '--font-alpina'
|
variable: '--font-alpina'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const mincho = localFont({
|
||||||
|
src: '../fonts/A-OTF-A1MinchoStd-Bold.otf',
|
||||||
|
display: 'swap',
|
||||||
|
variable: '--font-mincho'
|
||||||
|
});
|
||||||
|
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
return i18n.locales.map((locale) => ({ lang: locale }));
|
return i18n.locales.map((locale) => ({ lang: locale }));
|
||||||
}
|
}
|
||||||
@ -69,13 +70,15 @@ export default async function RootLayout({
|
|||||||
params
|
params
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
params: { lang: string };
|
params: { lang: Locale };
|
||||||
}) {
|
}) {
|
||||||
|
const dictionary = await getDictionary(params?.lang);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<html lang={params.lang} className={`${cinzel.variable} ${alpina.variable} ${mincho.variable}`}>
|
<html lang={params.lang} className={`${cinzel.variable} ${alpina.variable} ${mincho.variable}`}>
|
||||||
<body className="bg-dark text-white selection:bg-green-800 selection:text-green-400">
|
<body className="bg-dark text-white selection:bg-green-800 selection:text-green-400">
|
||||||
<div className="mx-auto max-w-screen-2xl">
|
<div className="mx-auto max-w-screen-2xl">
|
||||||
<LanguageProvider language={params.lang as Locale}>
|
<LanguageProvider language={params.lang as Locale} dictionary={dictionary}>
|
||||||
<Navbar />
|
<Navbar />
|
||||||
<Suspense>
|
<Suspense>
|
||||||
<main>{children}</main>
|
<main>{children}</main>
|
||||||
|
@ -4,8 +4,7 @@ import Footer from 'components/layout/footer';
|
|||||||
import { LanguageControl } from 'components/layout/navbar/language-control';
|
import { LanguageControl } from 'components/layout/navbar/language-control';
|
||||||
import type { Locale } from '../../i18n-config';
|
import type { Locale } from '../../i18n-config';
|
||||||
|
|
||||||
import Image from 'next/image';
|
import LogoNamemark from 'components/icons/namemark';
|
||||||
import Namemark from 'public/assets/images/namemark.png';
|
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
|
|
||||||
export const runtime = 'edge';
|
export const runtime = 'edge';
|
||||||
@ -20,15 +19,13 @@ export const metadata = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default async function HomePage({ params: { lang } }: { params: { lang: Locale } }) {
|
export default async function HomePage({ params: { lang } }: { params: { lang: Locale } }) {
|
||||||
// const dictionary = await getDictionary(lang);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="invisible absolute right-40 top-12 md:visible">
|
<div className="invisible absolute right-40 top-12 md:visible">
|
||||||
<LanguageControl lang={lang} />
|
<LanguageControl lang={lang} />
|
||||||
</div>
|
</div>
|
||||||
<div className="px-6 pb-12 pt-6 md:pb-48 md:pl-6 md:pt-12">
|
<div className="px-6 pb-12 pt-6 md:pb-48 md:pl-6 md:pt-12">
|
||||||
<Image src={Namemark} alt="suginomori brewery" className="max-w-[260px] md:max-w-[600px]" />
|
<LogoNamemark className="w-[260px] fill-current md:w-[600px]" />
|
||||||
</div>
|
</div>
|
||||||
<ThreeItemGrid lang={lang} />
|
<ThreeItemGrid lang={lang} />
|
||||||
<Suspense>
|
<Suspense>
|
||||||
|
@ -6,24 +6,29 @@ import { ReactNode, createContext, useContext, useState } from 'react';
|
|||||||
interface IContextProps {
|
interface IContextProps {
|
||||||
currentLanguage?: Locale;
|
currentLanguage?: Locale;
|
||||||
setCurrentLanguage: (language: Locale) => void;
|
setCurrentLanguage: (language: Locale) => void;
|
||||||
|
currentDictionary?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LanguageContext = createContext<IContextProps>({} as IContextProps);
|
export const LanguageContext = createContext<IContextProps>({} as IContextProps);
|
||||||
|
|
||||||
export function LanguageProvider({
|
export function LanguageProvider({
|
||||||
language,
|
language,
|
||||||
|
dictionary,
|
||||||
children
|
children
|
||||||
}: {
|
}: {
|
||||||
language: Locale;
|
language: Locale;
|
||||||
|
dictionary?: any;
|
||||||
children: ReactNode | ReactNode[] | string;
|
children: ReactNode | ReactNode[] | string;
|
||||||
}) {
|
}) {
|
||||||
const [currentLanguage, setCurrentLanguage] = useState<Locale>(language || 'en');
|
const [currentLanguage, setCurrentLanguage] = useState<Locale>(language || 'en');
|
||||||
|
const [currentDictionary] = useState<any | undefined>(dictionary);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LanguageContext.Provider
|
<LanguageContext.Provider
|
||||||
value={{
|
value={{
|
||||||
currentLanguage,
|
currentLanguage,
|
||||||
setCurrentLanguage
|
setCurrentLanguage,
|
||||||
|
currentDictionary
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
@ -1,36 +1,35 @@
|
|||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { GridTileImage } from 'components/grid/tile';
|
|
||||||
import { Locale } from 'i18n-config';
|
import { Locale } from 'i18n-config';
|
||||||
import { getCollectionProducts } from 'lib/shopify';
|
import { getCollectionProducts } from 'lib/shopify';
|
||||||
import type { Product } from 'lib/shopify/types';
|
import type { Product } from 'lib/shopify/types';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import Label from '../label';
|
import Label from '../label';
|
||||||
|
import { GridTileImage } from './tile';
|
||||||
|
|
||||||
function ThreeItemGridItem({ item, priority }: { item: Product; priority?: boolean }) {
|
function ThreeItemGridItem({ item, priority }: { item: Product; priority?: boolean }) {
|
||||||
|
const size = item?.variants?.[0]?.selectedOptions?.find((option) => option.name === 'size');
|
||||||
return (
|
return (
|
||||||
<div className={clsx('md:col-span-2 md:row-span-1')}>
|
<div className={clsx('col-span-1 row-span-1 md:col-span-2 md:row-span-1')}>
|
||||||
<Link
|
<Link
|
||||||
className="relative block aspect-bottle h-full w-full overflow-hidden bg-black/30"
|
className="relative block aspect-tall w-full overflow-hidden bg-black/30"
|
||||||
href={`/product/${item.handle}`}
|
href={`/product/${item.handle}`}
|
||||||
>
|
>
|
||||||
<GridTileImage
|
<GridTileImage
|
||||||
src={item.featuredImage.url}
|
src={item.featuredImage.url}
|
||||||
height={1690}
|
|
||||||
width={1192}
|
|
||||||
fill
|
fill
|
||||||
sizes={'(min-width: 768px) 33vw, 100vw'}
|
sizes={'(min-width: 768px) 33vw, 100vw'}
|
||||||
priority={priority}
|
priority={priority}
|
||||||
alt={item.title}
|
alt={item.title}
|
||||||
className="h-full w-full object-cover"
|
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<div className="font-multingual max-w-sm pt-4">
|
<div className="font-multilingual max-w-sm pt-4">
|
||||||
<Label
|
<Label
|
||||||
title={item.title as string}
|
title={item.title as string}
|
||||||
amount={item.priceRange.maxVariantPrice.amount}
|
amount={item.priceRange.maxVariantPrice.amount}
|
||||||
currencyCode={item.priceRange.maxVariantPrice.currencyCode}
|
currencyCode={item.priceRange.maxVariantPrice.currencyCode}
|
||||||
|
size={size?.value}
|
||||||
/>
|
/>
|
||||||
<div className="line-clamp-4 pt-2">{item?.description}</div>
|
<div className="font-regular line-clamp-4 pt-2">{item?.summary?.value}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -52,7 +51,8 @@ export async function ThreeItemGrid({ lang }: { lang: Locale }) {
|
|||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
className={clsx(
|
className={clsx(
|
||||||
'mx-auto grid max-w-screen-2xl gap-6 px-4 pb-4 md:grid-cols-6',
|
'mx-auto grid max-w-screen-2xl gap-6 px-4 pb-4 ',
|
||||||
|
'grid-cols-1 md:grid-cols-6',
|
||||||
'grid-rows-3 md:grid-rows-1'
|
'grid-rows-3 md:grid-rows-1'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
@ -20,7 +20,7 @@ export function GridTileImage({
|
|||||||
{props.src ? (
|
{props.src ? (
|
||||||
// eslint-disable-next-line jsx-a11y/alt-text -- `alt` is inherited from `props`, which is being enforced with TypeScript
|
// eslint-disable-next-line jsx-a11y/alt-text -- `alt` is inherited from `props`, which is being enforced with TypeScript
|
||||||
<Image
|
<Image
|
||||||
className={clsx('h-full w-full object-contain', {
|
className={clsx('h-full w-full object-cover', {
|
||||||
'transition duration-300 ease-in-out hover:scale-105': isInteractive
|
'transition duration-300 ease-in-out hover:scale-105': isInteractive
|
||||||
})}
|
})}
|
||||||
{...props}
|
{...props}
|
||||||
|
34
components/icons/namemark.tsx
Normal file
34
components/icons/namemark.tsx
Normal file
File diff suppressed because one or more lines are too long
@ -4,22 +4,32 @@ import Price from './price';
|
|||||||
const Label = ({
|
const Label = ({
|
||||||
title,
|
title,
|
||||||
amount,
|
amount,
|
||||||
currencyCode
|
currencyCode,
|
||||||
|
size
|
||||||
}: {
|
}: {
|
||||||
title: string;
|
title: string;
|
||||||
amount: string;
|
amount: string;
|
||||||
currencyCode: string;
|
currencyCode: string;
|
||||||
|
size?: string;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<div className={clsx('@container/label')}>
|
<div className={clsx('@container/label')}>
|
||||||
<div className="font-multilingual flex flex-col space-y-2">
|
<div className="font-multilingual flex flex-col space-y-2">
|
||||||
<h3 className="mr-4 line-clamp-2 flex-grow text-3xl">{title}</h3>
|
<h3 className="mr-4 line-clamp-2 flex-grow text-3xl">{title}</h3>
|
||||||
|
<div className="flex flex-row items-center space-x-2">
|
||||||
<Price
|
<Price
|
||||||
className="flex-none"
|
className="flex-none"
|
||||||
amount={amount}
|
amount={amount}
|
||||||
currencyCode={currencyCode}
|
currencyCode={currencyCode}
|
||||||
currencyCodeClassName="hidden @[275px]/label:inline"
|
currencyCodeClassName="hidden @[275px]/label:inline"
|
||||||
/>
|
/>
|
||||||
|
{!!size && (
|
||||||
|
<>
|
||||||
|
<div>/</div>
|
||||||
|
<div>{size}</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -9,7 +9,7 @@ import { Fragment, useRef, useState } from 'react';
|
|||||||
import { LanguageControl } from '../navbar/language-control';
|
import { LanguageControl } from '../navbar/language-control';
|
||||||
|
|
||||||
export function MenuModal() {
|
export function MenuModal() {
|
||||||
const { currentLanguage } = useLanguage();
|
const { currentLanguage, currentDictionary } = useLanguage();
|
||||||
let [isOpen, setIsOpen] = useState(false);
|
let [isOpen, setIsOpen] = useState(false);
|
||||||
let closeButtonRef = useRef(null);
|
let closeButtonRef = useRef(null);
|
||||||
|
|
||||||
@ -43,17 +43,6 @@ export function MenuModal() {
|
|||||||
>
|
>
|
||||||
<div className="fixed inset-0 z-20" />
|
<div className="fixed inset-0 z-20" />
|
||||||
</Transition.Child>
|
</Transition.Child>
|
||||||
<Transition.Child as={Fragment}>
|
|
||||||
<div className="fixed right-5 top-6 z-40 px-2 py-1 md:top-11">
|
|
||||||
<div className="flex flex-row space-x-6">
|
|
||||||
<LanguageControl lang={currentLanguage} />
|
|
||||||
|
|
||||||
<button ref={closeButtonRef} onClick={close} className="">
|
|
||||||
<CloseIcon className="h-10 w-10 stroke-current transition-opacity duration-150 hover:opacity-50" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Transition.Child>
|
|
||||||
|
|
||||||
<Transition.Child
|
<Transition.Child
|
||||||
as={Fragment}
|
as={Fragment}
|
||||||
@ -66,6 +55,16 @@ export function MenuModal() {
|
|||||||
>
|
>
|
||||||
<div className="fixed inset-0 z-30 backdrop-blur-sm">
|
<div className="fixed inset-0 z-30 backdrop-blur-sm">
|
||||||
<Dialog.Panel>
|
<Dialog.Panel>
|
||||||
|
<div className="fixed right-5 top-6 z-40 px-2 py-1 md:top-11">
|
||||||
|
<div className="flex flex-row space-x-6">
|
||||||
|
<LanguageControl lang={currentLanguage} />
|
||||||
|
|
||||||
|
<button ref={closeButtonRef} onClick={close} className="">
|
||||||
|
<CloseIcon className="h-10 w-10 stroke-current transition-opacity duration-150 hover:opacity-50" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="fixed inset-0 grid grid-cols-1 place-content-center bg-dark/80">
|
<div className="fixed inset-0 grid grid-cols-1 place-content-center bg-dark/80">
|
||||||
<div className="flex flex-row justify-end">
|
<div className="flex flex-row justify-end">
|
||||||
<div className="flex flex-col space-y-4 px-6 text-right">
|
<div className="flex flex-col space-y-4 px-6 text-right">
|
||||||
@ -74,7 +73,7 @@ export function MenuModal() {
|
|||||||
href="/products"
|
href="/products"
|
||||||
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
||||||
>
|
>
|
||||||
products
|
{currentDictionary?.menu?.products}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -83,7 +82,7 @@ export function MenuModal() {
|
|||||||
href="/shops"
|
href="/shops"
|
||||||
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
||||||
>
|
>
|
||||||
shop list
|
{currentDictionary?.menu?.shops}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -92,7 +91,7 @@ export function MenuModal() {
|
|||||||
href="/about"
|
href="/about"
|
||||||
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
||||||
>
|
>
|
||||||
about narai
|
{currentDictionary?.menu?.about}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -101,7 +100,7 @@ export function MenuModal() {
|
|||||||
href="/bar"
|
href="/bar"
|
||||||
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
||||||
>
|
>
|
||||||
sagyobar
|
{currentDictionary?.menu?.bar}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -110,7 +109,7 @@ export function MenuModal() {
|
|||||||
href="/concept"
|
href="/concept"
|
||||||
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
||||||
>
|
>
|
||||||
concept
|
{currentDictionary?.menu?.concept}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -119,7 +118,7 @@ export function MenuModal() {
|
|||||||
href="/stories"
|
href="/stories"
|
||||||
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
||||||
>
|
>
|
||||||
stories
|
{currentDictionary?.menu?.stories}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -128,7 +127,7 @@ export function MenuModal() {
|
|||||||
href="/company"
|
href="/company"
|
||||||
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
||||||
>
|
>
|
||||||
company
|
{currentDictionary?.menu?.company}
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -137,6 +136,7 @@ export function MenuModal() {
|
|||||||
href="/contact"
|
href="/contact"
|
||||||
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
className="font-serif text-4xl font-normal transition-opacity duration-150 hover:opacity-50"
|
||||||
>
|
>
|
||||||
|
{currentDictionary?.menu?.contact}
|
||||||
contact
|
contact
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"hello": {
|
"menu": {
|
||||||
"title": "Hello World",
|
"products": "products",
|
||||||
"description": "This is a description"
|
"shops": "shop list",
|
||||||
|
"about": "about narai",
|
||||||
|
"bar": "sagyobar",
|
||||||
|
"concept": "concept",
|
||||||
|
"stories": "stories",
|
||||||
|
"company": "company",
|
||||||
|
"contact": "contact"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
{
|
{
|
||||||
"hello": {
|
"menu": {
|
||||||
"title": "こんにちは",
|
"products": "商品",
|
||||||
"description": "これはせつめいですよ"
|
"shops": "取り扱い店",
|
||||||
|
"about": "naraiについて",
|
||||||
|
"bar": "sagyobar",
|
||||||
|
"concept": "コンセプト",
|
||||||
|
"stories": "ストーリー",
|
||||||
|
"company": "会社概要",
|
||||||
|
"contact": "contact"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@ const productFragment = /* GraphQL */ `
|
|||||||
title
|
title
|
||||||
description
|
description
|
||||||
descriptionHtml
|
descriptionHtml
|
||||||
|
summary: metafield(namespace: "custom", key: "product_summary") {
|
||||||
|
value
|
||||||
|
}
|
||||||
options {
|
options {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
@ -115,6 +115,9 @@ export type ShopifyProduct = {
|
|||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
descriptionHtml: string;
|
descriptionHtml: string;
|
||||||
|
summary: {
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
options: ProductOption[];
|
options: ProductOption[];
|
||||||
priceRange: {
|
priceRange: {
|
||||||
maxVariantPrice: Money;
|
maxVariantPrice: Money;
|
||||||
|
@ -15,7 +15,7 @@ module.exports = {
|
|||||||
japan: ['var(--font-mincho)', 'sans-serif']
|
japan: ['var(--font-mincho)', 'sans-serif']
|
||||||
},
|
},
|
||||||
aspectRatio: {
|
aspectRatio: {
|
||||||
bottle: '1.11'
|
tall: '596 / 845'
|
||||||
},
|
},
|
||||||
keyframes: {
|
keyframes: {
|
||||||
fadeIn: {
|
fadeIn: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user