dynamic region selection

This commit is contained in:
nomad 2025-06-13 14:28:42 +03:00
parent 68eee09cf3
commit 9342518a85
7 changed files with 173 additions and 6 deletions

View file

@ -1,3 +1,7 @@
<script>
import RegionSelector from './RegionSelector.svelte';
</script>
<footer class="footer p-10 bg-neutral text-neutral-content">
<div>
<span class="footer-title">Standard Marine GCC</span>
@ -17,6 +21,10 @@
<p>Email: info@standardmarinegcc.com</p>
<p>Working Hours: 24/7</p>
</div>
<div>
<span class="footer-title">Region Settings</span>
<RegionSelector />
</div>
<div>
<span class="footer-title">Social</span>
<div class="grid grid-flow-col gap-4">

View file

@ -0,0 +1,73 @@
<script lang="ts">
import { onMount } from 'svelte';
import { region } from '$lib/stores/region';
import type { Region } from '$lib/stores/region';
import { PUBLIC_MEDUSA_KEY } from '$env/static/public';
let regions: Region[] = [];
let selectedRegion: Region;
let loading = true;
onMount(async () => {
try {
const response = await fetch('http://localhost:9000/store/regions', {
headers: {
'x-publishable-api-key': PUBLIC_MEDUSA_KEY,
}
});
if (!response.ok) {
throw new Error('Failed to fetch regions');
}
const data = await response.json();
console.log(data);
regions = data.regions;
// Set the selected region from the store
selectedRegion = $region;
} catch (error) {
console.error('Error fetching regions:', error);
} finally {
loading = false;
}
});
function handleRegionChange(event: Event) {
const select = event.target as HTMLSelectElement;
const newRegion = regions.find(r => r.id === select.value);
if (newRegion) {
region.setRegion(newRegion);
selectedRegion = newRegion;
// Set cookie for server-side access
document.cookie = `selectedRegion=${newRegion.id}; path=/; max-age=31536000`; // 1 year expiry
// Reload the page to fetch products with new region
window.location.reload();
}
}
</script>
<div class="form-control w-full">
<label class="label" for="region-select">
<span class="label-text text-neutral-content">Region</span>
</label>
<select
id="region-select"
class="select select-bordered w-full bg-neutral text-neutral-content border-neutral-content/20"
value={selectedRegion?.id}
on:change={handleRegionChange}
disabled={loading}
>
{#if loading}
<option value="">Loading regions...</option>
{:else}
{#each regions as region}
<option value={region.id}>
{region.name} ({region.currency_code.toUpperCase()})
</option>
{/each}
{/if}
</select>
</div>

View file

@ -38,7 +38,7 @@
}}
>
{#each product.variants as variant}
<option value={variant.id}>{variant.title} {variant.calculated_price.calculated_amount} </option>
<option value={variant.id}>{variant.title} {variant.calculated_price.calculated_amount} {variant.calculated_price.currency_code}</option>
{/each}
</select>
<button

View file

@ -88,7 +88,7 @@
<div class="space-y-6">
<div>
<h1 class="text-3xl font-bold">{product.title}</h1>
<h1 class="text-3xl font-bold">{selectedVariant.calculated_price.calculated_amount} </h1>
<h1 class="text-3xl font-bold">{selectedVariant.calculated_price.calculated_amount} {selectedVariant.calculated_price.currency_code}</h1>
</div>
{#each product.options as option}

82
src/lib/stores/region.ts Normal file
View file

@ -0,0 +1,82 @@
import { writable } from 'svelte/store';
export interface Region {
id: string;
name: string;
currency_code: string;
tax_rate: number;
tax_code: string | null;
countries: {
id: number;
iso_2: string;
iso_3: string;
name: string;
display_name: string;
region_id: string | null;
num_iso: string;
}[];
}
function createRegionStore() {
// Initialize with default region
const defaultRegion = {
id: 'reg_01JXB17SNW6VA5WJVV8QPHKAY3',
name: 'EU',
currency_code: 'eur',
tax_rate: 0,
tax_code: null,
countries: []
};
let initialRegion = defaultRegion;
// Only try to get from localStorage if we're in the browser
if (typeof window !== 'undefined') {
const savedRegion = localStorage.getItem('selectedRegion');
if (savedRegion) {
try {
const parsed = JSON.parse(savedRegion);
if (parsed && typeof parsed === 'object' && 'id' in parsed) {
initialRegion = parsed;
}
} catch (e) {
console.warn('Failed to parse stored region, using default', e);
localStorage.removeItem('selectedRegion'); // Clear invalid data
}
}
}
const { subscribe, set, update } = writable<Region>(initialRegion);
return {
subscribe,
setRegion: (region: Region) => {
if (typeof window !== 'undefined') {
try {
localStorage.setItem('selectedRegion', JSON.stringify(region));
} catch (e) {
console.error('Failed to save region to localStorage', e);
}
}
set(region);
},
getRegion: () => {
if (typeof window !== 'undefined') {
const savedRegion = localStorage.getItem('selectedRegion');
if (savedRegion) {
try {
const parsed = JSON.parse(savedRegion);
if (parsed && typeof parsed === 'object' && 'id' in parsed) {
return parsed;
}
} catch (e) {
console.warn('Failed to parse stored region, using default', e);
}
}
}
return defaultRegion;
}
};
}
export const region = createRegionStore();

View file

@ -1,8 +1,10 @@
import { PUBLIC_MEDUSA_KEY } from '$env/static/public';
export async function load() {
export async function load({ cookies }) {
const regionId = cookies.get('selectedRegion');
const res = await fetch(
`http://localhost:9000/store/products?region_id=reg_01JXB17SNW6VA5WJVV8QPHKAY3`,
`http://localhost:9000/store/products?region_id=${regionId}`,
{
headers: {
'x-publishable-api-key': PUBLIC_MEDUSA_KEY,

View file

@ -1,9 +1,11 @@
import type { PageServerLoad } from './$types';
import { PUBLIC_MEDUSA_KEY } from '$env/static/public';
export const load = (async ({ params }) => {
export const load = (async ({ params, cookies }) => {
const regionId = cookies.get('selectedRegion');
const res = await fetch(
`http://localhost:9000/store/products/${params.id}?region_id=reg_01JXB17SNW6VA5WJVV8QPHKAY3`,
`http://localhost:9000/store/products/${params.id}?region_id=${regionId}`,
{
headers: {
'x-publishable-api-key': PUBLIC_MEDUSA_KEY,