Compare commits
3 Commits
0b71434fc5
...
7373a25a84
| Author | SHA1 | Date | |
|---|---|---|---|
| 7373a25a84 | |||
| fefb96daaa | |||
| 8caa23d716 |
@@ -36,7 +36,8 @@
|
||||
"vite": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@inlang/paraglide-sveltekit": "^0.15.5"
|
||||
"@inlang/paraglide-sveltekit": "^0.15.5",
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"pnpm": {
|
||||
"onlyBuiltDependencies": [
|
||||
|
||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -11,6 +11,9 @@ importers:
|
||||
'@inlang/paraglide-sveltekit':
|
||||
specifier: ^0.15.5
|
||||
version: 0.15.5(@sveltejs/kit@2.20.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.23.1)(vite@6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)))(svelte@5.23.1)(vite@6.2.2(@types/node@22.13.10)(jiti@2.4.2)(lightningcss@1.29.2)))
|
||||
lodash:
|
||||
specifier: ^4.17.21
|
||||
version: 4.17.21
|
||||
devDependencies:
|
||||
'@eslint/compat':
|
||||
specifier: ^1.2.5
|
||||
@@ -1561,6 +1564,9 @@ packages:
|
||||
lodash.once@4.1.1:
|
||||
resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==}
|
||||
|
||||
lodash@4.17.21:
|
||||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
|
||||
magic-string@0.30.17:
|
||||
resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==}
|
||||
|
||||
@@ -3582,6 +3588,8 @@ snapshots:
|
||||
|
||||
lodash.once@4.1.1: {}
|
||||
|
||||
lodash@4.17.21: {}
|
||||
|
||||
magic-string@0.30.17:
|
||||
dependencies:
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
35
src/lib/FormInput.svelte
Normal file
35
src/lib/FormInput.svelte
Normal file
@@ -0,0 +1,35 @@
|
||||
<script lang="ts" generics="T extends Record<string, unknown>">
|
||||
import { Field, Control, FieldErrors } from "formsnap";
|
||||
import type { FormPath, SuperForm } from "sveltekit-superforms";
|
||||
|
||||
let { form, type, label, name }: {
|
||||
form: SuperForm<T>,
|
||||
type: string,
|
||||
label: string,
|
||||
name: FormPath<T>,
|
||||
} = $props();
|
||||
const formData = form.form;
|
||||
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Field {form} {name}>
|
||||
<Control>
|
||||
{#snippet children({ props })}
|
||||
<label class="label floating-label w-full">
|
||||
<span>{label}</span>
|
||||
<input {type} class="input w-full aria-[invalid]:input-error" placeholder={label}
|
||||
bind:value={$formData[name]} {...props}
|
||||
/>
|
||||
</label>
|
||||
{/snippet}
|
||||
</Control>
|
||||
<FieldErrors>
|
||||
{#snippet children({ errors, errorProps })}
|
||||
{#each errors as err, idx (idx)}
|
||||
<p class="text-error" {...errorProps}>{err}</p>
|
||||
{/each}
|
||||
{/snippet}
|
||||
</FieldErrors>
|
||||
</Field>
|
||||
</div>
|
||||
@@ -1,22 +1,47 @@
|
||||
<script lang="ts">
|
||||
<script lang="ts" generics="T extends Record<string, unknown>">
|
||||
import { Field, Control, FieldErrors } from "formsnap";
|
||||
import type { FormPath, SuperForm } from "sveltekit-superforms";
|
||||
import Icon from "@iconify/svelte";
|
||||
|
||||
let { value = $bindable(), label, class: className = '', ...props } = $props();
|
||||
let { form, label, name }: {
|
||||
form: SuperForm<T>,
|
||||
label: string,
|
||||
name: FormPath<T>,
|
||||
} = $props();
|
||||
const formData = form.form;
|
||||
|
||||
let show = $state(false);
|
||||
let inputType = $derived(show ? 'text' : 'password');
|
||||
let type = $derived(show ? 'text' : 'password');
|
||||
|
||||
</script>
|
||||
|
||||
<div class="flex w-full gap-1">
|
||||
<label class="label floating-label w-full">
|
||||
<span>{label}</span>
|
||||
<input type={inputType} class={["input w-full", className]} placeholder={label} {...props} bind:value={value}/>
|
||||
</label>
|
||||
<button class="btn btn-circle" onclick={() => show = !show}>
|
||||
{#if show}
|
||||
<Icon icon="mdi:eye-off-outline"/>
|
||||
{:else }
|
||||
<Icon icon="mdi:eye-outline"/>
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<Field {form} {name}>
|
||||
<Control>
|
||||
{#snippet children({ props })}
|
||||
<div class="flex w-full gap-1">
|
||||
<label class="label floating-label w-full">
|
||||
<span>{label}</span>
|
||||
<input {type} class="input w-full aria-[invalid]:input-error" placeholder={label}
|
||||
bind:value={$formData[name]} {...props}
|
||||
/>
|
||||
</label>
|
||||
<button class="btn btn-circle" onclick={() => show = !show}>
|
||||
{#if show}
|
||||
<Icon icon="mdi:eye-off-outline"/>
|
||||
{:else }
|
||||
<Icon icon="mdi:eye-outline"/>
|
||||
{/if}
|
||||
</button>
|
||||
</div>
|
||||
{/snippet}
|
||||
</Control>
|
||||
<FieldErrors>
|
||||
{#snippet children({ errors, errorProps })}
|
||||
{#each errors as err, idx (idx)}
|
||||
<p class="text-error" {...errorProps}>{err}</p>
|
||||
{/each}
|
||||
{/snippet}
|
||||
</FieldErrors>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ export const actions = {
|
||||
username: data.get('username'),
|
||||
password: data.get('password')
|
||||
};
|
||||
//"/api/public/1/auth/login/"
|
||||
|
||||
const response = await event.fetch("/api/public/1/auth/login/", {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(payload),
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Actions } from './$types';
|
||||
import { superValidate } from 'sveltekit-superforms';
|
||||
import { arktype } from 'sveltekit-superforms/adapters';
|
||||
import { message } from 'sveltekit-superforms';
|
||||
import { fail } from '@sveltejs/kit';
|
||||
import { schema, defaults } from './schema';
|
||||
|
||||
export const load = async () => {
|
||||
@@ -13,21 +13,50 @@ export const load = async () => {
|
||||
};
|
||||
|
||||
export const actions = {
|
||||
default: async ({ request }) => {
|
||||
default: async ({ request, fetch }) => {
|
||||
const form = await superValidate(request, arktype(schema, { defaults }));
|
||||
console.log(form);
|
||||
|
||||
if (!form.valid) {
|
||||
// Return { form } and things will just work.
|
||||
return fail(400, { form });
|
||||
// return fail(400, { form });
|
||||
return message(form, {
|
||||
status: 'error',
|
||||
text: 'Invalid Form'
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Do something with the validated form.data
|
||||
// Create User
|
||||
const payload = {
|
||||
username: form.data.username,
|
||||
email: form.data.email,
|
||||
password: form.data.password,
|
||||
features: {},
|
||||
};
|
||||
const response = await fetch("/api/internal/current/users/", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(payload),
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
if (response.status >= 500) {
|
||||
console.error(`INTERNAL SERVER ERROR ${response.status}:\n${await response.text()}`);
|
||||
return message(form, {
|
||||
status: 'error',
|
||||
text: `Internal Server Error ${response.status}`
|
||||
});
|
||||
}
|
||||
if (response.status !== 201) return message(form, {
|
||||
status: 'error',
|
||||
text: `HTTP Code ${response.status}:\n${JSON.stringify(await response.json(), null, 2)}`
|
||||
}, { status: 400 });
|
||||
|
||||
// Return the form with a status message
|
||||
return message(form, {
|
||||
status: 'success',
|
||||
text: 'Form posted successfully!',
|
||||
text: `Form posted successfully!\n${JSON.stringify(await response.json(), null, 2)}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
} satisfies Actions;
|
||||
|
||||
@@ -3,105 +3,83 @@
|
||||
import { arktypeClient } from 'sveltekit-superforms/adapters';
|
||||
import PwdFormInput from "$lib/PwdFormInput.svelte";
|
||||
import { schema } from './schema';
|
||||
import FormInput from "$lib/FormInput.svelte";
|
||||
|
||||
let { data } = $props();
|
||||
const { form, errors, constraints, message, enhance } = superForm(data.form, {
|
||||
const form = superForm(data.form, {
|
||||
validators: arktypeClient(schema),
|
||||
resetForm: false,
|
||||
});
|
||||
const { message, enhance } = form;
|
||||
</script>
|
||||
|
||||
<div class="mx-auto w-sm">
|
||||
<!-- TODO: Do the new Form using https://www.formsnap.dev/docs/quick-start -->
|
||||
<form class="fieldset mt-4 bg-base-200 border border-base-300 p-4 rounded-box gap-4" method="POST" use:enhance>
|
||||
<h1 class="card-title">Create User</h1>
|
||||
<div>
|
||||
<label class="label floating-label w-full">
|
||||
<span>Username</span>
|
||||
<input type="text" class={["input w-full", $errors['username'] && 'input-error']}
|
||||
placeholder="Username" name="username"
|
||||
aria-invalid={$errors['username'] ? 'true' : undefined}
|
||||
bind:value={$form.username}
|
||||
{...$constraints.username}
|
||||
/>
|
||||
</label>
|
||||
<p class="text-error">{$errors['username'] ?? ''}</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="label floating-label w-full">
|
||||
<span>Email</span>
|
||||
<input type="email" class={["input w-full", $errors['email'] && 'input-error']} placeholder="Email"
|
||||
name="email"
|
||||
aria-invalid={$errors['email'] ? 'true' : undefined}
|
||||
bind:value={$form.email}
|
||||
{...$constraints.email}
|
||||
/>
|
||||
</label>
|
||||
<p class="text-error">{$errors['email'] ?? ''}</p>
|
||||
</div>
|
||||
<div>
|
||||
<PwdFormInput label="Password" autocomplete="new-password" name="password"
|
||||
class={$errors['password'] && 'input-error'}
|
||||
aria-invalid={$errors['password'] ? 'true' : undefined}
|
||||
bind:value={$form.password}
|
||||
{...$constraints.password}
|
||||
/>
|
||||
<p class="text-error">{$errors['password'] ?? ''}</p>
|
||||
</div>
|
||||
<div>
|
||||
<PwdFormInput label="Re-insert password" autocomplete="new-password" name="confirmPassword"
|
||||
class={$errors['confirmPassword'] && 'input-error'}
|
||||
aria-invalid={$errors['confirmPassword'] ? 'true' : undefined}
|
||||
bind:value={$form.confirmPassword}
|
||||
{...$constraints.confirmPassword}
|
||||
/>
|
||||
<p class="text-error">{$errors['confirmPassword'] ?? ''}</p>
|
||||
</div>
|
||||
<label class="label">
|
||||
<span>RossiniEnergy Staff</span>
|
||||
<input type="checkbox" class="checkbox"/>
|
||||
</label>
|
||||
<button class="btn btn-primary">SUBMIT</button>
|
||||
{#if $message}
|
||||
<div
|
||||
class:success={$message['status'] === 'success'}
|
||||
class:error={$message['status'] === 'error'}
|
||||
>
|
||||
{$message['text']}
|
||||
<div>
|
||||
<div class="mx-auto w-sm">
|
||||
<!-- TODO: Do the new Form using https://www.formsnap.dev/docs/quick-start -->
|
||||
<form class="fieldset mt-4 bg-base-200 border border-base-300 p-4 rounded-box gap-4" method="POST" use:enhance>
|
||||
<h1 class="card-title">Create User</h1>
|
||||
<div>
|
||||
<FormInput {form} type="text" label="Username" name="username"/>
|
||||
</div>
|
||||
{/if}
|
||||
<!-- <fieldset class="fieldset w-sm bg-base-200 border border-base-300 p-4 rounded-box gap-4">-->
|
||||
<!-- <legend class="fieldset-legend">Park Admin Feature</legend>-->
|
||||
<!-- <label class="label">-->
|
||||
<!-- <span>Enable</span>-->
|
||||
<!-- <input type="checkbox" class="checkbox"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <div class="fieldset gap-4">-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="checkbox" class="checkbox" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- </div>-->
|
||||
<!-- </fieldset>-->
|
||||
</form>
|
||||
<div>
|
||||
<FormInput {form} type="email" label="Email" name="email"/>
|
||||
</div>
|
||||
<div>
|
||||
<PwdFormInput {form} label="Password" name="password"/>
|
||||
</div>
|
||||
<div>
|
||||
<PwdFormInput {form} label="Re-insert password" name="confirmPassword"/>
|
||||
</div>
|
||||
<label class="label">
|
||||
<span>RossiniEnergy Staff</span>
|
||||
<input type="checkbox" class="checkbox"/>
|
||||
</label>
|
||||
<button class="btn btn-primary">SUBMIT</button>
|
||||
<!-- <fieldset class="fieldset w-sm bg-base-200 border border-base-300 p-4 rounded-box gap-4">-->
|
||||
<!-- <legend class="fieldset-legend">Park Admin Feature</legend>-->
|
||||
<!-- <label class="label">-->
|
||||
<!-- <span>Enable</span>-->
|
||||
<!-- <input type="checkbox" class="checkbox"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <div class="fieldset gap-4">-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label floating-label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="text" class="input w-full" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- <label class="label">-->
|
||||
<!-- <span>Username</span>-->
|
||||
<!-- <input type="checkbox" class="checkbox" placeholder="Username"/>-->
|
||||
<!-- </label>-->
|
||||
<!-- </div>-->
|
||||
<!-- </fieldset>-->
|
||||
</form>
|
||||
</div>
|
||||
{#if $message}
|
||||
<div class="card bg-base-200 mx-auto mt-4 w-fit card-border max-w-md">
|
||||
<div class="card-body">
|
||||
<h2 class="card-title" class:text-error={$message['status'] === 'error'}>
|
||||
{$message['status'] === 'success' ? 'Success!' : 'Error'}
|
||||
</h2>
|
||||
<div>
|
||||
{$message['text']}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type } from "arktype";
|
||||
|
||||
export const schema = type({
|
||||
username: 'string',
|
||||
username: 'string > 3',
|
||||
email: 'string.email',
|
||||
password: 'string > 6',
|
||||
confirmPassword: 'string > 6'
|
||||
|
||||
30
src/routes/user/list/+page.svelte
Normal file
30
src/routes/user/list/+page.svelte
Normal file
@@ -0,0 +1,30 @@
|
||||
<script lang="ts">
|
||||
import type { PageProps } from './$types';
|
||||
|
||||
let { data }: PageProps = $props();
|
||||
</script>
|
||||
|
||||
<div class="w-full">
|
||||
<div class="overflow-x-auto rounded-box border border-base-content/5 bg-base-100">
|
||||
<table class="table">
|
||||
<!-- head -->
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Username</th>
|
||||
<th>Actions?</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- rows -->
|
||||
{#each data.users as user (user.id)}
|
||||
<tr>
|
||||
<th>{user.id}</th>
|
||||
<td>{user.username}</td>
|
||||
<td>futures?</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
12
src/routes/user/list/+page.ts
Normal file
12
src/routes/user/list/+page.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { PageLoad } from './$types';
|
||||
import type { UserShort } from "./types";
|
||||
|
||||
export const load: PageLoad = async ({ fetch }) => {
|
||||
const res = await fetch("/api/internal/current/users/?limit=100&is_readonly=0", {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
}
|
||||
});
|
||||
const users: UserShort[] = await res.json();
|
||||
return { users };
|
||||
};
|
||||
4
src/routes/user/list/types.ts
Normal file
4
src/routes/user/list/types.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export type UserShort = {
|
||||
id: number,
|
||||
username: string
|
||||
}
|
||||
Reference in New Issue
Block a user