dynamic region selection
This commit is contained in:
parent
68eee09cf3
commit
9342518a85
7 changed files with 173 additions and 6 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
<script>
|
||||||
|
import RegionSelector from './RegionSelector.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
<footer class="footer p-10 bg-neutral text-neutral-content">
|
<footer class="footer p-10 bg-neutral text-neutral-content">
|
||||||
<div>
|
<div>
|
||||||
<span class="footer-title">Standard Marine GCC</span>
|
<span class="footer-title">Standard Marine GCC</span>
|
||||||
|
@ -17,6 +21,10 @@
|
||||||
<p>Email: info@standardmarinegcc.com</p>
|
<p>Email: info@standardmarinegcc.com</p>
|
||||||
<p>Working Hours: 24/7</p>
|
<p>Working Hours: 24/7</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<span class="footer-title">Region Settings</span>
|
||||||
|
<RegionSelector />
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="footer-title">Social</span>
|
<span class="footer-title">Social</span>
|
||||||
<div class="grid grid-flow-col gap-4">
|
<div class="grid grid-flow-col gap-4">
|
||||||
|
|
73
src/lib/components/RegionSelector.svelte
Normal file
73
src/lib/components/RegionSelector.svelte
Normal 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>
|
|
@ -38,7 +38,7 @@
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{#each product.variants as variant}
|
{#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}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -88,7 +88,7 @@
|
||||||
<div class="space-y-6">
|
<div class="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<h1 class="text-3xl font-bold">{product.title}</h1>
|
<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>
|
</div>
|
||||||
|
|
||||||
{#each product.options as option}
|
{#each product.options as option}
|
||||||
|
|
82
src/lib/stores/region.ts
Normal file
82
src/lib/stores/region.ts
Normal 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();
|
|
@ -1,8 +1,10 @@
|
||||||
import { PUBLIC_MEDUSA_KEY } from '$env/static/public';
|
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(
|
const res = await fetch(
|
||||||
`http://localhost:9000/store/products?region_id=reg_01JXB17SNW6VA5WJVV8QPHKAY3`,
|
`http://localhost:9000/store/products?region_id=${regionId}`,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
'x-publishable-api-key': PUBLIC_MEDUSA_KEY,
|
'x-publishable-api-key': PUBLIC_MEDUSA_KEY,
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { PUBLIC_MEDUSA_KEY } from '$env/static/public';
|
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(
|
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: {
|
headers: {
|
||||||
'x-publishable-api-key': PUBLIC_MEDUSA_KEY,
|
'x-publishable-api-key': PUBLIC_MEDUSA_KEY,
|
||||||
|
|
Loading…
Reference in a new issue