cms/resources/js/components/admin/ThemeIndex.svelte

151 lines
5.4 KiB
Svelte
Raw Permalink Normal View History

<script>
let { themes, activeTheme, adminPath } = $props();
let currentActive = $state(null);
$effect(() => {
currentActive = activeTheme;
});
let processing = $state(null);
let uploading = $state(false);
let fileInput;
async function activateTheme(themeSlug) {
if (processing) return;
processing = themeSlug;
try {
const baseUrl = window.location.origin.endsWith('/') ? window.location.origin : `${window.location.origin}/`;
const path = adminPath.startsWith('/') ? adminPath.substring(1) : adminPath;
const url = `${baseUrl}${path}/themes/activate`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
'Accept': 'application/json'
},
body: JSON.stringify({ theme: themeSlug })
});
const data = await response.json();
if (response.ok) {
currentActive = themeSlug;
// Optional: show success message
} else {
alert(data.message || 'Failed to activate theme.');
}
} catch (error) {
console.error('Error activating theme:', error);
alert('An error occurred while activating the theme.');
} finally {
processing = null;
}
}
async function handleUpload(e) {
const file = e.target.files[0];
if (!file) return;
uploading = true;
const formData = new FormData();
formData.append('theme_zip', file);
formData.append('_token', document.querySelector('meta[name="csrf-token"]').getAttribute('content'));
try {
const baseUrl = window.location.origin.endsWith('/') ? window.location.origin : `${window.location.origin}/`;
const path = adminPath.startsWith('/') ? adminPath.substring(1) : adminPath;
const url = `${baseUrl}${path}/themes/upload`;
const response = await fetch(url, {
method: 'POST',
headers: {
'Accept': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
},
body: formData
});
const data = await response.json();
if (response.ok) {
// Refresh themes list or add the new theme to state
// For simplicity, refresh the page since we don't have a direct themes list update function here
window.location.reload();
} else {
alert(data.message || 'Failed to upload theme.');
}
} catch (error) {
console.error('Error uploading theme:', error);
alert('An error occurred while uploading the theme.');
} finally {
uploading = false;
fileInput.value = '';
}
}
</script>
<div class="ui container">
<div class="ui grid">
<div class="ten wide column">
<h1 class="ui header">
<i class="paint brush icon"></i>
<div class="content">
Theme Management
<div class="sub header">Manage your site's appearance by selecting a theme.</div>
</div>
</h1>
</div>
<div class="six wide column right aligned">
<input
type="file"
bind:this={fileInput}
onchange={handleUpload}
accept=".zip"
style="display: none;"
>
<button
class="ui primary button {uploading ? 'loading' : ''}"
onclick={() => fileInput.click()}
disabled={uploading}
>
<i class="upload icon"></i> Upload Theme
</button>
</div>
<div class="sixteen wide column">
<div class="ui divider"></div>
</div>
</div>
<div class="ui three cards">
{#each themes as theme}
<div class="card {currentActive === theme.slug ? 'blue' : ''}">
<div class="content">
<div class="header">{theme.title}</div>
<div class="meta">By {theme.author} | v{theme.version || '1.0.0'}</div>
<div class="description">
{theme.description}
</div>
</div>
<div class="extra content">
{#if currentActive === theme.slug}
<button class="ui fluid disabled button">
<i class="check icon"></i> Active
</button>
{:else}
<button
class="ui fluid primary button {processing === theme.slug ? 'loading' : ''}"
onclick={() => activateTheme(theme.slug)}
disabled={processing !== null}
>
Activate
</button>
{/if}
</div>
</div>
{/each}
</div>
</div>