Skip to content

Commit f9d1bdf

Browse files
committed
feat: added modal when updating configurations
1 parent e11e586 commit f9d1bdf

File tree

12 files changed

+160
-7
lines changed

12 files changed

+160
-7
lines changed

app/Actions/Admin/Settings/Configurations.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace App\Actions\Admin\Settings;
44

5+
use App\Models\Configuration;
56
use App\Traits\CustomControllerResponsesTrait;
67
use App\Traits\ThemesTrait;
78
use Illuminate\Http\Request;
@@ -15,12 +16,29 @@ class Configurations
1516

1617
public function asController(Request $request)
1718
{
18-
$data = redis()->get('configurations');
19+
$data = Configuration::get();
1920

2021
if($request->isMethod('get')) {
2122
return $this->generateBackendPage('Admin/Settings/Configurations', [
2223
'configurations' => $data,
2324
]);
2425
}
26+
27+
$request->validate([
28+
'name' => 'required|string',
29+
'id' => 'required|integer',
30+
]);
31+
32+
$config = Configuration::findOrFail($request->id);
33+
$resp = $config->update([
34+
'value' => $request->value,
35+
]);
36+
37+
if($resp) {
38+
// refresh redis
39+
resetRedis('update-configurations');
40+
}
41+
42+
return $this->respJuicer($resp);
2543
}
2644
}

app/Library/helpers.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
use App\Models\Configuration;
44
use App\Repositories\RedisRepository;
5+
use App\Repositories\SystemInfoRepository;
56
use Illuminate\Http\Resources\Json\JsonResource;
67
use Illuminate\Http\Resources\Json\ResourceCollection;
78
use Illuminate\Support\Facades\Artisan;
@@ -75,6 +76,22 @@ function redis()
7576
}
7677
}
7778

79+
80+
if (! function_exists('resetRedis'))
81+
{
82+
/**
83+
* reset redis after setting update
84+
*
85+
* @param string $target
86+
*/
87+
function resetRedis($target = 'redis')
88+
{
89+
// refresh redis
90+
$repo = resolve(SystemInfoRepository::class);
91+
$repo->reset($target);
92+
}
93+
}
94+
7895
if (!function_exists('setting'))
7996
{
8097
/**

app/Models/Configuration.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,18 @@ public function __construct(array $attributes = [])
2626
parent::__construct($attributes);
2727
}
2828

29+
public function getValueAttribute()
30+
{
31+
if ($this->type == self::TYPE_BOOL) {
32+
return (bool) $this->attributes['value'];
33+
}
34+
35+
if ($this->type == self::TYPE_NUMBER) {
36+
return strpos($this->attributes['value'], '.') !== false
37+
? (int) $this->attributes['value']
38+
: (float) $this->attributes['value'];
39+
}
40+
41+
return $this->attributes['value'];
42+
}
2943
}

resources/css/app.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ font-family: 'Inter', sans-serif;
3535
.roboto {
3636
font-family: 'Roboto', sans-serif;
3737
}
38+
.modal-footer {
39+
@apply mt-5;
40+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h2><slot /></h2>

resources/ts/Layouts/MainLayout.svelte

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script lang="ts">
2-
import { AppShell, Toast, type ToastSettings, toastStore } from '@skeletonlabs/skeleton'
2+
import { AppShell, Toast, type ToastSettings, toastStore, Modal } from '@skeletonlabs/skeleton'
33
import { page } from '@inertiajs/svelte'
44
55
$: title = `${$page.props.title ?? 'Welcome'} | ${$page.props.siteName}`
@@ -22,6 +22,8 @@
2222
</svelte:head>
2323

2424
<div style="display: contents" class="min-h-screen overflow-hidden">
25+
<Modal />
26+
2527
{#if withShell}
2628
<AppShell>
2729
<Toast position="br" />

resources/ts/Pages/Admin/Dashboard.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import { fly } from 'svelte/transition'
44
import { quintOut } from 'svelte/easing'
55
import { onMount } from 'svelte'
6+
import Title from '@/Components/Title.svelte'
67
78
let ready = false
89
onMount(() => (ready = true))
@@ -11,7 +12,7 @@
1112
<div class="container mt-5">
1213
{#if ready}
1314
<div in:fly={{ y: -70, duration: 300, easing: quintOut }}>
14-
<h2>Admin Dashboard</h2>
15+
<Title>Admin Dashboard</Title>
1516
<a href="/" use:inertia>Go Home</a>
1617
</div>
1718
{/if}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
<script lang="ts">
2+
import { modalStore } from '@skeletonlabs/skeleton'
3+
import { useForm } from '@inertiajs/svelte'
4+
import type { SystemConfiguration } from '@/types'
5+
import { snakeCaseToSentenceCaseCapitalizeWords } from '@/helpers'
6+
import {} from 'os'
7+
import Button from '@/Components/Button.svelte'
8+
9+
// Base Classes
10+
const cBase = 'card p-4 w-modal shadow-xl space-y-4'
11+
const cHeader = 'text-2xl font-bold'
12+
const cForm = 'border border-surface-500 p-4 space-y-4 rounded-container-token'
13+
14+
// Props
15+
/** Exposes parent props to this component. */
16+
export let parent: any
17+
export let configuration: SystemConfiguration
18+
export let title: string
19+
20+
// Form Data
21+
let form = useForm({
22+
name: configuration.name,
23+
id: configuration.id,
24+
value: configuration.value,
25+
})
26+
27+
function handleSubmit(): void {
28+
$form.post(route('admin.settings.configurations'), {
29+
onSuccess: () => {
30+
modalStore.close()
31+
},
32+
})
33+
}
34+
</script>
35+
36+
<div class={cBase}>
37+
<header class={cHeader}>{title}</header>
38+
39+
<form on:submit|preventDefault={handleSubmit}>
40+
<div class="modal-form {cForm}" on:submit|preventDefault={handleSubmit}>
41+
<label class="label">
42+
<span>Name</span>
43+
<input
44+
class="input"
45+
type="text"
46+
required
47+
value={snakeCaseToSentenceCaseCapitalizeWords(configuration.name)}
48+
disabled
49+
placeholder="Name"
50+
/>
51+
</label>
52+
{#if configuration.type == 'bool'}
53+
<label class="flex items-center space-x-2">
54+
<p>Value</p>
55+
<input class="checkbox" type="checkbox" bind:checked={$form.value} />
56+
</label>
57+
{:else if configuration.type == 'number'}
58+
<label class="label">
59+
<span>Value</span>
60+
<input class="input" type="number" required bind:value={$form.value} placeholder="Value" />
61+
</label>
62+
{:else}
63+
<label class="label">
64+
<span>Value</span>
65+
<input class="input" type="text" required bind:value={$form.value} placeholder="Value" />
66+
</label>
67+
{/if}
68+
</div>
69+
70+
<footer class="modal-footer {parent.regionFooter}">
71+
<Button color="ghost" type="button" on:click={parent.onClose}>{parent.buttonTextCancel}</Button>
72+
<Button type="submit" loading={$form.processing}>Submit</Button>
73+
</footer>
74+
</form>
75+
</div>

resources/ts/Pages/Admin/Settings/Configurations.svelte

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
<script lang="ts">
22
import Circle from '@/Components/Circle.svelte'
33
import SimpleTable from '@/Components/SimpleTable.svelte'
4+
import Title from '@/Components/Title.svelte'
45
import { snakeCaseToSentenceCaseCapitalizeWords } from '@/helpers'
56
import type { SystemConfiguration } from '@/types'
7+
import { modalStore } from '@skeletonlabs/skeleton'
8+
import type { ModalSettings, ModalComponent } from '@skeletonlabs/skeleton'
9+
import ConfigurationModal from './ConfigurationModal.svelte'
610
711
export let configurations: SystemConfiguration[]
812
let search: string | undefined
@@ -18,6 +22,22 @@
1822
1923
function editItem(item: SystemConfiguration) {
2024
console.log('item', item)
25+
26+
const modalComponent: ModalComponent = {
27+
// Pass a reference to your custom component
28+
ref: ConfigurationModal,
29+
// Add the component properties as key/value pairs
30+
props: { configuration: item, title: 'Update Configuration' },
31+
// Provide a template literal for the default component slot
32+
slot: '<p>Modal</p>',
33+
}
34+
35+
const d: ModalSettings = {
36+
type: 'component',
37+
// Pass the component registry key as a string:
38+
component: modalComponent,
39+
}
40+
modalStore.trigger(d)
2141
}
2242
2343
function handleSearch(e: CustomEvent) {
@@ -26,7 +46,7 @@
2646
</script>
2747

2848
<div class="container mt-5">
29-
<h2>Configurations</h2>
49+
<Title>Configurations</Title>
3050
<br />
3151
<SimpleTable {headers} hasFooter hasSearch on:search={handleSearch}>
3252
{#each filteredList as item, i}

resources/ts/Pages/Admin/Settings/ResetSystem.svelte

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import type { ResetSystemAction } from '@/types'
33
import Button from '@/Components/Button.svelte'
44
import { useForm } from '@inertiajs/svelte'
5+
import Title from '@/Components/Title.svelte'
56
67
export let actions: ResetSystemAction[]
78
@@ -17,7 +18,7 @@
1718
</script>
1819

1920
<div class="container mt-5">
20-
<h2>Reset System</h2>
21+
<Title>Reset System</Title>
2122
<br />
2223
<div class="card p-4">
2324
<div class="flex flex-wrap gap-4">

0 commit comments

Comments
 (0)