You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
4.6 KiB
TypeScript
168 lines
4.6 KiB
TypeScript
import { createContext } from "solid-js";
|
|
import { createStore as createStore_ } from "solid-js/store";
|
|
import { addressSchema, createAddress } from "./components/Address";
|
|
import { createLocalStore as createLocalStore_ } from "./localStore";
|
|
import { getUnixTime } from "date-fns";
|
|
import z, { Infer } from "myzod";
|
|
|
|
export const POSITION_TYPE_QUANTITY = "QUANTITY";
|
|
export const POSITION_TYPE_AGILE = "AGILE";
|
|
|
|
export const positionSchema = z.object({
|
|
id: z.number(),
|
|
name: z.string(),
|
|
enabled: z.boolean(),
|
|
type: z.literals(POSITION_TYPE_QUANTITY, POSITION_TYPE_AGILE),
|
|
agilePointsMin: z.number().optional(),
|
|
agilePointsMax: z.number().optional(),
|
|
agileRiskFactor: z.number().optional(),
|
|
number: z.string().optional(),
|
|
description: z.string().optional(),
|
|
quantity: z.number(),
|
|
fixedDiscountPrice: z.number().optional(),
|
|
itemPrice: z.number().optional(),
|
|
});
|
|
|
|
export type Position = Infer<typeof positionSchema>;
|
|
|
|
export const PRINT_TYPE_OFFER = "OFFER";
|
|
export const PRINT_TYPE_CONFIRMATION = "CONFIRMATION";
|
|
export const PRINT_TYPE_INVOICE = "INVOICE";
|
|
|
|
export type PrintType =
|
|
| typeof PRINT_TYPE_OFFER
|
|
| typeof PRINT_TYPE_CONFIRMATION
|
|
| typeof PRINT_TYPE_INVOICE;
|
|
|
|
export const printTypeTitles = {
|
|
[PRINT_TYPE_OFFER]: "Offerte",
|
|
[PRINT_TYPE_CONFIRMATION]: "Bestätigung",
|
|
[PRINT_TYPE_INVOICE]: "Rechnung",
|
|
};
|
|
|
|
export const createUiStore = () =>
|
|
createStore_({
|
|
lastSaved: 0,
|
|
printType: PRINT_TYPE_INVOICE as PrintType,
|
|
selectedPosition: undefined as undefined | number,
|
|
});
|
|
export type UiStore = ReturnType<typeof createUiStore>;
|
|
export const UiStoreContext = createContext<UiStore>();
|
|
|
|
export const storeSchema = z.object({
|
|
version: z.number(),
|
|
project: z.object({
|
|
orderNumber: z.string(),
|
|
projectNumber: z.string(),
|
|
deliveryNumber: z.string(),
|
|
deliveryDate: z.number().optional(),
|
|
date: z.number(),
|
|
preface: z.string().optional(),
|
|
conclusion: z.string().optional(),
|
|
}),
|
|
invoice: z.object({
|
|
reference: z.string(),
|
|
message: z.string(),
|
|
}),
|
|
fullWidthInvoice: z.boolean(),
|
|
useCustomerAlternativeAddress: z.boolean(),
|
|
customer: z.object({
|
|
customerNumber: z.string(),
|
|
vatNumber: z.string(),
|
|
alternativeAddress: addressSchema,
|
|
debtorAddress: addressSchema,
|
|
}),
|
|
defaultItemPrice: z.number(),
|
|
agileRiskFactor: z.number(),
|
|
agileHoursPerStoryPoint: z.number(),
|
|
defaultPositionType: z.literals(POSITION_TYPE_QUANTITY, POSITION_TYPE_AGILE),
|
|
positions: z.array(positionSchema),
|
|
});
|
|
export type StoreObject = Infer<typeof storeSchema>;
|
|
|
|
export const createStore = () =>
|
|
createStore_<StoreObject>({
|
|
version: 1,
|
|
project: {
|
|
orderNumber: "",
|
|
projectNumber: "",
|
|
deliveryNumber: "",
|
|
date: getUnixTime(new Date()),
|
|
},
|
|
invoice: {
|
|
reference: "",
|
|
message: "",
|
|
},
|
|
fullWidthInvoice: true,
|
|
useCustomerAlternativeAddress: false,
|
|
customer: {
|
|
customerNumber: "",
|
|
vatNumber: "",
|
|
alternativeAddress: createAddress(),
|
|
debtorAddress: createAddress(),
|
|
},
|
|
defaultPositionType: POSITION_TYPE_QUANTITY,
|
|
defaultItemPrice: 0,
|
|
agileRiskFactor: 0.7,
|
|
agileHoursPerStoryPoint: 4,
|
|
positions: [] as Position[],
|
|
});
|
|
|
|
export type Store = ReturnType<typeof createStore>;
|
|
export const StoreContext = createContext<Store>();
|
|
|
|
export const localStoreSchema = z.object({
|
|
// TODO: Move this to a cookie (advantage: ssr)
|
|
showWelcome: z.boolean(),
|
|
version: z.number(),
|
|
vatNumber: z.string(),
|
|
vatRate: z.number(),
|
|
paymentTerms: z.string().optional(),
|
|
iban: z.string(),
|
|
creditor: addressSchema,
|
|
customAddress: addressSchema,
|
|
contact: z.object({
|
|
name: z.string(),
|
|
phone: z.string(),
|
|
email: z.string(),
|
|
}),
|
|
showLufraiWatermark: z.boolean(),
|
|
// TODO: Signature Image
|
|
logo: z
|
|
.object({
|
|
type: z.string(),
|
|
url: z.string(),
|
|
width: z.number(),
|
|
height: z.number(),
|
|
})
|
|
.optional(),
|
|
useCustomAddress: z.boolean(),
|
|
});
|
|
export type LocalStoreObject = Infer<typeof localStoreSchema>;
|
|
|
|
export const createLocalStore = () =>
|
|
createLocalStore_<LocalStoreObject>(
|
|
{
|
|
version: 1,
|
|
showWelcome: true,
|
|
vatNumber: "",
|
|
vatRate: 0.0,
|
|
paymentTerms: undefined,
|
|
creditor: createAddress(),
|
|
customAddress: createAddress(),
|
|
contact: {
|
|
name: "",
|
|
phone: "",
|
|
email: "",
|
|
},
|
|
logo: undefined,
|
|
showLufraiWatermark: true,
|
|
useCustomAddress: false,
|
|
iban: "",
|
|
},
|
|
{ prefix: "invoice-app" }
|
|
);
|
|
|
|
export type LocalStore = ReturnType<typeof createLocalStore>;
|
|
export const LocalStoreContext = createContext<LocalStore>();
|