workin on document creation: frontend work

This commit is contained in:
2025-07-09 23:49:01 +02:00
parent 003899f75d
commit d68dc991d0
11 changed files with 271 additions and 20 deletions

View File

@@ -0,0 +1,37 @@
<script>
import {onMount} from 'svelte';
import {t} from '../translations.svelte.js';
let { caption, onselect = (contact) => console.log('selected '+contact.FN||contact.ORG) } = $props();
let message = t('contacts.loading');
let contacts = $state(null);
let value = 0;
async function loadContacts(){
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/contacts`;
var resp = await fetch(url,{ credentials: 'include'});
if (resp.ok){
contacts = await resp.json();
} else {
message = await resp.text();
}
}
function select(){
onselect(contacts[value]);
}
onMount(loadContacts)
</script>
{#if contacts}
<select onchange={select} bind:value>
<option value={0}>{caption}</option>
{#each contacts as contact,idx}
<option value={idx}>{contact.FN||contact.ORG}</option>
{/each}
</select>
{:else}
<span>{message}</span>
{/if}

View File

@@ -14,7 +14,6 @@ async function fetchModules(){
if (resp.ok){
const arr = await resp.json();
for (let entry of arr) modules.push({name:t('menu.'+entry.module),url:entry.url});
console.log(modules);
} else {
console.log('error');
}

View File

@@ -1,13 +1,141 @@
<script>
import { onMount } from 'svelte';
import { t } from '../../translations.svelte.js';
import { useTinyRouter } from 'svelte-tiny-router';
import ContactSelector from '../../Components/ContactSelector.svelte';
let router = useTinyRouter();
let company_id = router.query.company;
let company = $state(null);
let error = null;
let docType = $state(null);
let document = $state({
type : router.query.document_type,
company : router.query.company_id,
customer : {
addr : ''
},
sender : {
name : 'sender'
}
});
async function loadCompanies(){
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/companies`;
var resp = await fetch(url,{ credentials: 'include'});
if (resp.ok){
const companies = await resp.json();
company = companies[document.company];
document.sender.name = '';
if (company.name) document.sender.name += company.name+"\n";
if (company.address) document.sender.name += company.address+"\n";
if (company.tax_number) document.sender.tax_id = company.tax_number;
if (company.bank_account) document.sender.bank_account = company.bank_account;
if (company.court) document.sender.court = company.court;
} else {
error = await resp.text();
}
}
async function loadDocType(){
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/types`;
var resp = await fetch(url,{ credentials: 'include'});
if (resp.ok){
const types = await resp.json();
docType = t('document.type_'+types[document.type]);
} else {
error = await resp.text();
}
}
function load(){
loadCompanies();
loadDocType();
}
function contactSelected(contact){
var addr = '';
if (contact.ORG) addr += contact.ORG.trim()+"\n";
if (contact.N) {
var name = (contact.N.given+" "+contact.N.family).trim()+"\n";
if (name != addr) addr += name;
}
if (contact.ADR.street) addr += contact.ADR.street+"\n";
if (contact.ADR.locality) addr += contact.ADR.post_code + " "+ contact.ADR.locality + "\n";
if (contact.ADR.county) addr += contact.ADR.country+"\n";
document.customer.addr = addr;
document.customer.tax_number = contact['X-TAX-NUMBER'];
document.customer.id = contact['X-CUSTOMER-NUMBER'];
document.customer.email = contact.EMAIL.val;
}
async function submit(){
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document`;
const resp = await fetch(url,{
method: 'POST',
credentials: 'include',
body: JSON.stringify(document)
});
if (resp.ok){
} else {
error = await resp.text();
}
}
onMount(load);
</script>
<style>
label{display:block}
</style>
<fieldset>
<legend>{t('document.add_new')}</legend>
Company: {company_id}
{#if docType}
<legend>{t('document.add_new',docType)}</legend>
{/if}
{#if error}
<span class="error">{error}</span>
{/if}
{#if company}
Company: {company.name}
<fieldset>
<legend>{t('document.customer')}</legend>
<ContactSelector caption={t('document.select_customer')} onselect={contactSelected} />
<label>
<textarea bind:value={document.customer.addr}></textarea>
{t('document.customer_address')}
</label>
<label>
<input bind:value={document.customer.tax_number} />
{t('document.tax_number')}
</label>
<label>
<input bind:value={document.customer.id} />
{t('document.customer_id')}
</label>
<label>
<input bind:value={document.customer.email} />
{t('document.email')}
</label>
</fieldset>
{/if}
<fieldset>
<legend>{t('document.sender')}</legend>
<label>
<textarea bind:value={document.sender.name}></textarea>
{t('document.sender_name')}
</label>
<label>
<input bind:value={document.sender.tax_id} />
{t('document.sender_tax_id')}
</label>
<label>
<textarea bind:value={document.sender.bank_account}></textarea>
{t('document.sender_bank_account')}
</label>
<label>
<input bind:value={document.sender.court} />
{t('document.sender_local_court')}
</label>
</fieldset>
<button onclick={submit}>{t('document.create_new')}</button>
</fieldset>

View File

@@ -2,18 +2,20 @@
import { useTinyRouter } from 'svelte-tiny-router';
import { onMount } from 'svelte';
import { t } from '../../translations.svelte.js';
import TypeSelector from './TypeSelector.svelte';
let error = null;
let companies = {};
let documents = null;
let selected_company = null;
let router = useTinyRouter();
let docType = 0;
async function loadCompanies(){
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/companies`;
var resp = await fetch(url,{ credentials: 'include'});
if (resp.ok){
companies = await resp.json();
console.log(companies);
} else {
error = await resp.text();
}
@@ -29,18 +31,20 @@
});
if (resp.ok){
documents = await resp.json();
console.log(documents);
} else {
error = await resp.text();
}
}
function createDoc(){
router.navigate(`/document/add?company_id=${selected_company.id}&document_type=${docType}`)
}
onMount(loadCompanies);
</script>
<fieldset>
<legend>{name ? t( 'document.list_of',name) : t('document.list')}</legend>
<legend>{selected_company ? t( 'document.list_of',selected_company.name) : t('document.list')}</legend>
{#if error}
<div class="error">{error}</div>
{/if}
@@ -51,19 +55,31 @@
{/each}
</div>
{#if documents}
<button onclick={() => router.navigate(`/document/add?company=${selected_company.id}`)}>{t('document.create_new')}</button>
<table>
<thead>
<tr>
<th>{t('document.number')}</th>
<th>{t('document.date')}</th>
<th>{t('document.customer')}</th>
<th>{t('document.gross_sum')}</th>
<th>{t('document.type')}</th>
<th>{t('document.state')}</th>
<th>
{t('document.actions')}
{docType}
<TypeSelector caption={t('document.create_new')} bind:value={docType} onchange={createDoc}/>
</th>
</tr>
</thead>
<tbody>
{#each Object.entries(documents) as [id,document]}
{#each Object.entries(documents).reverse() as [id,document]}
<tr>
<td>{id}</td>
<td>{document.number}</td>
<td>{document.date}</td>
<td>{document.customer.name.split('\n')[0]}</td>
<td>{document.sum/100 + document.currency}</td>
<td>{t('document.type_'+document.type)}</td>
<td>{t('document.state_'+document.state.name)}</td>
</tr>
{/each}
</tbody>

View File

@@ -0,0 +1,33 @@
<script>
import {onMount} from 'svelte';
import {t} from '../../translations.svelte.js';
let { caption, value = $bindable(0), onchange = () => console.log('changed')} = $props();
let message = t('document.loading');
let types = $state(null);
async function loadTypes(){
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/document/types`;
var resp = await fetch(url,{ credentials: 'include'});
if (resp.ok){
types = await resp.json();
} else {
message = await resp.text();
}
}
onMount(loadTypes)
</script>
{#if types}
<select bind:value onchange={onchange}>
<option value={0}>{caption}</option>
{#each Object.entries(types) as [id,type]}
<option value={id}>{t('document.type_'+type)}</option>
{/each}
</select>
{:else}
<span>{message}</span>
{/if}

View File

@@ -21,10 +21,8 @@
}
onMount(() => {
console.log(location.search);
let params = new URLSearchParams(location.search);
key = params.get('key');
console.log({param:key});
if (key) doSearch();
});

View File

@@ -25,7 +25,6 @@
async function checkToken(){
const urlParams = new URLSearchParams(window.location.search);
const token = urlParams.get('token');
console.log({token:token,params:urlParams});
if (token) {
const url = `${location.protocol}//${location.host.replace('5173','8080')}/api/user/validate/${token}`;
const resp = await fetch(url,{