Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 622e7f3642 | |||
| 864008af16 | |||
| 011994b36e | |||
| 261fd36579 | |||
| 09725c6b0d | |||
| 57bae7ed6f |
@@ -19,7 +19,7 @@ export async function generateMetadata({ params }: AboutPageProps): Promise<Meta
|
|||||||
const metadata = getPageMetadata(validLocale as Locale);
|
const metadata = getPageMetadata(validLocale as Locale);
|
||||||
const keywords = getPageKeywords(validLocale as Locale, 'about');
|
const keywords = getPageKeywords(validLocale as Locale, 'about');
|
||||||
|
|
||||||
const localePrefix = validLocale === DEFAULT_LOCALE ? "" : `/${validLocale}`;
|
const localePrefix = `/${validLocale}`;
|
||||||
const canonicalUrl = `${baseUrl}${localePrefix}/about`;
|
const canonicalUrl = `${baseUrl}${localePrefix}/about`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export async function generateMetadata({ params }: ContactPageProps): Promise<Me
|
|||||||
const metadata = getPageMetadata(validLocale as Locale);
|
const metadata = getPageMetadata(validLocale as Locale);
|
||||||
const keywords = getPageKeywords(validLocale as Locale, 'contact');
|
const keywords = getPageKeywords(validLocale as Locale, 'contact');
|
||||||
|
|
||||||
const localePrefix = validLocale === DEFAULT_LOCALE ? "" : `/${validLocale}`;
|
const localePrefix = `/${validLocale}`;
|
||||||
const canonicalUrl = `${baseUrl}${localePrefix}/contact`;
|
const canonicalUrl = `${baseUrl}${localePrefix}/contact`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ export async function generateMetadata({
|
|||||||
}): Promise<Metadata> {
|
}): Promise<Metadata> {
|
||||||
const { locale } = await params;
|
const { locale } = await params;
|
||||||
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
const validLocale = isValidLocale(locale) ? locale : DEFAULT_LOCALE;
|
||||||
const localePrefix = validLocale === DEFAULT_LOCALE ? "" : `/${locale}`;
|
const localePrefix = `/${locale}`;
|
||||||
|
|
||||||
const languages: Record<string, string> = {};
|
const languages: Record<string, string> = {};
|
||||||
for (const loc of SUPPORTED_LOCALES) {
|
for (const loc of SUPPORTED_LOCALES) {
|
||||||
const prefix = loc === DEFAULT_LOCALE ? "" : `/${loc}`;
|
const prefix = `/${loc}`;
|
||||||
languages[loc] = `${baseUrl}${prefix}`;
|
languages[loc] = `${baseUrl}${prefix}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ export async function generateMetadata({ params }: { params: Promise<{ locale: s
|
|||||||
setRequestLocale(validLocale);
|
setRequestLocale(validLocale);
|
||||||
|
|
||||||
// Build canonical URL
|
// Build canonical URL
|
||||||
const localePrefix = validLocale === DEFAULT_LOCALE ? "" : `/${validLocale}`;
|
const localePrefix = `/${validLocale}`;
|
||||||
const canonicalUrl = `${baseUrl}${localePrefix || '/'}`;
|
const canonicalUrl = `${baseUrl}${localePrefix}`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: metadata.home.title,
|
title: metadata.home.title,
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export async function generateMetadata({ params }: ProductPageProps): Promise<Me
|
|||||||
const secondaryKeywords = keywords.secondary.map(replaceTemplate);
|
const secondaryKeywords = keywords.secondary.map(replaceTemplate);
|
||||||
|
|
||||||
// Build canonical URL
|
// Build canonical URL
|
||||||
const localePrefix = validLocale === DEFAULT_LOCALE ? "" : `/${validLocale}`;
|
const localePrefix = `/${validLocale}`;
|
||||||
const canonicalUrl = `${baseUrl}${localePrefix}/products/${slug}`;
|
const canonicalUrl = `${baseUrl}${localePrefix}/products/${slug}`;
|
||||||
|
|
||||||
// Get product image for OpenGraph
|
// Get product image for OpenGraph
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ export async function generateMetadata({ params }: ProductsPageProps): Promise<M
|
|||||||
const keywords = getPageKeywords(validLocale as Locale, 'products');
|
const keywords = getPageKeywords(validLocale as Locale, 'products');
|
||||||
|
|
||||||
// Build canonical URL
|
// Build canonical URL
|
||||||
const localePrefix = validLocale === DEFAULT_LOCALE ? "" : `/${validLocale}`;
|
const localePrefix = `/${validLocale}`;
|
||||||
const canonicalUrl = `${baseUrl}${localePrefix}/products`;
|
const canonicalUrl = `${baseUrl}${localePrefix}/products`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { useTranslations, useLocale } from "next-intl";
|
|||||||
import { useSaleorCheckoutStore } from "@/stores/saleorCheckoutStore";
|
import { useSaleorCheckoutStore } from "@/stores/saleorCheckoutStore";
|
||||||
import { formatPrice } from "@/lib/saleor";
|
import { formatPrice } from "@/lib/saleor";
|
||||||
import { useAnalytics } from "@/lib/analytics";
|
import { useAnalytics } from "@/lib/analytics";
|
||||||
|
import { FREE_SHIPPING_THRESHOLD_RSD } from "@/lib/config/shipping";
|
||||||
|
|
||||||
export default function CartDrawer() {
|
export default function CartDrawer() {
|
||||||
const t = useTranslations("Cart");
|
const t = useTranslations("Cart");
|
||||||
@@ -251,9 +252,9 @@ export default function CartDrawer() {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(checkout?.subtotalPrice?.gross?.amount || 0) < 5000 && (
|
{(checkout?.subtotalPrice?.gross?.amount || 0) < FREE_SHIPPING_THRESHOLD_RSD && (
|
||||||
<p className="text-xs text-[#666666] text-center">
|
<p className="text-xs text-[#666666] text-center">
|
||||||
{t("freeShippingOver", { amount: formatPrice(5000) })}
|
{t("freeShippingOver", { amount: formatPrice(FREE_SHIPPING_THRESHOLD_RSD) })}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
|
import { FREE_SHIPPING_THRESHOLD_RSD } from "@/lib/config/shipping";
|
||||||
|
|
||||||
export default function TickerBar() {
|
export default function TickerBar() {
|
||||||
const items = [
|
const items = [
|
||||||
"Free shipping on orders over 10000 RSD",
|
`Free shipping on orders over ${FREE_SHIPPING_THRESHOLD_RSD} RSD`,
|
||||||
"Natural ingredients",
|
"Natural ingredients",
|
||||||
"Cruelty-free",
|
"Cruelty-free",
|
||||||
"Handmade with love",
|
"Handmade with love",
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* Shipping configuration
|
||||||
|
* Centralized configuration for shipping rules and thresholds
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free shipping threshold in RSD (Serbian Dinar)
|
||||||
|
* Orders above this amount qualify for free shipping
|
||||||
|
*/
|
||||||
|
export const FREE_SHIPPING_THRESHOLD_RSD = 10000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default shipping cost in RSD when order is below threshold
|
||||||
|
*/
|
||||||
|
export const DEFAULT_SHIPPING_COST_RSD = 500;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Currency code for shipping calculations
|
||||||
|
*/
|
||||||
|
export const SHIPPING_CURRENCY = "RSD";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an order qualifies for free shipping
|
||||||
|
* @param orderTotal - The total amount of the order
|
||||||
|
* @returns boolean indicating if order qualifies for free shipping
|
||||||
|
*/
|
||||||
|
export function qualifiesForFreeShipping(orderTotal: number): boolean {
|
||||||
|
return orderTotal >= FREE_SHIPPING_THRESHOLD_RSD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate shipping cost based on order total
|
||||||
|
* @param orderTotal - The total amount of the order
|
||||||
|
* @returns Shipping cost (0 if qualifies for free shipping)
|
||||||
|
*/
|
||||||
|
export function calculateShippingCost(orderTotal: number): number {
|
||||||
|
return qualifiesForFreeShipping(orderTotal) ? 0 : DEFAULT_SHIPPING_COST_RSD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the remaining amount needed for free shipping
|
||||||
|
* @param orderTotal - The current order total
|
||||||
|
* @returns Amount needed to reach free shipping threshold (0 if already qualified)
|
||||||
|
*/
|
||||||
|
export function getRemainingForFreeShipping(orderTotal: number): number {
|
||||||
|
if (qualifiesForFreeShipping(orderTotal)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return FREE_SHIPPING_THRESHOLD_RSD - orderTotal;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user