First Commit. Duplicate bunext-sqlite preset

This commit is contained in:
2026-10-18 16:47:11 +01:00
commit 81e4a8aecc
718 changed files with 41695 additions and 0 deletions
@@ -0,0 +1,49 @@
import Section from "@moduletrace/twui/layout/Section";
import { makeRowKey } from "@/src/components/general/sortable-line-items-editor";
import { AppContext } from "@/src/pages/__root";
import { useContext } from "react";
import { koboToNairaString } from "@/src/utils/money";
import InvoiceForm from "../../../create/(partials)/invoice-form";
import type {
InvoiceItemFormObject,
QuoteLinkFormObject,
} from "../../../(data)/invoice-form-types";
export default function EditInvoiceFormSection() {
const { pageProps } = useContext(AppContext);
const invoice = pageProps?.invoice;
const invoice_items = pageProps?.invoice_items;
const quote_links = pageProps?.invoice_quote_links;
if (!invoice) return null;
const existing_items: InvoiceItemFormObject[] = (
invoice_items || []
).map((item) => ({
description: item.description,
quantity: String(item.quantity || "1"),
unit_price: koboToNairaString(item.unit_price_kobo),
_key: makeRowKey(),
}));
const first_quote_link = quote_links?.[0];
const existing_quote_link: QuoteLinkFormObject | undefined =
first_quote_link
? {
quote_id: first_quote_link.quote_id || "",
amount: koboToNairaString(first_quote_link.amount_kobo),
}
: undefined;
return (
<Section>
<InvoiceForm
existing_invoice={invoice}
existing_items={existing_items}
existing_quote_link={existing_quote_link}
/>
</Section>
);
}
@@ -0,0 +1,21 @@
import AdminHero from "@/src/components/general/admin-hero";
import Button from "@moduletrace/twui/layout/Button";
export default function Hero() {
return (
<AdminHero
title="Edit Invoice"
buttons={
<>
<Button
title="All Invoices"
href="/admin/invoices"
variant="outlined"
>
All Invoices
</Button>
</>
}
/>
);
}
@@ -0,0 +1,50 @@
import grabInvoice, {
grabInvoiceItems,
grabInvoiceQuoteLinks,
} from "@/src/functions/backend/db/invoices/grab-invoice";
import type { PagePropsType } from "@/src/types";
import isReadOnlyUser from "@/src/utils/rbac/is-read-only-user";
import type { BunextPageServerFn } from "@moduletrace/bunext/types";
export const server: BunextPageServerFn<PagePropsType> = async (params) => {
const invoice_id = params.query?.id;
const user_types = params.props?.user_types;
if (isReadOnlyUser({ user_types })) {
return {
redirect: {
destination: "/admin/invoices",
},
};
}
if (!invoice_id) {
return {
redirect: {
destination: "/admin/invoices",
},
};
}
const invoice_res = await grabInvoice({ id: invoice_id });
if (!invoice_res.singleRes) {
return {
redirect: {
destination: "/admin/invoices",
},
};
}
const items_res = await grabInvoiceItems({ invoice_id });
const quote_links_res = await grabInvoiceQuoteLinks({ invoice_id });
return {
props: {
invoice: invoice_res.singleRes,
invoice_items: items_res.payload || [],
invoice_quote_links: quote_links_res.payload || [],
},
};
};
@@ -0,0 +1,24 @@
import type { PagePropsType } from "@/src/types";
import { SiteData } from "@/src/data/site-data";
import type { BunextPageModuleMetaFn } from "@moduletrace/bunext/types";
import Hero from "./(sections)/hero";
import EditInvoiceFormSection from "./(sections)/edit-invoice-form-section";
export default function EditInvoicePage() {
return (
<>
<Hero />
<EditInvoiceFormSection />
</>
);
}
export const meta: BunextPageModuleMetaFn = async (params) => {
const invoice = (params.serverRes?.props as PagePropsType | undefined)
?.invoice;
return {
title: `Edit Invoice ${invoice?.invoice_number || ""} | ${SiteData["SiteName"]}`,
description: "Invoice generator",
};
};