Compare commits

..

No commits in common. "98afc28773806e05a846742a434fd5d0cbadede9" and "e225b6dcadadfa3ef249ecdacbc178566214281e" have entirely different histories.

7 changed files with 80 additions and 285 deletions

Binary file not shown.

View File

@ -1,188 +0,0 @@
/* Reset and base styles */
:root {
--primary-color: #4a90e2;
--secondary-color: #f5f5f5;
--border-color: #ddd;
--text-color: #333;
--error-color: #e74c3c;
--success-color: #2ecc71;
--shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
sans-serif;
line-height: 1.6;
color: var(--text-color);
background-color: #fff;
padding: 2rem;
}
/* Typography */
h1 {
font-size: 2rem;
margin-bottom: 1.5rem;
color: var(--text-color);
}
h2 {
font-size: 1.5rem;
margin: 1.5rem 0 1rem;
}
/* Links */
a {
color: var(--primary-color);
text-decoration: none;
transition: color 0.2s;
}
a:hover {
color: #357abd;
text-decoration: underline;
}
/* Lists */
ul {
list-style: none;
margin: 1rem 0;
}
li {
padding: 0.75rem;
border-bottom: 1px solid var(--border-color);
}
li:last-child {
border-bottom: none;
}
/* Forms */
form {
max-width: 800px;
margin: 2rem 0;
}
.form-group {
margin-bottom: 1.5rem;
}
label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
}
input[type='text'],
input[type='number'],
input[type='date'],
select,
textarea {
width: 100%;
padding: 0.75rem;
border: 1px solid var(--border-color);
border-radius: 4px;
font-size: 1rem;
margin-bottom: 1rem;
transition: border-color 0.2s;
}
input:focus,
select:focus,
textarea:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 2px rgba(74, 144, 226, 0.2);
}
textarea {
min-height: 100px;
resize: vertical;
}
/* Buttons */
button {
background-color: var(--primary-color);
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 4px;
cursor: pointer;
font-size: 1rem;
transition: background-color 0.2s;
}
button:hover:not(:disabled) {
background-color: #357abd;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
button.secondary {
background-color: var(--secondary-color);
color: var(--text-color);
border: 1px solid var(--border-color);
}
button.secondary:hover:not(:disabled) {
background-color: #e8e8e8;
}
button + button {
margin-left: 1rem;
}
/* Field management */
.field-container {
background-color: var(--secondary-color);
padding: 1rem;
border-radius: 4px;
margin-bottom: 1rem;
}
/* Submissions */
.submissions-list {
background-color: var(--secondary-color);
padding: 1rem;
border-radius: 4px;
}
.submission-item {
background-color: white;
padding: 1rem;
margin-bottom: 0.5rem;
border-radius: 4px;
box-shadow: var(--shadow);
}
/* Utility classes */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
.loading {
text-align: center;
padding: 2rem;
color: #666;
}
.error {
color: var(--error-color);
margin: 1rem 0;
}
.success {
color: var(--success-color);
margin: 1rem 0;
}

View File

@ -1,11 +0,0 @@
<nav>
<h1>Formies</h1>
<button>logout</button>
</nav>
<style>
nav {
display: flex;
justify-content: space-between;
}
</style>

View File

@ -1,7 +0,0 @@
<script lang="ts">
import Navbar from '$lib/components/Navbar.svelte';
let { children } = $props();
</script>
<Navbar></Navbar>
{@render children()}

View File

@ -6,10 +6,12 @@
let fields: FormField[] = []; let fields: FormField[] = [];
function addField() { function addField() {
// Use a new array assignment to trigger reactivity
fields = [...fields, { label: '', name: '', field_type: 'text' }]; fields = [...fields, { label: '', name: '', field_type: 'text' }];
} }
function removeField(index: number) { function removeField(index: number) {
// Reassign to trigger reactivity
fields = fields.filter((_, i) => i !== index); fields = fields.filter((_, i) => i !== index);
} }
@ -25,38 +27,36 @@
} }
</script> </script>
<div class="container"> <h1>Create Form</h1>
<h1>Create Form</h1>
<form on:submit|preventDefault={saveForm}>
<div class="form-group">
<label>Form Name:</label>
<input type="text" bind:value={name} placeholder="Enter form name" />
</div>
<h2>Fields</h2> <label>
{#each fields as field, i} Form Name:
<div class="field-container"> <input type="text" bind:value={name} placeholder="Enter form name" />
<div class="form-group"> </label>
<label>Label:</label>
<input type="text" bind:value={field.label} placeholder="Enter field label" /> <h2>Fields</h2>
</div> {#each fields as field, i}
<div class="form-group"> <div>
<label>Name:</label> <label>
<input type="text" bind:value={field.name} placeholder="Enter field name" /> Label:
</div> <input type="text" bind:value={field.label} placeholder="Enter field label" />
<div class="form-group"> </label>
<label>Type:</label> <label>
<select bind:value={field.field_type}> Name:
<option value="text">Text</option> <input type="text" bind:value={field.name} placeholder="Enter field name" />
<option value="number">Number</option> </label>
<option value="date">Date</option> <label>
<option value="textarea">Textarea</option> Type:
</select> <select bind:value={field.field_type}>
</div> <option value="text">Text</option>
<button class="secondary" on:click={() => removeField(i)}>Remove</button> <option value="number">Number</option>
</div> <option value="date">Date</option>
{/each} <option value="textarea">Textarea</option>
<button class="secondary" on:click={addField}>Add Field</button> </select>
<button type="submit" disabled={!name || fields.length === 0}>Save Form</button> </label>
</form> <button on:click={() => removeField(i)}>Remove</button>
</div> </div>
{/each}
<button on:click={addField}>Add Field</button>
<button on:click={saveForm} disabled={!name || fields.length === 0}> Save Form </button>

View File

@ -5,12 +5,13 @@
import { page } from '$app/stores'; import { page } from '$app/stores';
export let params: { id: string }; export let params: { id: string };
console.log('params.id:', params);
let form: any | null = null; let form: any | null = null;
let submissions: any[] = []; let submissions: any[] = [];
let responseData: Record<string, any> = {}; let responseData: Record<string, any> = {};
onMount(async () => { onMount(async () => {
const { id } = $page.params; const { id } = $page.params; // Use $page.params to access route parameters
if (id) { if (id) {
form = await getForms().then((forms) => forms.find((f: any) => f.id === id) || null); form = await getForms().then((forms) => forms.find((f: any) => f.id === id) || null);
submissions = await getSubmissions(id); submissions = await getSubmissions(id);
@ -20,42 +21,41 @@
}); });
async function submitResponse() { async function submitResponse() {
const { id } = $page.params; const { id } = $page.params; // Use $page.params to access route parameters
await submitForm(id, responseData); await submitForm(id, responseData);
alert('Response submitted successfully!'); alert('Response submitted successfully!');
submissions = await getSubmissions(params.id); submissions = await getSubmissions(params.id); // Refresh submissions
} }
</script> </script>
<div class="container"> <h1>{form?.name}</h1>
<h1>{form?.name}</h1>
{#if form} {#if form}
<form on:submit|preventDefault={submitResponse}> <form on:submit|preventDefault={submitResponse}>
{#each form.fields as field} {#each form.fields as field}
<div class="form-group"> <div>
<label>{field.label}</label> <!-- svelte-ignore a11y_label_has_associated_control -->
{#if field.field_type === 'text'} <label>{field.label}</label>
<input type="text" bind:value={responseData[field.name]} /> {#if field.field_type === 'text'}
{:else if field.field_type === 'number'} <input type="text" bind:value={responseData[field.name]} />
<input type="number" bind:value={responseData[field.name]} /> {:else if field.field_type === 'number'}
{:else if field.field_type === 'date'} <input type="number" bind:value={responseData[field.name]} />
<input type="date" bind:value={responseData[field.name]} /> {:else if field.field_type === 'date'}
{:else if field.field_type === 'textarea'} <input type="date" bind:value={responseData[field.name]} />
<textarea bind:value={responseData[field.name]}></textarea> {:else if field.field_type === 'textarea'}
{/if} <textarea bind:value={responseData[field.name]}></textarea>
</div> {/if}
{/each} </div>
<button type="submit">Submit</button> {/each}
</form> <button type="submit">Submit</button>
<h2>Submissions</h2> </form>
<div class="submissions-list">
{#each submissions as submission} <h2>Submissions</h2>
<div class="submission-item"> <ul>
{JSON.stringify(submission.data)} {#each submissions as submission}
</div> <li>{JSON.stringify(submission.data)}</li>
{/each} {/each}
</div> </ul>
{:else} {:else}
<p class="loading">Loading...</p> <p>Loading...</p>
{/if} {/if}
</div>

View File

@ -10,13 +10,14 @@
}); });
</script> </script>
<div class="container"> <h1>Form Management Tool</h1>
<a href="/create" class="button">Create a New Form</a>
<ul class="forms-list"> <a href="/create">Create a New Form</a>
{#each forms as form}
<li> <ul>
<a href={`/form/${form.id}`}>{form.name}</a> {#each forms as form}
</li> <li>
{/each} <a href={`/form/${form.id}`}>{form.name}</a>
</ul> </li>
</div> {/each}
</ul>