mirror of
https://github.com/vercel/commerce.git
synced 2025-05-19 16:07:01 +00:00
Merge pull request #2 from zenzen-sol/sol/2023-08-23-updates
fix: Various fixes and feedback from previews
This commit is contained in:
commit
40e20fbc2f
@ -1,4 +1,4 @@
|
||||
COMPANY_NAME="Suginomori Brewery"
|
||||
COMPANY_NAME="suginomori brewery"
|
||||
TWITTER_SITE="https://narai.jp"
|
||||
SITE_NAME="suginomori brewery"
|
||||
SHOPIFY_REVALIDATION_SECRET=
|
||||
|
34
.eslintrc.js
34
.eslintrc.js
@ -19,30 +19,30 @@ module.exports = {
|
||||
case: 'kebabCase'
|
||||
}
|
||||
],
|
||||
"prettier/prettier": "warn",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"unused-imports/no-unused-imports": "error",
|
||||
"no-template-curly-in-string": "error",
|
||||
"unused-imports/no-unused-vars": [
|
||||
"warn",
|
||||
'prettier/prettier': 'warn',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'unused-imports/no-unused-imports': 'error',
|
||||
'no-template-curly-in-string': 'error',
|
||||
'unused-imports/no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
"vars": "all",
|
||||
"varsIgnorePattern": "^_",
|
||||
"args": "after-used",
|
||||
"argsIgnorePattern": "^_"
|
||||
vars: 'all',
|
||||
varsIgnorePattern: '^_',
|
||||
args: 'after-used',
|
||||
argsIgnorePattern: '^_'
|
||||
}
|
||||
]
|
||||
},
|
||||
"settings": {
|
||||
"tailwindcss": {
|
||||
"config": "./tailwind.config.js",
|
||||
"callees": ["cx"]
|
||||
settings: {
|
||||
tailwindcss: {
|
||||
config: './tailwind.config.js',
|
||||
callees: ['cx']
|
||||
},
|
||||
"tailwindcss/classnames-order": [
|
||||
'tailwindcss/classnames-order': [
|
||||
true,
|
||||
{
|
||||
"callees": ["cx"],
|
||||
"config": "./tailwind.config.js"
|
||||
callees: ['cx'],
|
||||
config: './tailwind.config.js'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
BIN
.yarn/cache/eslint-plugin-prettier-npm-5.0.0-2f21113cba-84e88744b9.zip
vendored
Normal file
BIN
.yarn/cache/eslint-plugin-prettier-npm-5.0.0-2f21113cba-84e88744b9.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/fast-diff-npm-1.3.0-9f19e3b743-d22d371b99.zip
vendored
Normal file
BIN
.yarn/cache/fast-diff-npm-1.3.0-9f19e3b743-d22d371b99.zip
vendored
Normal file
Binary file not shown.
BIN
.yarn/cache/prettier-linter-helpers-npm-1.0.0-6925131a7e-00ce8011cf.zip
vendored
Normal file
BIN
.yarn/cache/prettier-linter-helpers-npm-1.0.0-6925131a7e-00ce8011cf.zip
vendored
Normal file
Binary file not shown.
68
README.md
68
README.md
@ -80,18 +80,12 @@ Once installed, you'll need to create a `SHOPIFY_STOREFRONT_ACCESS_TOKEN` enviro
|
||||
<summary>Expand to view detailed walkthrough</summary>
|
||||
|
||||
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/apps`.
|
||||
1. Click the green `Shopify App Store` button.
|
||||

|
||||
1. Search for `Headless` and click on the `Headless` app.
|
||||

|
||||
1. Click the black `Add app` button.
|
||||

|
||||
1. Click the green `Add sales channel` button.
|
||||

|
||||
1. Click the green `Create storefront` button.
|
||||

|
||||
1. Copy and paste the public access token and assign it to a `SHOPIFY_STOREFRONT_ACCESS_TOKEN` environment variable.
|
||||

|
||||
1. Click the green `Shopify App Store` button. 
|
||||
1. Search for `Headless` and click on the `Headless` app. 
|
||||
1. Click the black `Add app` button. 
|
||||
1. Click the green `Add sales channel` button. 
|
||||
1. Click the green `Create storefront` button. 
|
||||
1. Copy and paste the public access token and assign it to a `SHOPIFY_STOREFRONT_ACCESS_TOKEN` environment variable. 
|
||||
1. If you ever need to reference the public access token again, you can navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/headless_storefronts`.
|
||||
</details>
|
||||
|
||||
@ -106,21 +100,14 @@ Follow the installation instructions and configure the theme with your headless
|
||||
<details>
|
||||
<summary>Expand to view detailed walkthrough</summary>
|
||||
|
||||
1. Download [Shopify Headless Theme](https://github.com/instantcommerce/shopify-headless-theme).
|
||||

|
||||
1. Download [Shopify Headless Theme](https://github.com/instantcommerce/shopify-headless-theme). 
|
||||
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/themes`.
|
||||
1. Click `Add theme`, then `Upload zip file`.
|
||||

|
||||
1. Select the downloaded zip file from above, and click the green `Upload file` button.
|
||||

|
||||
1. Click `Customize`.
|
||||

|
||||
1. Click `Theme settings` (ie. the paintbrush icon), expand the `STOREFRONT` section, enter your headless store domain, click the gray `Publish` button.
|
||||

|
||||
1. Confirm the theme change by clicking the green `Save and publish` button.
|
||||

|
||||
1. The headless theme should now be your current active theme.
|
||||

|
||||
1. Click `Add theme`, then `Upload zip file`. 
|
||||
1. Select the downloaded zip file from above, and click the green `Upload file` button. 
|
||||
1. Click `Customize`. 
|
||||
1. Click `Theme settings` (ie. the paintbrush icon), expand the `STOREFRONT` section, enter your headless store domain, click the gray `Publish` button. 
|
||||
1. Confirm the theme change by clicking the green `Save and publish` button. 
|
||||
1. The headless theme should now be your current active theme. 
|
||||
</details>
|
||||
|
||||
### Branding & Design
|
||||
@ -141,27 +128,21 @@ You can use Shopify's admin to customize these pages to match your brand and des
|
||||
#### Checkout, order status, and order history
|
||||
|
||||
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/checkout`.
|
||||
1. Click the green `Customize` button.
|
||||

|
||||
1. Click `Branding` (ie. the paintbrush icon) and customize your brand. Please note, there are three steps / pages to the checkout flow. Use the dropdown to change pages and adjust branding as needed on each page. Click `Save` when you are done.
|
||||

|
||||
1. Click the green `Customize` button. 
|
||||
1. Click `Branding` (ie. the paintbrush icon) and customize your brand. Please note, there are three steps / pages to the checkout flow. Use the dropdown to change pages and adjust branding as needed on each page. Click `Save` when you are done. 
|
||||
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/branding`.
|
||||
1. Customize settings to match your brand.
|
||||

|
||||
1. Customize settings to match your brand. 
|
||||
|
||||
#### Emails
|
||||
|
||||
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/email_settings`.
|
||||
1. Customize settings to match your brand.
|
||||

|
||||
1. Customize settings to match your brand. 
|
||||
|
||||
#### Favicon
|
||||
|
||||
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/themes`.
|
||||
1. Click the green `Customize` button.
|
||||

|
||||
1. Click `Theme settings` (ie. the paintbrush icon), expand the `FAVICON` section, upload favicon, then click the `Save` button.
|
||||

|
||||
1. Click the green `Customize` button. 
|
||||
1. Click `Theme settings` (ie. the paintbrush icon), expand the `FAVICON` section, upload favicon, then click the `Save` button. 
|
||||
|
||||
</details>
|
||||
|
||||
@ -189,9 +170,7 @@ Next.js is pre-configured to listen for the following Shopify webhook events and
|
||||
#### Configure Shopify webhooks
|
||||
|
||||
1. Navigate to `https://[your-shopify-store-subdomain].myshopify.com/admin/settings/notifications`.
|
||||
1. Add webhooks for all six event topics listed above. You can add more sets for other preview urls, environments, or local development. Append `?secret=[SECRET]` to each url, where `[SECRET]` is the secret you created above.
|
||||

|
||||

|
||||
1. Add webhooks for all six event topics listed above. You can add more sets for other preview urls, environments, or local development. Append `?secret=[SECRET]` to each url, where `[SECRET]` is the secret you created above.  
|
||||
|
||||
#### Testing webhooks during local development
|
||||
|
||||
@ -200,11 +179,8 @@ The easiest way to test webhooks while developing locally is to use [ngrok](http
|
||||
1. [Install and configure ngrok](https://ngrok.com/download) (you will need to create an account).
|
||||
1. Run your app locally, `npm run dev`.
|
||||
1. In a separate terminal session, run `ngrok http 3000`.
|
||||
1. Use the url generated by ngrok and add or update your webhook urls in Shopify.
|
||||

|
||||

|
||||
1. You can now make changes to your store and your local app should receive updates. You can also use the `Send test notification` button to trigger a generic webhook test.
|
||||

|
||||
1. Use the url generated by ngrok and add or update your webhook urls in Shopify.  
|
||||
1. You can now make changes to your store and your local app should receive updates. You can also use the `Send test notification` button to trigger a generic webhook test. 
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -16,12 +16,12 @@ export default function AboutNaraiDetail({ awards }: { awards: string }) {
|
||||
|
||||
return (
|
||||
<div className="w-full px-6">
|
||||
<div className="font-multilingual flex w-full flex-col items-center space-y-2 pb-24 text-center font-extralight md:pb-48">
|
||||
<div className="font-multilingual flex w-full flex-col items-center space-y-px pb-24 text-center font-extralight md:pb-48">
|
||||
<h1 className="text-6xl">{t('about.001.title')}</h1>
|
||||
<h1 className="text-6xl">{t('about.001.subtitle')}</h1>
|
||||
</div>
|
||||
|
||||
<div className="max-w-screen-2x relative mx-auto">
|
||||
<div className="relative mx-auto max-w-screen-2xl">
|
||||
<Image
|
||||
src={AboutImage001}
|
||||
priority={true}
|
||||
@ -39,7 +39,7 @@ export default function AboutNaraiDetail({ awards }: { awards: string }) {
|
||||
<p className="text-base leading-loose">{t('about.002.para002')}</p>
|
||||
</div>
|
||||
|
||||
<div className="max-w-screen-2x relative mx-auto">
|
||||
<div className="relative mx-auto max-w-screen-2xl">
|
||||
<Image
|
||||
src={AboutImage002}
|
||||
priority={true}
|
||||
@ -78,7 +78,7 @@ export default function AboutNaraiDetail({ awards }: { awards: string }) {
|
||||
>
|
||||
<div className="font-multilingual flex flex-row items-baseline space-x-4">
|
||||
<h2 className="text-5xl">{t('about.awards.title')}</h2>
|
||||
<h3 className="text-2xl font-extralight">{t('about.awards.subtitle')}</h3>
|
||||
<h3 className="text-xl font-extralight">{t('about.awards.subtitle')}</h3>
|
||||
</div>
|
||||
|
||||
<div className="border-y border-white/20 py-12">
|
||||
@ -94,7 +94,10 @@ export default function AboutNaraiDetail({ awards }: { awards: string }) {
|
||||
>
|
||||
<div className="flex flex-col space-y-24">
|
||||
<div className="font-multilingual font-extralight">
|
||||
<h2 className="text-5xl">{t('about.materials.title')}</h2>
|
||||
<div className="flex flex-row items-baseline space-x-3">
|
||||
<h2 className="text-5xl">{t('about.materials.title')}</h2>
|
||||
<h2 className="text-4xl">{t('about.materials.subtitle')}</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Image
|
||||
@ -106,10 +109,12 @@ export default function AboutNaraiDetail({ awards }: { awards: string }) {
|
||||
|
||||
<div className="font-multilingual flex flex-col space-y-12 font-extralight md:flex-row md:space-x-6 md:space-y-0">
|
||||
<div className="md:w-1/2">
|
||||
<h2 className="max-w-sm text-5xl">{t('about.materials.water.title')}</h2>
|
||||
<h2 className="max-w-title text-3xl leading-normal">
|
||||
{t('about.materials.water.title')}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="md:w-1/2">
|
||||
<p className="text-xl leading-relaxed">{t('about.materials.water.body')}</p>
|
||||
<p className="text-base leading-relaxed">{t('about.materials.water.body')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -124,10 +129,12 @@ export default function AboutNaraiDetail({ awards }: { awards: string }) {
|
||||
|
||||
<div className="font-multilingual flex flex-col space-y-12 font-extralight md:flex-row md:space-x-6 md:space-y-0">
|
||||
<div className="md:w-1/2">
|
||||
<h2 className="max-w-sm text-5xl">{t('about.materials.rice.title')}</h2>
|
||||
<h2 className="max-w-title text-3xl leading-normal">
|
||||
{t('about.materials.rice.title')}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="md:w-1/2">
|
||||
<p className="text-xl leading-relaxed">{t('about.materials.rice.body')}</p>
|
||||
<p className="text-base leading-relaxed">{t('about.materials.rice.body')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -142,10 +149,12 @@ export default function AboutNaraiDetail({ awards }: { awards: string }) {
|
||||
|
||||
<div className="font-multilingual flex flex-col space-y-12 font-extralight md:flex-row md:space-x-6 md:space-y-0">
|
||||
<div className="md:w-1/2">
|
||||
<h2 className="max-w-sm text-5xl">{t('about.materials.koji.title')}</h2>
|
||||
<h2 className="max-w-title text-3xl leading-normal">
|
||||
{t('about.materials.koji.title')}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="md:w-1/2">
|
||||
<p className="text-xl leading-relaxed">{t('about.materials.koji.body')}</p>
|
||||
<p className="text-base leading-relaxed">{t('about.materials.koji.body')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -156,8 +165,8 @@ export default function AboutNaraiDetail({ awards }: { awards: string }) {
|
||||
<div className="border-t border-white/20"></div>
|
||||
</div>
|
||||
<div className="font-multilingual max-w-xl font-extralight">
|
||||
<p className="text-xl">{t('about.irie.title')}</p>
|
||||
<p className="text-xl leading-relaxed">{t('about.irie.body')}</p>
|
||||
<p className="text-lg">{t('about.irie.title')}</p>
|
||||
<p className="text-lg leading-relaxed">{t('about.irie.body')}</p>
|
||||
</div>
|
||||
|
||||
<Image
|
||||
|
@ -15,7 +15,7 @@ export default function SagyobarDetail() {
|
||||
|
||||
return (
|
||||
<div className="w-full px-6">
|
||||
<div className="max-w-screen-2x relative mx-auto">
|
||||
<div className="relative mx-auto max-w-screen-2xl">
|
||||
<Image
|
||||
src={BarImage001}
|
||||
priority={true}
|
||||
@ -29,9 +29,10 @@ export default function SagyobarDetail() {
|
||||
'font-multilingual mx-auto flex w-full flex-col space-y-12 py-12 text-left font-extralight md:flex-row md:space-x-6 md:space-y-0 md:py-24 md:pb-24'
|
||||
)}
|
||||
>
|
||||
<div className="md:w-1/2">
|
||||
<h2 className="max-w-sm text-4xl md:text-5xl">{t('bar.001.title')}</h2>
|
||||
<h2 className="max-w-sm text-4xl md:text-5xl">{t('bar.001.subtitle')}</h2>
|
||||
<div className="flex flex-col space-y-4 md:w-1/2">
|
||||
<h2 className="max-w-sm text-4xl md:text-5xl">{t('bar.001.title.line001')}</h2>
|
||||
<h2 className="max-w-sm text-4xl md:text-5xl">{t('bar.001.title.line002')}</h2>
|
||||
<h2 className="max-w-sm text-4xl md:text-5xl">{t('bar.001.title.line003')}</h2>
|
||||
</div>
|
||||
<div className="flex flex-col space-y-12 md:w-1/2">
|
||||
<p className="text-base leading-loose">{t('bar.001.para001')}</p>
|
||||
@ -39,7 +40,7 @@ export default function SagyobarDetail() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="max-w-screen-2x relative mx-auto flex flex-col space-y-24">
|
||||
<div className="relative mx-auto flex max-w-screen-2xl flex-col space-y-24">
|
||||
<Image
|
||||
src={BarImage002}
|
||||
priority={true}
|
||||
@ -95,13 +96,13 @@ export default function SagyobarDetail() {
|
||||
<div className="h-4 w-4 rounded-full bg-white"></div>
|
||||
<p className="text-xl">{t('bar.access.title')}</p>
|
||||
</div>
|
||||
<p className="text-base leading-relaxed">{t('bar.access.para001')}</p>
|
||||
<p className="text-base leading-relaxed">{t('bar.access.para002')}</p>
|
||||
<p className="text-base leading-relaxed">{t('bar.access.para003')}</p>
|
||||
<p className="text-base leading-relaxed">{t('bar.access.para004')}</p>
|
||||
<p className="text-base leading-relaxed">{t('bar.access.para005')}</p>
|
||||
<p className="text-base leading-relaxed">{t('bar.access.para006')}</p>
|
||||
<p className="text-base leading-relaxed">{t('bar.access.para007')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.access.para001')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.access.para002')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.access.para003')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.access.para004')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.access.para005')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.access.para006')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.access.para007')}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -111,9 +112,9 @@ export default function SagyobarDetail() {
|
||||
<div className="h-4 w-4 rounded-full bg-white"></div>
|
||||
<p className="text-xl">{t('bar.hours.title')}</p>
|
||||
</div>
|
||||
<p className="pb-6 text-base leading-relaxed">{t('bar.hours.para001')}</p>
|
||||
<p className="text-base leading-relaxed">{t('bar.hours.para002')}</p>
|
||||
<p className="text-base leading-relaxed">{t('bar.hours.para003')}</p>
|
||||
<p className="pb-6 text-[15px] leading-relaxed">{t('bar.hours.para001')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.hours.para002')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.hours.para003')}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -123,8 +124,11 @@ export default function SagyobarDetail() {
|
||||
<div className="h-4 w-4 rounded-full bg-white"></div>
|
||||
<p className="text-xl">{t('bar.menu.title')}</p>
|
||||
</div>
|
||||
<p className="pb-6 text-base leading-relaxed">
|
||||
<Link href="/menu" className="transition-opacity duration-150 hover:opacity-90">
|
||||
<p className="pb-6 text-[15px] leading-relaxed">
|
||||
<Link
|
||||
href="https://cdn.shopify.com/s/files/1/0578/5570/5261/files/sagyobar_menu.pdf?v=1692861259"
|
||||
className="transition-opacity duration-150 hover:opacity-90"
|
||||
>
|
||||
{t('bar.menu.para001')}
|
||||
</Link>
|
||||
</p>
|
||||
@ -136,8 +140,8 @@ export default function SagyobarDetail() {
|
||||
<div className="border-t border-white/20"></div>
|
||||
</div>
|
||||
<div className="font-multilingual max-w-xl font-extralight">
|
||||
<p className="text-xl">{t('bar.clerk.title')}</p>
|
||||
<p className="text-xl leading-relaxed">{t('bar.clerk.body')}</p>
|
||||
<p className="text-[15px]">{t('bar.clerk.title')}</p>
|
||||
<p className="text-[15px] leading-relaxed">{t('bar.clerk.body')}</p>
|
||||
</div>
|
||||
|
||||
<Image
|
||||
|
@ -30,7 +30,7 @@ export default function CompanyDetail() {
|
||||
|
||||
<div>
|
||||
<h3 className="text-2xl">{t('company.subtitle001')}</h3>
|
||||
<ul className="font-multilingual flex flex-col space-y-4 py-4 text-xl font-extralight">
|
||||
<ul className="font-multilingual flex flex-col space-y-4 py-4 text-base font-extralight">
|
||||
<li className="border-t border-white/20 py-4">
|
||||
<div className="flex flex-col space-y-2 md:flex-row md:space-x-3 md:space-y-0">
|
||||
<div className="w-1/3">{t('company.name.label')}</div>
|
||||
@ -67,7 +67,7 @@ export default function CompanyDetail() {
|
||||
<div>
|
||||
<h3 className="pb-4 text-2xl">{t('company.subtitle002')}</h3>
|
||||
<div className="grid grid-cols-1 gap-4 border-t border-white/20 md:grid-cols-3">
|
||||
<div className="font-multilingual col-span-1 py-4 text-lg font-extralight">
|
||||
<div className="font-multilingual col-span-1 py-4 text-base font-extralight">
|
||||
<div className="relative aspect-square">
|
||||
<Image
|
||||
src={CompanyImage001}
|
||||
@ -78,7 +78,7 @@ export default function CompanyDetail() {
|
||||
</div>
|
||||
<div className="pt-2">{t('company.irie.japanese')}</div>
|
||||
<div className="pb-4">{t('company.irie.english')}</div>
|
||||
<div className="text-base">{t('company.irie.role')}</div>
|
||||
<div className="text-sm">{t('company.irie.role')}</div>
|
||||
</div>
|
||||
|
||||
<div className="font-multilingual col-span-1 py-4 text-lg font-extralight">
|
||||
@ -92,7 +92,7 @@ export default function CompanyDetail() {
|
||||
</div>
|
||||
<div className="pt-2">{t('company.nishikawa.japanese')}</div>
|
||||
<div className="pb-4">{t('company.nishikawa.english')}</div>
|
||||
<div className="text-base">{t('company.nishikawa.role')}</div>
|
||||
<div className="text-sm">{t('company.nishikawa.role')}</div>
|
||||
</div>
|
||||
|
||||
<div className="font-multilingual col-span-1 py-4 text-lg font-extralight">
|
||||
@ -106,7 +106,7 @@ export default function CompanyDetail() {
|
||||
</div>
|
||||
<div className="pt-2">{t('company.sundberg.japanese')}</div>
|
||||
<div className="pb-4">{t('company.sundberg.english')}</div>
|
||||
<div className="text-base">{t('company.sundberg.role')}</div>
|
||||
<div className="text-sm">{t('company.sundberg.role')}</div>
|
||||
</div>
|
||||
|
||||
<div className="font-multilingual col-span-1 py-4 text-lg font-extralight">
|
||||
@ -120,7 +120,7 @@ export default function CompanyDetail() {
|
||||
</div>
|
||||
<div className="pt-2">{t('company.yamano.japanese')}</div>
|
||||
<div className="pb-4">{t('company.yamano.english')}</div>
|
||||
<div className="text-base">{t('company.yamano.role')}</div>
|
||||
<div className="text-sm">{t('company.yamano.role')}</div>
|
||||
</div>
|
||||
|
||||
<div className="font-multilingual col-span-1 py-4 text-lg font-extralight">
|
||||
@ -134,7 +134,7 @@ export default function CompanyDetail() {
|
||||
</div>
|
||||
<div className="pt-2">{t('company.yoshida.japanese')}</div>
|
||||
<div className="pb-4">{t('company.yoshida.english')}</div>
|
||||
<div className="text-base">{t('company.yoshida.role')}</div>
|
||||
<div className="text-sm">{t('company.yoshida.role')}</div>
|
||||
</div>
|
||||
|
||||
<div className="font-multilingual col-span-1 py-4 text-lg font-extralight">
|
||||
@ -148,7 +148,7 @@ export default function CompanyDetail() {
|
||||
</div>
|
||||
<div className="pt-2">{t('company.ikegaya.japanese')}</div>
|
||||
<div className="pb-4">{t('company.ikegaya.english')}</div>
|
||||
<div className="text-base">{t('company.ikegaya.role')}</div>
|
||||
<div className="text-sm">{t('company.ikegaya.role')}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,7 +11,7 @@ export default function ConceptDetail() {
|
||||
|
||||
return (
|
||||
<div className="w-full px-6">
|
||||
<div className="max-w-screen-2x relative mx-auto">
|
||||
<div className="relative mx-auto max-w-screen-2xl">
|
||||
<Image
|
||||
src={ConceptImage001}
|
||||
priority={true}
|
||||
@ -29,24 +29,24 @@ export default function ConceptDetail() {
|
||||
>
|
||||
<div className="md:w-1/2">
|
||||
<h2 className="max-w-sm pb-12 text-4xl md:text-5xl">{t('concept.title')}</h2>
|
||||
<p className="font-multilingual text-lg font-extralight">
|
||||
<p className="font-multilingual text-base font-extralight">
|
||||
{t('concept.para001')} {t('concept.para002')} {t('concept.para003')}
|
||||
</p>
|
||||
<div className="font-multilingual pt-24 font-extralight">
|
||||
<p className="pb-6 text-xl font-normal">{t('concept.subtitle001')}</p>
|
||||
<p className="pb-24 text-lg leading-relaxed">{t('concept.para004')}</p>
|
||||
<p className="pb-24 text-base leading-relaxed">{t('concept.para004')}</p>
|
||||
<p className="pb-6 text-xl font-normal">{t('concept.subtitle002')}</p>
|
||||
<p className="pb-4 text-lg leading-relaxed">{t('concept.para005')}</p>
|
||||
<p className="pb-4 text-lg leading-relaxed">
|
||||
<p className="pb-4 text-base leading-relaxed">{t('concept.para005')}</p>
|
||||
<p className="pb-4 text-base leading-relaxed">
|
||||
{t('concept.para006')} {t('concept.para007')} {t('concept.para008')}
|
||||
</p>
|
||||
<p className="pb-4 text-lg leading-relaxed">{t('concept.para009')}</p>
|
||||
<p className="text-lg leading-relaxed">{t('concept.para010')}</p>
|
||||
<p className="pb-4 text-base leading-relaxed">{t('concept.para009')}</p>
|
||||
<p className="text-base leading-relaxed">{t('concept.para010')}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-row items-start justify-end md:w-1/2">
|
||||
<div className="pb-24">
|
||||
<Logo className="h-30 w-48" />
|
||||
<Logo className="h-32 w-48" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,8 +12,8 @@ export default function Disclosures() {
|
||||
{t('disclosurePage.title')}
|
||||
</h4>
|
||||
<div className="mx-auto max-w-4xl">
|
||||
<div className="font-multilingual my-12 text-lg">
|
||||
<section className="font-multilingual mb-36 mt-12 flex flex-col space-y-6 text-lg md:space-y-3">
|
||||
<div className="font-multilingual my-12">
|
||||
<section className="font-multilingual mb-36 mt-12 flex flex-col space-y-6 text-base md:space-y-3">
|
||||
<div className="flex flex-col space-y-2 md:flex-row md:space-x-3 md:space-y-0">
|
||||
<div className="md:w-1/3">{t('disclosurePage.distributor.label')}</div>
|
||||
<div className="md:w-2/3">
|
||||
|
@ -25,5 +25,5 @@ button {
|
||||
}
|
||||
|
||||
[lang='ja'] .font-multilingual {
|
||||
@apply font-japan;
|
||||
@apply font-japan tracking-widest;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { ThreeItemGrid } from 'components/grid/three-items';
|
||||
import Footer from 'components/layout/footer';
|
||||
import { SupportedLocale } from 'components/layout/navbar/language-control';
|
||||
|
||||
@ -11,6 +10,7 @@ import HomeImage006 from '@images/home-images/home-image-006.webp';
|
||||
import HomeImage007 from '@images/home-images/home-image-007.webp';
|
||||
import HomeImage008 from '@images/home-images/home-image-008.webp';
|
||||
import clsx from 'clsx';
|
||||
import { HomepageProducts } from 'components/grid/homepage-products';
|
||||
import AboutNaraiPreview from 'components/layout/about-narai-preview';
|
||||
import ConceptPreview from 'components/layout/concept-preview';
|
||||
import LocationPreview from 'components/layout/location-preview';
|
||||
@ -18,7 +18,7 @@ import Navbar from 'components/layout/navbar';
|
||||
import NewsletterSignup from 'components/layout/newsletter-signup';
|
||||
import SagyobarPreview from 'components/layout/sagyobar-preview';
|
||||
import Shoplist from 'components/layout/shoplist';
|
||||
import Stories from 'components/layout/stories';
|
||||
import StoriesPreview from 'components/layout/stories-preview';
|
||||
import { BLOG_HANDLE } from 'lib/constants';
|
||||
import { getCart } from 'lib/shopify';
|
||||
import { cookies } from 'next/headers';
|
||||
@ -52,7 +52,7 @@ export default async function HomePage({
|
||||
<div>
|
||||
<Navbar cart={cart} locale={locale} />
|
||||
<div className="pt-12 md:pt-48">
|
||||
<ThreeItemGrid lang={locale} />
|
||||
<HomepageProducts lang={locale} />
|
||||
</div>
|
||||
<div className="py-48">
|
||||
<NewsletterSignup />
|
||||
@ -132,7 +132,7 @@ export default async function HomePage({
|
||||
</div>
|
||||
|
||||
<div className="relative">
|
||||
<Stories handle={BLOG_HANDLE} articles={3} locale={locale} more />
|
||||
<StoriesPreview handle={BLOG_HANDLE} articles={3} locale={locale} more />
|
||||
</div>
|
||||
|
||||
<div className="relative">
|
||||
|
@ -7,11 +7,11 @@ export default function PrivacyPolicy() {
|
||||
return (
|
||||
<>
|
||||
<div className="mx-auto max-w-3xl text-white">
|
||||
<div className="md:text-4x text-center font-serif text-3xl font-bold leading-tight text-white md:mb-16">
|
||||
<div className="text-center font-serif text-3xl font-bold leading-tight text-white md:mb-16 md:text-4xl">
|
||||
{t('privacy.title')}
|
||||
</div>
|
||||
<div className="mb-24 text-lg leading-normal">
|
||||
<div className="text-sb-highlight text-center">{t('privacy.lastModifiedDate')}</div>
|
||||
<div className="text-center">{t('privacy.lastModifiedDate')}</div>
|
||||
<div className="mt-4">
|
||||
<p>{t('privacy.pleaseRead')}</p>
|
||||
<p className="mt-4">{t('privacy.usedFor')}</p>
|
||||
|
@ -2,6 +2,7 @@ import type { Metadata } from 'next';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { AddToCart } from 'components/cart/add-to-cart';
|
||||
import { GridTileImage } from 'components/grid/tile';
|
||||
import Label from 'components/label';
|
||||
@ -64,13 +65,16 @@ export default async function ProductPage({
|
||||
}: {
|
||||
params: { handle: string; locale?: SupportedLocale };
|
||||
}) {
|
||||
const numberOfOtherImages = 3;
|
||||
const product = await getProduct({
|
||||
handle: params.handle,
|
||||
language: params?.locale?.toUpperCase()
|
||||
});
|
||||
let otherImages: MediaImage[] = [];
|
||||
if (!!product) {
|
||||
otherImages = product.images.filter((image) => image?.url !== product.featuredImage?.url);
|
||||
otherImages = product.images
|
||||
.slice(0, numberOfOtherImages + 1) // +1 to account for featured image
|
||||
.filter((image) => image?.url !== product.featuredImage?.url);
|
||||
}
|
||||
|
||||
if (!product) return notFound();
|
||||
@ -102,7 +106,7 @@ export default async function ProductPage({
|
||||
/>
|
||||
<div className="mx-auto max-w-screen-xl py-24">
|
||||
<div className="flex flex-col space-y-12">
|
||||
<div className="relative aspect-square h-full w-full">
|
||||
<div className="relative h-full w-full">
|
||||
<Image
|
||||
src={product.featuredImage?.url}
|
||||
alt={product.featuredImage?.altText}
|
||||
@ -147,17 +151,28 @@ export default async function ProductPage({
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
{!!otherImages &&
|
||||
otherImages?.length > 0 &&
|
||||
otherImages.map((image) => (
|
||||
<div key={image.url} className="relative aspect-square h-full w-full">
|
||||
<Image
|
||||
src={image.url}
|
||||
alt={image.altText}
|
||||
height={image.height}
|
||||
width={image.width}
|
||||
className="h-full w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
otherImages.map((image, index) => {
|
||||
const isOdd = otherImages.length % 2 != 0;
|
||||
const isLast = index === otherImages.length - 1;
|
||||
const isOddAndLast = isOdd && isLast;
|
||||
return (
|
||||
<div
|
||||
key={image.url}
|
||||
className={clsx(
|
||||
isOddAndLast ? 'col-span-2' : 'col-span-1 aspect-square',
|
||||
'relative h-full w-full bg-gray-900/10'
|
||||
)}
|
||||
>
|
||||
<Image
|
||||
src={image.url}
|
||||
alt={image.altText}
|
||||
height={image.height}
|
||||
width={image.width}
|
||||
className="h-full w-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Suspense>
|
||||
<RelatedProducts id={product.id} />
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ThreeItemGrid } from 'components/grid/three-items';
|
||||
import Footer from 'components/layout/footer';
|
||||
import { SupportedLocale } from 'components/layout/navbar/language-control';
|
||||
|
||||
import { ProductGrid } from 'components/grid/product-grid';
|
||||
import Navbar from 'components/layout/navbar';
|
||||
import { getCart } from 'lib/shopify';
|
||||
import { cookies } from 'next/headers';
|
||||
@ -36,7 +36,7 @@ export default async function ProductPage({
|
||||
<div>
|
||||
<Navbar cart={cart} locale={locale} compact />
|
||||
<div className="py-24 md:py-48">
|
||||
<ThreeItemGrid lang={locale} />
|
||||
<ProductGrid lang={locale} />
|
||||
</div>
|
||||
|
||||
<Suspense>
|
||||
|
@ -8,7 +8,7 @@ import { getCart, getPage } from 'lib/shopify';
|
||||
import { cookies } from 'next/headers';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { Suspense } from 'react';
|
||||
import ShopsTitle from './ShopsTitle';
|
||||
import ShopsNav from './shops-nav';
|
||||
|
||||
export const runtime = 'edge';
|
||||
|
||||
@ -50,9 +50,9 @@ export default async function Page({ params }: { params: { locale?: SupportedLoc
|
||||
<div>
|
||||
<Navbar cart={cart} locale={params?.locale} compact />
|
||||
<div className="mx-auto max-w-xl px-6 pb-24 pt-12 md:pb-48 md:pt-24">
|
||||
<ShopsTitle />
|
||||
<h2 className="mb-8 text-3xl font-medium">{page.title}</h2>
|
||||
<Prose className="" html={page.body as string} />
|
||||
<ShopsNav />
|
||||
<h2 className="font-multilingual mb-8 text-3xl font-medium">{page.title}</h2>
|
||||
<Prose html={page.body as string} />
|
||||
</div>
|
||||
|
||||
<Suspense>
|
||||
|
@ -3,11 +3,11 @@
|
||||
import { useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
|
||||
export default function ShopsTitle() {
|
||||
export default function ShopsNav() {
|
||||
const t = useTranslations('Index');
|
||||
return (
|
||||
<div>
|
||||
<div className="flex flex-row items-baseline space-x-6 pb-12">
|
||||
<div className="font-multilingual flex flex-row items-baseline space-x-6 pb-12">
|
||||
<Link href="/#shops">
|
||||
<span className="flex flex-row items-center space-x-1.5">
|
||||
<span>←</span>
|
||||
@ -15,7 +15,7 @@ export default function ShopsTitle() {
|
||||
</span>
|
||||
</Link>
|
||||
<div>|</div>
|
||||
<div className="font-medium">{t('shops.title')}</div>
|
||||
<div className="font-multilingual font-medium">{t('shops.title')}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
@ -127,7 +127,6 @@ export default function TermsOfUse() {
|
||||
{t('terms.contactUs.instructions')}
|
||||
<a
|
||||
href={`mailto:${t('email-address.support')}`}
|
||||
className="branded-link"
|
||||
aria-label={t('privacy.contactUs.ariaLabel')}
|
||||
>
|
||||
{t('email-address.support')}
|
||||
|
@ -37,7 +37,7 @@ export default function DeleteItemButton({ item }: { item: CartItem }) {
|
||||
{isPending ? (
|
||||
<LoadingDots className="bg-white" />
|
||||
) : (
|
||||
<XMarkIcon className="hover:text-accent-3 mx-[1px] h-4 w-4 text-white dark:text-black" />
|
||||
<XMarkIcon className="mx-[1px] h-4 w-4 text-white transition-opacity duration-150 hover:opacity-60 dark:text-black" />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
|
75
components/cart/inline-add-to-cart.tsx
Normal file
75
components/cart/inline-add-to-cart.tsx
Normal file
@ -0,0 +1,75 @@
|
||||
'use client';
|
||||
|
||||
import clsx from 'clsx';
|
||||
import { addItem } from 'components/cart/actions';
|
||||
import LoadingDots from 'components/loading-dots';
|
||||
import { ProductVariant } from 'lib/shopify/types';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
import { useTransition } from 'react';
|
||||
|
||||
export function InlineAddToCart({
|
||||
variants,
|
||||
availableForSale
|
||||
}: {
|
||||
variants: ProductVariant[];
|
||||
availableForSale: boolean;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const t = useTranslations('Index');
|
||||
|
||||
const [isPending, startTransition] = useTransition();
|
||||
const defaultVariantId = variants.length === 1 ? variants[0]?.id : undefined;
|
||||
const variant = variants.find((variant: ProductVariant) =>
|
||||
variant.selectedOptions.every(
|
||||
(option) => option.value === searchParams.get(option.name.toLowerCase())
|
||||
)
|
||||
);
|
||||
const selectedVariantId = variant?.id || defaultVariantId;
|
||||
const title = !availableForSale
|
||||
? 'Out of stock'
|
||||
: !selectedVariantId
|
||||
? 'Please select options'
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<button
|
||||
aria-label="Add item to cart"
|
||||
disabled={isPending || !availableForSale || !selectedVariantId}
|
||||
title={title}
|
||||
onClick={() => {
|
||||
// Safeguard in case someone messes with `disabled` in devtools.
|
||||
if (!availableForSale || !selectedVariantId) return;
|
||||
|
||||
startTransition(async () => {
|
||||
const error = await addItem(selectedVariantId);
|
||||
|
||||
if (error) {
|
||||
// Trigger the error boundary in the root error.js
|
||||
throw new Error(error.toString());
|
||||
}
|
||||
|
||||
router.refresh();
|
||||
});
|
||||
}}
|
||||
className={clsx(
|
||||
'p-4',
|
||||
'relative flex w-full items-center justify-center',
|
||||
'border border-white/20 hover:border-white',
|
||||
'font-serif text-base tracking-wider text-white',
|
||||
'transition-colors duration-150',
|
||||
{
|
||||
'cursor-not-allowed opacity-60 hover:opacity-60': !availableForSale || !selectedVariantId,
|
||||
'cursor-not-allowed': isPending
|
||||
}
|
||||
)}
|
||||
>
|
||||
{!isPending ? (
|
||||
<span>{availableForSale ? t('cart.add') : t('cart.out-of-stock')}</span>
|
||||
) : (
|
||||
<LoadingDots className="my-3 bg-white" />
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
@ -67,7 +67,7 @@ export default function CartModal({ cart }: { cart: Cart | undefined }) {
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="translate-x-full"
|
||||
>
|
||||
<Dialog.Panel className="fixed bottom-0 right-0 top-0 flex h-full w-full flex-col border-l border-white/20 bg-dark p-6 font-sans text-white backdrop-blur-xl md:w-[390px]">
|
||||
<Dialog.Panel className="fixed inset-y-0 right-0 flex h-full w-full flex-col border-l border-white/20 bg-dark p-6 font-sans text-white backdrop-blur-xl md:w-[390px]">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-lg font-semibold">Cart</p>
|
||||
|
||||
@ -83,7 +83,7 @@ export default function CartModal({ cart }: { cart: Cart | undefined }) {
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex h-full flex-col justify-between overflow-hidden p-1">
|
||||
<ul className="flex-grow overflow-auto py-4">
|
||||
<ul className="grow overflow-auto py-4">
|
||||
{cart.lines.map((item, i) => {
|
||||
const merchandiseSearchParams = {} as MerchandiseSearchParams;
|
||||
|
||||
@ -159,11 +159,11 @@ export default function CartModal({ cart }: { cart: Cart | undefined }) {
|
||||
currencyCode={cart.cost.totalTaxAmount.currencyCode}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-3 flex items-center justify-between border-b border-white/20 pb-1 pt-1">
|
||||
<div className="mb-3 flex items-center justify-between border-b border-white/20 py-1">
|
||||
<p>Shipping</p>
|
||||
<p className="text-right text-white/50">Calculated at checkout</p>
|
||||
</div>
|
||||
<div className="mb-3 flex items-center justify-between border-b border-white/20 pb-1 pt-1">
|
||||
<div className="mb-3 flex items-center justify-between border-b border-white/20 py-1">
|
||||
<p>Total</p>
|
||||
<Price
|
||||
className="text-right text-base text-white"
|
||||
|
@ -19,7 +19,7 @@ export default function OpenCart({
|
||||
/>
|
||||
|
||||
{quantity ? (
|
||||
<div className="absolute right-[23%] top-[85%] -mr-2 -mt-2 h-5 w-5 -translate-x-1/2 -translate-y-1/2 transform font-sans text-[12px] font-medium text-white">
|
||||
<div className="absolute right-[23%] top-[85%] -mr-2 -mt-2 h-5 w-5 -translate-x-1/2 -translate-y-1/2 font-sans text-[12px] font-medium text-white">
|
||||
{quantity}
|
||||
</div>
|
||||
) : null}
|
||||
|
78
components/grid/homepage-products.tsx
Normal file
78
components/grid/homepage-products.tsx
Normal file
@ -0,0 +1,78 @@
|
||||
import { ChevronRightIcon } from '@heroicons/react/24/outline';
|
||||
import clsx from 'clsx';
|
||||
import { InlineAddToCart } from 'components/cart/inline-add-to-cart';
|
||||
import { SupportedLocale } from 'components/layout/navbar/language-control';
|
||||
import { getCollectionProducts } from 'lib/shopify';
|
||||
import type { Product } from 'lib/shopify/types';
|
||||
import Link from 'next/link';
|
||||
import Label from '../label';
|
||||
import { GridTileImage } from './tile';
|
||||
|
||||
function HomepageProductsItem({ item, priority }: { item: Product; priority?: boolean }) {
|
||||
const size = item?.variants?.[0]?.selectedOptions?.find((option) => option.name === 'Size');
|
||||
const image = item?.variants?.[0]?.image;
|
||||
|
||||
return !!image ? (
|
||||
<div
|
||||
className={clsx(
|
||||
'col-span-1 row-span-1 flex flex-col justify-between space-y-6 md:col-span-2 md:row-span-1'
|
||||
)}
|
||||
>
|
||||
<Link className="group block w-full" href={`/product/${item.handle}`}>
|
||||
<div className="relative block aspect-tall overflow-hidden ">
|
||||
<GridTileImage
|
||||
src={image?.url}
|
||||
fill
|
||||
sizes={'(min-width: 768px) 33vw, 100vw'}
|
||||
priority={priority}
|
||||
alt={item.title}
|
||||
/>
|
||||
</div>
|
||||
<div className="font-multilingual max-w-sm pb-24 pt-4 md:pb-0">
|
||||
<Label
|
||||
title={item.title as string}
|
||||
amount={item.priceRange.maxVariantPrice.amount}
|
||||
currencyCode={item.priceRange.maxVariantPrice.currencyCode}
|
||||
size={size?.value}
|
||||
/>
|
||||
<div className="line-clamp-4 pt-2 font-extralight">
|
||||
<span>{item?.summary?.value}</span>{' '}
|
||||
<span className="ml-2 inline-flex flex-row items-center space-x-1 opacity-50 transition-opacity duration-150 group-hover:opacity-100">
|
||||
<span>Read more.</span>
|
||||
<span>
|
||||
<ChevronRightIcon width={16} />
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</Link>
|
||||
<InlineAddToCart variants={item.variants} availableForSale={item.availableForSale} />
|
||||
</div>
|
||||
) : null;
|
||||
}
|
||||
|
||||
export async function HomepageProducts({ lang }: { lang?: SupportedLocale }) {
|
||||
// Collections that start with `hidden-*` are hidden from the search page.
|
||||
const homepageItems = await getCollectionProducts({
|
||||
collection: 'hidden-homepage-featured-items',
|
||||
language: lang?.toUpperCase()
|
||||
});
|
||||
|
||||
if (!homepageItems[0] || !homepageItems[1] || !homepageItems[2]) return null;
|
||||
|
||||
const [firstProduct, secondProduct, thirdProduct] = homepageItems;
|
||||
|
||||
return (
|
||||
<section
|
||||
className={clsx(
|
||||
'mx-auto grid max-w-screen-xl gap-12 px-4 pb-4 ',
|
||||
'grid-cols-1 md:grid-cols-6',
|
||||
'grid-rows-3 md:grid-rows-1'
|
||||
)}
|
||||
>
|
||||
<HomepageProductsItem item={firstProduct} priority={true} />
|
||||
<HomepageProductsItem item={secondProduct} priority={true} />
|
||||
<HomepageProductsItem item={thirdProduct} />
|
||||
</section>
|
||||
);
|
||||
}
|
@ -6,12 +6,13 @@ import Link from 'next/link';
|
||||
import Label from '../label';
|
||||
import { GridTileImage } from './tile';
|
||||
|
||||
function ThreeItemGridItem({ item, priority }: { item: Product; priority?: boolean }) {
|
||||
function ProductGridItem({ item, priority }: { item: Product; priority?: boolean }) {
|
||||
const size = item?.variants?.[0]?.selectedOptions?.find((option) => option.name === 'Size');
|
||||
|
||||
return (
|
||||
<div className={clsx('col-span-1 row-span-1 md:col-span-2 md:row-span-1')}>
|
||||
<Link className="w-full bg-black/30" href={`/product/${item.handle}`}>
|
||||
<div className="relative block aspect-tall overflow-hidden ">
|
||||
<div className="relative block aspect-square overflow-hidden ">
|
||||
<GridTileImage
|
||||
src={item.featuredImage.url}
|
||||
fill
|
||||
@ -34,16 +35,14 @@ function ThreeItemGridItem({ item, priority }: { item: Product; priority?: boole
|
||||
);
|
||||
}
|
||||
|
||||
export async function ThreeItemGrid({ lang }: { lang?: SupportedLocale }) {
|
||||
export async function ProductGrid({ lang }: { lang?: SupportedLocale }) {
|
||||
// Collections that start with `hidden-*` are hidden from the search page.
|
||||
const homepageItems = await getCollectionProducts({
|
||||
collection: 'hidden-homepage-featured-items',
|
||||
const productPageItems = await getCollectionProducts({
|
||||
collection: 'hidden-products-page-items',
|
||||
language: lang?.toUpperCase()
|
||||
});
|
||||
|
||||
if (!homepageItems[0] || !homepageItems[1] || !homepageItems[2]) return null;
|
||||
|
||||
const [firstProduct, secondProduct, thirdProduct] = homepageItems;
|
||||
if (!productPageItems?.length) return null;
|
||||
|
||||
return (
|
||||
<section
|
||||
@ -53,9 +52,9 @@ export async function ThreeItemGrid({ lang }: { lang?: SupportedLocale }) {
|
||||
'grid-rows-3 md:grid-rows-1'
|
||||
)}
|
||||
>
|
||||
<ThreeItemGridItem item={firstProduct} priority={true} />
|
||||
<ThreeItemGridItem item={secondProduct} priority={true} />
|
||||
<ThreeItemGridItem item={thirdProduct} />
|
||||
{productPageItems.map((item) => (
|
||||
<ProductGridItem key={item.id} item={item} priority={true} />
|
||||
))}
|
||||
</section>
|
||||
);
|
||||
}
|
@ -3,8 +3,8 @@ import Image from 'next/image';
|
||||
|
||||
export function GridTileImage({
|
||||
isInteractive = true,
|
||||
active,
|
||||
label,
|
||||
active: _active,
|
||||
label: _label,
|
||||
...props
|
||||
}: {
|
||||
isInteractive?: boolean;
|
||||
|
@ -15,8 +15,10 @@ const Label = ({
|
||||
return (
|
||||
<div className={clsx('@container/label')}>
|
||||
<div className="flex flex-col space-y-2">
|
||||
<h3 className="mr-4 line-clamp-2 flex-grow font-serif text-3xl md:text-4xl">{title}</h3>
|
||||
<div className="font-multilingual flex flex-row items-center space-x-2">
|
||||
<h3 className="mr-4 line-clamp-2 grow font-serif text-3xl tracking-wider md:text-4xl">
|
||||
{title}
|
||||
</h3>
|
||||
<div className="font-multilingual flex flex-row items-center space-x-2 text-[17px]">
|
||||
<Price
|
||||
className="flex-none"
|
||||
amount={amount}
|
||||
|
@ -7,10 +7,10 @@ export default function AboutNaraiPreview() {
|
||||
return (
|
||||
<div className="flex flex-col space-y-4 px-6 py-24 md:flex-row md:space-x-12 md:space-y-0 md:p-24">
|
||||
<div className="font-multilingual flex flex-col space-y-2 font-extralight md:w-1/2">
|
||||
<div className="max-w-sm text-5xl">{t('home.previews.about-narai.title')}</div>
|
||||
<div className="max-w-sm text-5xl">{t('home.previews.about-narai.subtitle')}</div>
|
||||
<div className="max-w-title text-[40px]">{t('home.previews.about-narai.title')}</div>
|
||||
<div className="max-w-sm text-[40px]">{t('home.previews.about-narai.subtitle')}</div>
|
||||
</div>
|
||||
<div className="font-multilingual flex flex-col space-y-6 font-extralight md:w-1/2">
|
||||
<div className="font-multilingual flex flex-col space-y-6 text-base font-extralight md:w-1/2">
|
||||
<div>{t('home.previews.about-narai.body')}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -8,14 +8,14 @@ export default function ConceptPreview() {
|
||||
return (
|
||||
<div className="flex flex-col space-y-4 px-6 py-24 md:flex-row md:space-x-12 md:space-y-0 md:p-24">
|
||||
<div className="font-multilingual flex flex-col space-y-2 font-extralight md:w-1/2">
|
||||
<div className="max-w-sm text-5xl">{t('home.previews.concept.title')}</div>
|
||||
<div className="max-w-sm text-5xl">{t('home.previews.concept.subtitle')}</div>
|
||||
<div className="max-w-sm text-[40px]">{t('home.previews.concept.title')}</div>
|
||||
<div className="max-w-sm text-[40px]">{t('home.previews.concept.subtitle')}</div>
|
||||
</div>
|
||||
<div className="font-multilingual flex flex-col space-y-6 font-extralight md:w-1/2">
|
||||
<div className="font-multilingual flex flex-col space-y-6 text-base font-extralight md:w-1/2">
|
||||
<div>{t('home.previews.concept.body')}</div>
|
||||
<Link
|
||||
href="/location"
|
||||
className="max-w-sm border border-white px-6 py-3 text-center text-lg transition-colors duration-150 hover:border-white/50"
|
||||
href="/concept"
|
||||
className="max-w-sm border border-white px-6 py-3 text-center text-base transition-colors duration-150 hover:border-white/50"
|
||||
>
|
||||
{t('home.previews.concept.button')}
|
||||
</Link>
|
||||
|
@ -10,7 +10,7 @@ export default function FooterMenu() {
|
||||
<div className="hidden md:grid md:w-full md:grid-cols-2">
|
||||
<div className="col-span-1">
|
||||
<div className="mb-4 font-serif text-base underline">{t('menu.title')}</div>
|
||||
<nav className="font-multilingual flex flex-col space-y-2 text-left text-base font-extralight">
|
||||
<nav className="font-multilingual flex flex-col space-y-2 text-left text-sm font-extralight">
|
||||
<div>
|
||||
<Link href="/products" className="transition-opacity duration-150 hover:opacity-50">
|
||||
{t('menu.products')}
|
||||
@ -59,7 +59,7 @@ export default function FooterMenu() {
|
||||
<div className="mb-4 text-right font-serif text-base underline">
|
||||
{t('shopping-guide.title')}
|
||||
</div>
|
||||
<nav className="font-multilingual flex flex-col items-end space-y-2 text-left text-base font-extralight">
|
||||
<nav className="font-multilingual flex flex-col items-end space-y-2 text-left text-sm font-extralight">
|
||||
<div>
|
||||
<Link href="/terms" className="transition-opacity duration-150 hover:opacity-50">
|
||||
{t('shopping-guide.terms')}
|
||||
|
@ -35,11 +35,11 @@ export default async function Footer({ cart }: { cart?: Cart }) {
|
||||
<div className="flex flex-row items-end space-x-6">
|
||||
<div className="flex flex-col items-start space-y-2">
|
||||
<p className="font-japan text-3xl font-extralight">杉の森酒造</p>
|
||||
<p className="font-serif text-lg">suginomori brewery</p>
|
||||
<p className="font-serif text-xs font-semibold">suginomori brewery</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-start space-y-2">
|
||||
<p className="font-japan text-xl font-extralight">長野県塩尻市奈良井551-1</p>
|
||||
<p className="font-serif text-lg">551-1 Narai, Shiojiri, Nagano</p>
|
||||
<p className="font-serif text-xs font-semibold">551-1 Narai, Shiojiri, Nagano</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -52,11 +52,11 @@ export default async function Footer({ cart }: { cart?: Cart }) {
|
||||
</Link>
|
||||
<div className="flex grow flex-col items-end space-y-6">
|
||||
<div className="flex flex-col items-start space-y-2">
|
||||
<p className="font-japan text-3xl font-extralight">杉の森酒造</p>
|
||||
<p className="font-japan text-[22px] font-extralight">杉の森酒造</p>
|
||||
<p className="font-serif text-lg">suginomori brewery</p>
|
||||
</div>
|
||||
<div className="flex flex-col items-start space-y-2">
|
||||
<p className="font-japan text-xl font-extralight">長野県塩尻市奈良井551-1</p>
|
||||
<p className="font-japan text-[17px] font-extralight">長野県塩尻市奈良井551-1</p>
|
||||
<p className="font-serif text-lg">551-1 Narai, Shiojiri, Nagano</p>
|
||||
</div>
|
||||
<div className="flex flex-row justify-between space-x-4">
|
||||
|
@ -8,14 +8,14 @@ export default function LocationPreview() {
|
||||
return (
|
||||
<div className="flex flex-col space-y-4 px-6 py-24 md:flex-row md:space-x-12 md:space-y-0 md:p-24">
|
||||
<div className="font-multilingual flex flex-col space-y-2 font-extralight md:w-1/2">
|
||||
<div className="max-w-sm text-5xl">{t('home.previews.location.title')}</div>
|
||||
<div className="max-w-sm text-5xl">{t('home.previews.location.subtitle')}</div>
|
||||
<div className="max-w-title text-[40px]">{t('home.previews.location.title')}</div>
|
||||
<div className="max-w-sm text-[40px]">{t('home.previews.location.subtitle')}</div>
|
||||
</div>
|
||||
<div className="font-multilingual flex flex-col space-y-6 font-extralight md:w-1/2">
|
||||
<div className="font-multilingual flex flex-col space-y-6 text-base font-extralight md:w-1/2">
|
||||
<div>{t('home.previews.location.body')}</div>
|
||||
<Link
|
||||
href="/location"
|
||||
className="max-w-sm border border-white px-6 py-3 text-center text-lg transition-colors duration-150 hover:border-white/50"
|
||||
href="/about"
|
||||
className="max-w-sm border border-white px-6 py-3 text-center text-base transition-colors duration-150 hover:border-white/50"
|
||||
>
|
||||
{t('home.previews.location.button')}
|
||||
</Link>
|
||||
|
@ -3,6 +3,7 @@
|
||||
import { Dialog, Transition } from '@headlessui/react';
|
||||
import clsx from 'clsx';
|
||||
import CloseIcon from 'components/icons/close';
|
||||
import Logo from 'components/icons/logo';
|
||||
import MenuIcon from 'components/icons/menu';
|
||||
import { useLocale, useTranslations } from 'next-intl';
|
||||
import Link from 'next/link';
|
||||
@ -12,8 +13,8 @@ import { LanguageControl, SupportedLocale } from '../navbar/language-control';
|
||||
export function MenuModal({ scrolled }: { scrolled: boolean }) {
|
||||
const t = useTranslations('Index');
|
||||
const locale = useLocale();
|
||||
let [isOpen, setIsOpen] = useState(false);
|
||||
let closeButtonRef = useRef(null);
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const closeButtonRef = useRef(null);
|
||||
|
||||
const close = () => {
|
||||
setIsOpen(false);
|
||||
@ -55,6 +56,9 @@ export function MenuModal({ scrolled }: { scrolled: boolean }) {
|
||||
<div className="fixed inset-0 z-30 bg-dark/80 backdrop-blur-sm">
|
||||
<Dialog.Panel>
|
||||
<div className="z-40 mx-auto max-w-screen-xl px-6">
|
||||
<div className="absolute left-6 top-2">
|
||||
<Logo className="h-[132px] w-[132px]" />
|
||||
</div>
|
||||
<div
|
||||
className={clsx(
|
||||
'flex flex-row justify-end space-x-6 px-2',
|
||||
|
@ -61,7 +61,7 @@ export default function MobileMenu({ menu }: { menu: Menu[] }) {
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="translate-x-[-100%]"
|
||||
>
|
||||
<Dialog.Panel className="fixed bottom-0 left-0 right-0 top-0 flex h-full w-full flex-col bg-white pb-6 dark:bg-black">
|
||||
<Dialog.Panel className="fixed inset-0 flex h-full w-full flex-col bg-white pb-6 dark:bg-black">
|
||||
<div className="p-4">
|
||||
<button
|
||||
className="mb-4 flex h-11 w-11 items-center justify-center rounded-md border border-neutral-200 text-black transition-colors dark:border-neutral-700 dark:text-white"
|
||||
|
@ -32,7 +32,7 @@ export default function Search() {
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit} className="w-max-[550px] relative w-full lg:w-80 xl:w-full">
|
||||
<form onSubmit={onSubmit} className="relative w-full max-w-[550px] lg:w-80 xl:w-full">
|
||||
<input
|
||||
type="text"
|
||||
name="search"
|
||||
|
@ -36,7 +36,7 @@ export default function NewsletterSignup() {
|
||||
)}
|
||||
placeholder={t('newsletter.placeholder')}
|
||||
/>
|
||||
<div className="mt-3 rounded-md sm:ml-3 sm:mt-0 sm:flex-shrink-0">
|
||||
<div className="mt-3 rounded-md sm:ml-3 sm:mt-0 sm:shrink-0">
|
||||
<button
|
||||
type="submit"
|
||||
className={clsx(
|
||||
|
@ -8,7 +8,7 @@ export default function NewsletterSignup() {
|
||||
return (
|
||||
<div className="mx-auto max-w-xl space-y-4">
|
||||
<h3 className="font-serif text-2xl tracking-wider">{t('newsletter.title')}</h3>
|
||||
<div className="font-multilingual font-extralight">{t('newsletter.description')}</div>
|
||||
<div className="font-multilingual text-sm font-extralight">{t('newsletter.description')}</div>
|
||||
<form
|
||||
className="max-w-xl space-x-px md:flex"
|
||||
action={`${process?.env?.NEXT_PUBLIC_MAILCHIMP_HOST}/subscribe/post?u=${process?.env?.NEXT_PUBLIC_MAILCHIMP_USER_ID}&id=${process?.env?.NEXT_PUBLIC_MAILCHIMP_LIST_ID}`}
|
||||
@ -26,7 +26,7 @@ export default function NewsletterSignup() {
|
||||
autoComplete="email"
|
||||
required
|
||||
className={clsx(
|
||||
'w-full min-w-0 appearance-none',
|
||||
'w-full min-w-0 appearance-none text-sm',
|
||||
'bg-white outline-none',
|
||||
'px-4 py-3 focus:outline-none',
|
||||
'focus:ring-2 focus:ring-inset focus:ring-emerald-300 focus:ring-offset-0',
|
||||
@ -34,11 +34,11 @@ export default function NewsletterSignup() {
|
||||
)}
|
||||
placeholder={t('newsletter.placeholder')}
|
||||
/>
|
||||
<div className="mt-3 rounded-md sm:ml-3 sm:mt-0 sm:flex-shrink-0">
|
||||
<div className="mt-3 rounded-md sm:ml-3 sm:mt-0 sm:shrink-0">
|
||||
<button
|
||||
type="submit"
|
||||
className={clsx(
|
||||
'px-4 py-3',
|
||||
'px-4 py-3 text-sm',
|
||||
'transition-colors duration-150',
|
||||
'font-multilingual flex w-full items-center justify-center font-extralight',
|
||||
'border border-white/30 hover:border-white',
|
||||
|
@ -7,15 +7,16 @@ export default function SagyobarPreview() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-4 px-6 py-24 md:flex-row md:space-x-12 md:space-y-0 md:p-24">
|
||||
<div className="font-multilingual flex flex-col space-y-2 font-extralight md:w-1/2">
|
||||
<div className="max-w-sm text-5xl">{t('home.previews.bar.title')}</div>
|
||||
<div className="max-w-sm text-5xl">{t('home.previews.bar.subtitle')}</div>
|
||||
<div className="font-multilingual flex flex-col font-extralight md:w-1/2">
|
||||
<div className="max-w-sm text-[40px]">{t('home.previews.bar.title.line001')}</div>
|
||||
<div className="max-w-sm text-[40px]">{t('home.previews.bar.title.line002')}</div>
|
||||
<div className="max-w-sm text-[40px]">{t('home.previews.bar.title.line003')}</div>
|
||||
</div>
|
||||
<div className="font-multilingual flex flex-col space-y-6 font-extralight md:w-1/2">
|
||||
<div className="font-multilingual flex flex-col space-y-6 text-base font-extralight md:w-1/2">
|
||||
<div>{t('home.previews.bar.body')}</div>
|
||||
<Link
|
||||
href="/location"
|
||||
className="max-w-sm border border-white px-6 py-3 text-center text-lg transition-colors duration-150 hover:border-white/50"
|
||||
href="/sagyobar"
|
||||
className="max-w-sm border border-white px-6 py-3 text-center text-base transition-colors duration-150 hover:border-white/50"
|
||||
>
|
||||
{t('home.previews.bar.button')}
|
||||
</Link>
|
||||
|
@ -6,12 +6,10 @@ import Link from 'next/link';
|
||||
export default function Shoplist() {
|
||||
const t = useTranslations('Index');
|
||||
return (
|
||||
<div className="mx-auto max-w-screen-xl space-y-4 px-6" id="shops">
|
||||
<div className="font-multilingual mx-auto max-w-screen-xl space-y-4 px-6" id="shops">
|
||||
<div className="flex w-full flex-row items-baseline space-x-12 pb-6">
|
||||
<h2 className="font-serif text-6xl tracking-wider">shop list</h2>
|
||||
<h3 className="font-multilingual text-2xl font-extralight tracking-wider">
|
||||
{t('shops.subtitle')}
|
||||
</h3>
|
||||
<h3 className="text-2xl font-extralight tracking-wider">{t('shops.subtitle')}</h3>
|
||||
</div>
|
||||
<div className="grid w-full grid-cols-2 gap-px">
|
||||
<Link
|
||||
|
@ -4,7 +4,7 @@ import Image from 'next/image';
|
||||
import Link from 'next/link';
|
||||
import { SupportedLocale } from './navbar/language-control';
|
||||
|
||||
export default async function Stories({
|
||||
export default async function StoriesPreview({
|
||||
locale,
|
||||
handle,
|
||||
articles,
|
||||
@ -21,7 +21,7 @@ export default async function Stories({
|
||||
language: locale?.toUpperCase()
|
||||
});
|
||||
|
||||
if (!blog) return null;
|
||||
if (!blog || !!blog?.articles) return null;
|
||||
|
||||
return (
|
||||
<div className="bg-white px-6 py-24 text-black">
|
||||
@ -60,7 +60,7 @@ export default async function Stories({
|
||||
<div className="flex w-full flex-row justify-center pt-12">
|
||||
<Link
|
||||
href="/stories"
|
||||
className="mx-auto max-w-sm border border-dark px-24 py-3 text-center text-lg transition-colors duration-150 hover:border-dark/40"
|
||||
className="mx-auto max-w-sm border border-dark px-24 py-3 text-center text-[15px] transition-colors duration-150 hover:border-dark/40"
|
||||
>
|
||||
more stories
|
||||
</Link>
|
@ -5,8 +5,8 @@ export default function LogoSquare({ size }: { size?: 'sm' | undefined }) {
|
||||
return (
|
||||
<div
|
||||
className={clsx('flex flex-none items-center justify-center', {
|
||||
'h-[40px] w-[40px] rounded-xl': !size,
|
||||
'h-[30px] w-[30px] rounded-lg': size === 'sm'
|
||||
'h-[40px] w-[40px]': !size,
|
||||
'h-[30px] w-[30px]': size === 'sm'
|
||||
})}
|
||||
>
|
||||
<Logo
|
||||
|
@ -100,7 +100,7 @@ const AgeGateForm: FC<AgeGateFormProps> = ({ checkoutUrl, didCancel }) => {
|
||||
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
|
||||
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||
>
|
||||
<div className="inline-block transform space-y-6 overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left align-bottom text-dark shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6 sm:align-middle">
|
||||
<div className="inline-block space-y-6 overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left align-bottom text-dark shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6 sm:align-middle">
|
||||
<div>
|
||||
<div className="mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100 dark:bg-green-900">
|
||||
<CheckIcon
|
||||
@ -116,9 +116,7 @@ const AgeGateForm: FC<AgeGateFormProps> = ({ checkoutUrl, didCancel }) => {
|
||||
{t('age-gate.title')}
|
||||
</Dialog.Title>
|
||||
<div className="mt-2">
|
||||
<p className="dark:text-secondary-neutral text-sm text-white">
|
||||
{t('age-gate.description')}
|
||||
</p>
|
||||
<p className="text-sm text-white">{t('age-gate.description')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -11,7 +11,7 @@ const Prose: FunctionComponent<TextProps> = ({ html, className }) => {
|
||||
<div
|
||||
className={clsx(
|
||||
'prose text-lg leading-7',
|
||||
'font-multilingual font-extralight text-white',
|
||||
'font-multilingual text-[15px] font-extralight text-white',
|
||||
'prose-headings:mt-8 prose-headings:font-semibold prose-headings:tracking-wide prose-headings:text-white',
|
||||
'prose-h1:text-5xl prose-h2:text-4xl prose-h3:text-3xl prose-h4:text-2xl prose-h5:text-xl prose-h6:text-lg',
|
||||
'prose-a:text-white/80 prose-a:underline hover:prose-a:text-white',
|
||||
@ -20,6 +20,7 @@ const Prose: FunctionComponent<TextProps> = ({ html, className }) => {
|
||||
'prose-tr:border-subtle',
|
||||
'prose-ol:mt-8 prose-ol:list-decimal prose-ol:pl-6 prose-ul:mt-8 prose-ul:list-disc prose-ul:pl-6',
|
||||
'dark:text-white dark:prose-headings:text-white dark:prose-a:text-white dark:prose-strong:text-white',
|
||||
'!tracking-normal',
|
||||
className
|
||||
)}
|
||||
dangerouslySetInnerHTML={{ __html: html as string }}
|
||||
|
@ -40,6 +40,9 @@ const productFragment = /* GraphQL */ `
|
||||
name
|
||||
value
|
||||
}
|
||||
image {
|
||||
...image
|
||||
}
|
||||
price {
|
||||
amount
|
||||
currencyCode
|
||||
|
@ -98,6 +98,7 @@ export type ProductVariant = {
|
||||
value: string;
|
||||
}[];
|
||||
price: Money;
|
||||
image: Image;
|
||||
};
|
||||
|
||||
export type SEO = {
|
||||
|
18
license.md
18
license.md
@ -2,20 +2,8 @@ The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2023 Vercel, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
@ -41,8 +41,11 @@
|
||||
"button": "about narai"
|
||||
},
|
||||
"bar": {
|
||||
"title": "sagyobar : a brewery-operated bar & workspace",
|
||||
"subtitle": "",
|
||||
"title": {
|
||||
"line001": "sagyobar : a brewery-operated bar & workspace",
|
||||
"line002": "",
|
||||
"line003": ""
|
||||
},
|
||||
"body": "Introducing sagyobar: a place where brewery operations (sagyo) and drinking (bar) come together. We have combined our brewery workspace, where we pack boxes and fulfill orders, with a place to enjoy sake served from our very own suginomori wagon. It is a renovated warehouse located a one-minute walk from the brewery, just across the railway tracks.",
|
||||
"button": "about sagyobar"
|
||||
},
|
||||
@ -71,8 +74,8 @@
|
||||
}
|
||||
},
|
||||
"cart": {
|
||||
"add": "Add to cart",
|
||||
"out-of-stock": "Out of stock",
|
||||
"add": "add to cart",
|
||||
"out-of-stock": "out of stock",
|
||||
"title": "Shopping Bag",
|
||||
"subtitle": "Review your Order",
|
||||
"empty": "Your shopping bag is empty",
|
||||
@ -92,7 +95,7 @@
|
||||
"editNote": "Edit note",
|
||||
"hideNote": "Hide",
|
||||
"saving": "Saving...",
|
||||
"addFeaturedProduct": "+ Add"
|
||||
"addFeaturedProduct": "+ add"
|
||||
},
|
||||
"age-gate": {
|
||||
"title": "Confirm Your Age",
|
||||
@ -127,6 +130,7 @@
|
||||
},
|
||||
"materials": {
|
||||
"title": "materials",
|
||||
"subtitle": "",
|
||||
"water": {
|
||||
"title": "water - the foundation",
|
||||
"body": "While most breweries use well water with stable properties, narai uses natural mountain water flowing from an altitude of over 1,000 meters. This mountain water, which springs near the divide between the Shinano and Kiso Rivers, is one of the clearest in Japan with a hardness of less than 25 and a round, smooth texture."
|
||||
@ -147,8 +151,11 @@
|
||||
},
|
||||
"bar": {
|
||||
"001": {
|
||||
"title": "sagyobar : a brewery-operated bar & workspace",
|
||||
"subtitle": "",
|
||||
"title": {
|
||||
"line001": "sagyobar : a brewery-operated bar & workspace",
|
||||
"line002": "",
|
||||
"line003": ""
|
||||
},
|
||||
"para001": "Introducing sagyobar: a place where brewery operations (sagyo) and drinking (bar) come together. We have combined our brewery workspace, where we pack boxes and fulfill orders, with a place to enjoy sake served from our very own suginomori wagon.",
|
||||
"para002": "The renovated warehouse was originally used for storing equipment and business supplies left from the old Suginomori Shuzo, the precursor to suginomori brewery that was established in 1793. While maintaining its original structure, we have revamped its entrance and installed new systems such as lighting and air conditioning. We utilize “P-boxes” – containers used to transport sake bottles – that can be flexibly arranged to transform the space into standing bar."
|
||||
},
|
||||
|
@ -5,13 +5,13 @@
|
||||
},
|
||||
"menu": {
|
||||
"title": "menu",
|
||||
"products": "商品",
|
||||
"shops": "取り扱い店",
|
||||
"about": "naraiについて",
|
||||
"products": "products",
|
||||
"shops": "shop list",
|
||||
"about": "about narai",
|
||||
"bar": "sagyobar",
|
||||
"concept": "コンセプト",
|
||||
"stories": "ストーリー",
|
||||
"company": "会社概要",
|
||||
"concept": "concept",
|
||||
"stories": "stories",
|
||||
"company": "company",
|
||||
"contact": "contact"
|
||||
},
|
||||
"shopping-guide": {
|
||||
@ -41,8 +41,11 @@
|
||||
"button": "naraiについて"
|
||||
},
|
||||
"bar": {
|
||||
"title": "酒蔵直営の角打ち&作業場",
|
||||
"subtitle": "sagyobar",
|
||||
"title": {
|
||||
"line001": "酒蔵直営の",
|
||||
"line002": "角打ち&作業場",
|
||||
"line003": "sagyobar"
|
||||
},
|
||||
"body": "ここは、ボトルの箱詰めや出荷などの酒蔵作業 (sagyo) と、日本酒移動販売車「suginomori wagon」から提供されるSAKEを楽しむこともできる場(bar)が融合した、弊蔵の直営店です。酒蔵から徒歩1分。線路を挟み向かいの倉庫をリノベーションしました。",
|
||||
"button": "sagyobarについて"
|
||||
},
|
||||
@ -126,7 +129,8 @@
|
||||
"subtitle": "受賞歴"
|
||||
},
|
||||
"materials": {
|
||||
"title": "自然を紡ぐ – naraiの素材",
|
||||
"title": "自然を紡ぐ",
|
||||
"subtitle": " – naraiの素材",
|
||||
"water": {
|
||||
"title": "水 – 土台",
|
||||
"body": "多くの酒蔵が水の性質が安定している井戸水を使用しますが、naraiは標高1,000m以上から流れる天然の山水を使用。信濃川と木曽川の分水嶺付近の湧き水であるこの山水は、日本でも有数な「硬度25以下」の透明感と丸みのある滑らかな舌触りが特徴です。"
|
||||
@ -136,7 +140,7 @@
|
||||
"body": "長野県安曇野エリアで、日本アルプスの恵みで農家を営む「ファームいちまる」によって、丁寧に育てられた米を使用しています。地産米にこだわり、杜氏自ら農家に通い、田植えなどを行いながら相談し、米を厳選しています。"
|
||||
},
|
||||
"koji": {
|
||||
"title": "酵母と麹 (発酵) – 構成要素",
|
||||
"title": "酵母と麹 - 構成要素(発酵)",
|
||||
"body": "酵母は発酵力が強く、香りを上品にまとめることができることが特徴だと考えている長野由来の協会第7号を使用しています。米を糖に変える麹菌は、酵素力価の良いバランスの取れたものを採用しています。"
|
||||
}
|
||||
},
|
||||
@ -147,8 +151,11 @@
|
||||
},
|
||||
"bar": {
|
||||
"001": {
|
||||
"title": "酒蔵直営の角打ち&作業場",
|
||||
"subtitle": "sagyobar",
|
||||
"title": {
|
||||
"line001": "酒蔵直営の",
|
||||
"line002": "角打ち&作業場",
|
||||
"line003": "sagyobar"
|
||||
},
|
||||
"para001": "ここは、ボトルの箱詰めや出荷などの酒蔵作業 (sagyo) と、日本酒移動販売車「suginomori wagon」から提供されるsakeを楽しむこともできる場(bar)が融合した、弊蔵の直営店です。",
|
||||
"para002": "リノベーションした倉庫は、元々は先代の頃の杉の森酒蔵の機材や業務備品の保管用の場所として利用されていました。倉庫の建築はそのままに、入り口部分のゲートを刷新し、照明や空調等の設備を新設。什器は酒蔵の作業でも使用する酒瓶を運ぶための外装容器「P箱」を活用しています。このP箱を自在にレイアウトすることで、角打ちのようなスペースとしても活用できます。"
|
||||
},
|
||||
@ -214,7 +221,7 @@
|
||||
},
|
||||
"address": {
|
||||
"label": "所在地",
|
||||
"value": "〒399-6303長野県塩尻市奈良井551-1"
|
||||
"value": "〒399-6303 長野県塩尻市奈良井551-1"
|
||||
},
|
||||
"telephone": {
|
||||
"label": "電話番号",
|
||||
|
@ -28,6 +28,7 @@
|
||||
"@thgh/next-gtm": "^0.1.4",
|
||||
"clsx": "^2.0.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"eslint-plugin-prettier": "^5.0.0",
|
||||
"eslint-plugin-tailwindcss": "^3.13.0",
|
||||
"eslint-plugin-unused-imports": "^3.0.0",
|
||||
"js-cookie": "^3.0.5",
|
||||
|
3443
pnpm-lock.yaml
generated
3443
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -17,10 +17,18 @@ module.exports = {
|
||||
title: ['var(--font-cinzel)', 'serif'],
|
||||
japan: ['var(--font-noto)', 'serif']
|
||||
},
|
||||
fontSize: {
|
||||
'6xl': '65px',
|
||||
'5xl': '45px',
|
||||
'3xs': '.5rem'
|
||||
},
|
||||
aspectRatio: {
|
||||
tall: '596 / 845',
|
||||
video: '1792 / 750'
|
||||
},
|
||||
maxWidth: {
|
||||
title: '281px'
|
||||
},
|
||||
keyframes: {
|
||||
fadeIn: {
|
||||
from: { opacity: 0 },
|
||||
|
36
yarn.lock
36
yarn.lock
@ -1299,6 +1299,7 @@ __metadata:
|
||||
eslint: ^8.45.0
|
||||
eslint-config-next: latest
|
||||
eslint-config-prettier: ^8.8.0
|
||||
eslint-plugin-prettier: ^5.0.0
|
||||
eslint-plugin-tailwindcss: ^3.13.0
|
||||
eslint-plugin-unicorn: ^48.0.0
|
||||
eslint-plugin-unused-imports: ^3.0.0
|
||||
@ -1812,6 +1813,25 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-plugin-prettier@npm:^5.0.0":
|
||||
version: 5.0.0
|
||||
resolution: "eslint-plugin-prettier@npm:5.0.0"
|
||||
dependencies:
|
||||
prettier-linter-helpers: ^1.0.0
|
||||
synckit: ^0.8.5
|
||||
peerDependencies:
|
||||
"@types/eslint": ">=8.0.0"
|
||||
eslint: ">=8.0.0"
|
||||
prettier: ">=3.0.0"
|
||||
peerDependenciesMeta:
|
||||
"@types/eslint":
|
||||
optional: true
|
||||
eslint-config-prettier:
|
||||
optional: true
|
||||
checksum: 84e88744b9050f2d5ef31b94e85294dda16f3a53c2449f9d33eac8ae6264889b459bf35a68e438fb6b329c2a1d6491aac4bfa00d86317e7009de3dad0311bec6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-plugin-react-hooks@npm:5.0.0-canary-7118f5dd7-20230705":
|
||||
version: 5.0.0-canary-7118f5dd7-20230705
|
||||
resolution: "eslint-plugin-react-hooks@npm:5.0.0-canary-7118f5dd7-20230705"
|
||||
@ -2060,6 +2080,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-diff@npm:^1.1.2":
|
||||
version: 1.3.0
|
||||
resolution: "fast-diff@npm:1.3.0"
|
||||
checksum: d22d371b994fdc8cce9ff510d7b8dc4da70ac327bcba20df607dd5b9cae9f908f4d1028f5fe467650f058d1e7270235ae0b8230809a262b4df587a3b3aa216c3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"fast-glob@npm:^3.2.12, fast-glob@npm:^3.2.5, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0":
|
||||
version: 3.3.1
|
||||
resolution: "fast-glob@npm:3.3.1"
|
||||
@ -4057,6 +4084,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prettier-linter-helpers@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "prettier-linter-helpers@npm:1.0.0"
|
||||
dependencies:
|
||||
fast-diff: ^1.1.2
|
||||
checksum: 00ce8011cf6430158d27f9c92cfea0a7699405633f7f1d4a45f07e21bf78e99895911cbcdc3853db3a824201a7c745bd49bfea8abd5fb9883e765a90f74f8392
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"prettier-plugin-organize-imports@npm:^3.2.3":
|
||||
version: 3.2.3
|
||||
resolution: "prettier-plugin-organize-imports@npm:3.2.3"
|
||||
|
Loading…
x
Reference in New Issue
Block a user