feat: implement reactive stores and store models
parent
a46be3e8dc
commit
69e624b097
@ -0,0 +1,184 @@
|
||||
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 const createUiStore = () =>
|
||||
createStore_({
|
||||
printType: PRINT_TYPE_INVOICE as
|
||||
| typeof PRINT_TYPE_OFFER
|
||||
| typeof PRINT_TYPE_CONFIRMATION
|
||||
| typeof PRINT_TYPE_INVOICE,
|
||||
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: [
|
||||
{
|
||||
id: 0,
|
||||
name: "Entwicklung",
|
||||
enabled: true,
|
||||
quantity: 0,
|
||||
agilePointsMin: 8,
|
||||
agilePointsMax: 13,
|
||||
itemPrice: 80,
|
||||
type: POSITION_TYPE_AGILE,
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: "Kaffee Trinken",
|
||||
enabled: true,
|
||||
quantity: 2,
|
||||
itemPrice: 160,
|
||||
type: POSITION_TYPE_QUANTITY,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Pizza Essen",
|
||||
enabled: true,
|
||||
quantity: 1,
|
||||
itemPrice: 280,
|
||||
type: POSITION_TYPE_QUANTITY,
|
||||
},
|
||||
] as Position[],
|
||||
});
|
||||
|
||||
export type Store = ReturnType<typeof createStore>;
|
||||
export const StoreContext = createContext<Store>();
|
||||
|
||||
export const localStoreSchema = z.object({
|
||||
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: false,
|
||||
useCustomAddress: false,
|
||||
iban: "",
|
||||
},
|
||||
{ prefix: "invoice-app" }
|
||||
);
|
||||
|
||||
export type LocalStore = ReturnType<typeof createLocalStore>;
|
||||
export const LocalStoreContext = createContext<LocalStore>();
|
Loading…
Reference in New Issue