All checks were successful
Build Latest and dev images / build-container (push) Successful in 1m0s
292 lines
8.3 KiB
Svelte
292 lines
8.3 KiB
Svelte
<script>
|
|
import { _ } from "svelte-i18n";
|
|
import { DonationService } from "@odit/lfk-client-js";
|
|
import store from "../../store";
|
|
import DonationsEmptyState from "./DonationsEmptyState.svelte";
|
|
import AddDonationPaymentModal from "./AddDonationPaymentModal.svelte";
|
|
import { onMount } from "svelte";
|
|
import {
|
|
createSvelteTable,
|
|
flexRender,
|
|
getCoreRowModel,
|
|
getFilteredRowModel,
|
|
getPaginationRowModel,
|
|
getSortedRowModel,
|
|
renderComponent,
|
|
} from "@tanstack/svelte-table";
|
|
import { writable } from "svelte/store";
|
|
import TableBottom from "../shared/TableBottom.svelte";
|
|
import InputElement from "../shared/InputElement.svelte";
|
|
import TableHeader from "../shared/TableHeader.svelte";
|
|
import DonationDonor from "./DonationDonor.svelte";
|
|
import DonationRunner from "./DonationRunner.svelte";
|
|
import DonationStatus from "./DonationStatus.svelte";
|
|
import DonationTableAction from "./DonationTableAction.svelte";
|
|
import DeleteDonationModal from "./DeleteDonationModal.svelte";
|
|
import {
|
|
donationDonorFilter,
|
|
donationRunnerFilter,
|
|
} from "../shared/tablefilters";
|
|
import toast from "svelte-french-toast";
|
|
$: searchvalue = "";
|
|
$: active_deletes = [];
|
|
$: active_edits = [];
|
|
$: selected =
|
|
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
|
$: dataLoaded = false;
|
|
|
|
export let current_donations = [];
|
|
export const addDonations = (donations) => {
|
|
current_donations = current_donations.concat(...donations);
|
|
options.update((options) => ({
|
|
...options,
|
|
data: current_donations,
|
|
}));
|
|
};
|
|
|
|
//Section table
|
|
const columns = [
|
|
{
|
|
accessorKey: "id",
|
|
header: () => "id",
|
|
filterFn: `equalsString`,
|
|
},
|
|
{
|
|
accessorKey: "donor",
|
|
header: () => $_("donor"),
|
|
cell: (info) => {
|
|
return renderComponent(DonationDonor, { donor: info.getValue() });
|
|
},
|
|
filterFn: `donor`,
|
|
},
|
|
{
|
|
accessorKey: "runner",
|
|
header: () => $_("runner"),
|
|
cell: (info) => {
|
|
return renderComponent(DonationRunner, { runner: info.getValue() });
|
|
},
|
|
filterFn: `runner`,
|
|
},
|
|
{
|
|
accessorKey: "amountPerDistance",
|
|
header: () => $_("amount-per-kilometer"),
|
|
cell: (info) => {
|
|
if (!info.getValue()) {
|
|
return $_("fixed-donation");
|
|
}
|
|
return `${(info.getValue() / 100)
|
|
.toFixed(2)
|
|
.toLocaleString("de-DE", { valute: "EUR" })} €`;
|
|
},
|
|
enableColumnFilter: false,
|
|
},
|
|
{
|
|
accessorKey: "amount",
|
|
header: () => $_("donation-amount"),
|
|
cell: (info) => {
|
|
return `${(info.getValue() / 100)
|
|
.toFixed(2)
|
|
.toLocaleString("de-DE", { valute: "EUR" })} €`;
|
|
},
|
|
enableColumnFilter: false,
|
|
},
|
|
{
|
|
accessorKey: "paidAmount",
|
|
header: () => $_("total-paid-amount"),
|
|
cell: (info) => {
|
|
return `${(info.getValue() / 100)
|
|
.toFixed(2)
|
|
.toLocaleString("de-DE", { valute: "EUR" })} €`;
|
|
},
|
|
enableColumnFilter: false,
|
|
},
|
|
{
|
|
accessorKey: "status",
|
|
header: () => $_("status"),
|
|
cell: (info) => {
|
|
return renderComponent(DonationStatus, { status: info.getValue() });
|
|
},
|
|
enableColumnFilter: false,
|
|
},
|
|
{
|
|
accessorKey: "actions",
|
|
header: () => $_("action"),
|
|
cell: (info) => {
|
|
return renderComponent(DonationTableAction, {
|
|
detailsLink: `./${info.row.original.id}`,
|
|
deleteAction: () => {
|
|
active_deletes = current_donations.filter(
|
|
(r) => r.id == info.row.original.id
|
|
);
|
|
},
|
|
paymentAction: () => {
|
|
active_edits = current_donations.filter(
|
|
(r) => r.id == info.row.original.id
|
|
);
|
|
},
|
|
deleteEnabled:
|
|
store.state.jwtinfo.userdetails.permissions.includes(
|
|
"DONATION:DELETE"
|
|
),
|
|
});
|
|
},
|
|
enableColumnFilter: false,
|
|
enableSorting: false,
|
|
},
|
|
];
|
|
const options = writable({
|
|
data: [],
|
|
columns: columns,
|
|
initialState: {
|
|
pagination: {
|
|
pageSize: 50,
|
|
},
|
|
},
|
|
filterFns: {
|
|
donor: donationDonorFilter,
|
|
runner: donationRunnerFilter,
|
|
},
|
|
enableRowSelection: true,
|
|
getCoreRowModel: getCoreRowModel(),
|
|
getFilteredRowModel: getFilteredRowModel(),
|
|
getPaginationRowModel: getPaginationRowModel(),
|
|
getSortedRowModel: getSortedRowModel(),
|
|
});
|
|
const table = createSvelteTable(options);
|
|
|
|
async function deleteDonation(delete_donation_id) {
|
|
await DonationService.donationControllerRemove(delete_donation_id, true);
|
|
current_donations = current_donations.filter(
|
|
(r) => r.id !== delete_donation_id
|
|
);
|
|
options.update((options) => ({
|
|
...options,
|
|
data: current_donations,
|
|
}));
|
|
toast.success($_("donation-deleted"));
|
|
}
|
|
|
|
onMount(async () => {
|
|
let page = 0;
|
|
let pagesize = 300;
|
|
while (page >= 0) {
|
|
const donations = await DonationService.donationControllerGetAll(
|
|
page,
|
|
pagesize
|
|
);
|
|
if (donations.length == 0) {
|
|
page = -2;
|
|
}
|
|
|
|
current_donations = current_donations.concat(...donations);
|
|
options.update((options) => ({
|
|
...options,
|
|
data: current_donations,
|
|
}));
|
|
|
|
dataLoaded = true;
|
|
page++;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<AddDonationPaymentModal
|
|
original_data={active_edits[0]}
|
|
payment_modal_open={active_edits.length > 0}
|
|
paid_amount_input={(active_edits[0]?.paidAmount || 0) / 100}
|
|
on:created={(event) => {
|
|
current_donations = current_donations.map((d)=>{
|
|
if(d.id === event.detail.donation.id){
|
|
d.paidAmount = event.detail.donation.paidAmount;
|
|
}
|
|
return d;
|
|
})
|
|
options.update((options) => ({
|
|
...options,
|
|
data: current_donations,
|
|
}));
|
|
}}
|
|
/>
|
|
<DeleteDonationModal
|
|
delete_donation={active_deletes[0]}
|
|
modal_open={active_deletes.length > 0}
|
|
on:delete={(event) => {
|
|
deleteDonation(event.detail.id);
|
|
}}
|
|
/>
|
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")}
|
|
{#if !dataLoaded}
|
|
<div
|
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
|
role="alert"
|
|
>
|
|
<p class="font-bold">{$_("donations-are-being-loaded")}</p>
|
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
|
</div>
|
|
{:else if current_donations.length === 0}
|
|
<DonationsEmptyState />
|
|
{:else}
|
|
<input
|
|
type="search"
|
|
bind:value={searchvalue}
|
|
placeholder={$_("datatable.search")}
|
|
aria-label={$_("datatable.search")}
|
|
class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
|
|
/>
|
|
<div
|
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
|
>
|
|
<table class="w-full">
|
|
<thead class="border-b border-gray-400">
|
|
{#each $table.getHeaderGroups() as headerGroup}
|
|
<tr class="select-none">
|
|
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
|
<InputElement
|
|
type="checkbox"
|
|
checked={$table.getIsAllRowsSelected()}
|
|
indeterminate={$table.getIsSomeRowsSelected()}
|
|
on:change={() => $table.toggleAllRowsSelected()}
|
|
/>
|
|
</th>
|
|
{#each headerGroup.headers as header}
|
|
<TableHeader {header} />
|
|
{/each}
|
|
</tr>
|
|
{/each}
|
|
</thead>
|
|
<tbody>
|
|
{#each $table.getRowModel().rows as row}
|
|
<tr class="odd:bg-white even:bg-gray-100">
|
|
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
|
<InputElement
|
|
type="checkbox"
|
|
checked={row.getIsSelected()}
|
|
on:change={() => row.toggleSelected()}
|
|
/>
|
|
</td>
|
|
{#each row.getVisibleCells() as cell}
|
|
<td>
|
|
<svelte:component
|
|
this={flexRender(
|
|
cell.column.columnDef.cell,
|
|
cell.getContext()
|
|
)}
|
|
/>
|
|
</td>
|
|
{/each}
|
|
</tr>
|
|
{/each}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="h-2" />
|
|
<TableBottom {table} {selected} />
|
|
{/if}
|
|
{/if}
|
|
|
|
<style>
|
|
table tbody tr td:nth-child(2) {
|
|
font-family: monospace;
|
|
}
|
|
</style>
|