refactor(v4.0.0-alpha): beginning of a new era

This commit is contained in:
Amruth Pillai
2023-11-05 12:31:42 +01:00
parent 0ba6a444e2
commit 22933bd412
505 changed files with 81829 additions and 0 deletions

View File

@ -0,0 +1,21 @@
import { UserDto } from "@reactive-resume/dto";
import { create } from "zustand";
import { persist } from "zustand/middleware";
interface AuthState {
user: UserDto | null;
}
interface AuthActions {
setUser: (user: UserDto | null) => void;
}
export const useAuthStore = create<AuthState & AuthActions>()(
persist(
(set) => ({
user: null,
setUser: (user) => set({ user }),
}),
{ name: "auth" },
),
);

View File

@ -0,0 +1,108 @@
import { ImperativePanelHandle } from "react-resizable-panels";
import { ReactZoomPanPinchRef } from "react-zoom-pan-pinch";
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
type Sheet = {
open: boolean;
setOpen: (open: boolean) => void;
};
type Panel = {
isDragging: boolean;
ref: ImperativePanelHandle | null;
setRef: (ref: ImperativePanelHandle | null) => void;
setDragging: (dragging: boolean) => void;
};
interface BuilderState {
transform: {
ref: Omit<ReactZoomPanPinchRef, "instance"> | null;
setRef: (ref: Omit<ReactZoomPanPinchRef, "instance"> | null) => void;
};
sheet: {
left: Sheet;
right: Sheet;
};
panel: {
left: Panel;
right: Panel;
};
}
interface BuilderActions {
toggle: (side: "left" | "right") => void;
}
export const useBuilderStore = create<BuilderState & BuilderActions>()(
immer((set) => ({
transform: {
ref: null,
setRef: (ref) => {
set((state) => {
state.transform.ref = ref;
});
},
},
sheet: {
left: {
open: false,
setOpen: (open) => {
set((state) => {
state.sheet.left.open = open;
});
},
},
right: {
open: false,
setOpen: (open) => {
set((state) => {
state.sheet.right.open = open;
});
},
},
},
panel: {
left: {
ref: null,
isDragging: false,
setRef: (ref) => {
set((state) => {
state.panel.left.ref = ref;
});
},
setDragging: (dragging) => {
set((state) => {
state.panel.left.isDragging = dragging;
});
},
},
right: {
ref: null,
isDragging: false,
setRef: (ref) => {
set((state) => {
state.panel.right.ref = ref;
});
},
setDragging: (dragging) => {
set((state) => {
state.panel.right.isDragging = dragging;
});
},
},
},
toggle: (side) => {
set((state) => {
const panelRef = state.panel[side].ref;
if (panelRef) {
const collapsed = panelRef.getCollapsed();
collapsed ? panelRef.expand() : panelRef.collapse();
} else {
state.sheet[side].open = !state.sheet[side].open;
}
});
},
})),
);

View File

@ -0,0 +1,46 @@
import { SectionKey } from "@reactive-resume/schema";
import { create } from "zustand";
export type DialogName = "resume" | "import" | "two-factor" | SectionKey;
export type DialogMode = "create" | "update" | "duplicate" | "delete";
export type DialogPayload<T = unknown> = {
id: DialogName;
item?: T;
};
type Dialog<T = unknown> = {
name: DialogName;
mode: DialogMode;
payload?: DialogPayload<T>;
};
interface DialogState {
dialog: Dialog | null;
}
interface DialogActions {
setDialog: <T>(dialog: Dialog<T> | null) => void;
}
export const useDialogStore = create<DialogState & DialogActions>()((set) => ({
dialog: null,
setDialog: (dialog) => set({ dialog }),
}));
export const useDialog = <T = unknown>(name: DialogName) => {
const dialog = useDialogStore((state) => {
if (name.startsWith("custom.")) name = "custom";
return state.dialog?.name === name ? state.dialog : null;
});
return {
isOpen: !!dialog,
mode: dialog?.mode,
payload: dialog?.payload as DialogPayload<T>,
open: (mode: DialogMode, payload?: DialogPayload<T>) =>
useDialogStore.setState({ dialog: { name, mode, payload } }),
close: () => useDialogStore.setState({ dialog: null }),
};
};

View File

@ -0,0 +1,17 @@
import { create } from "zustand";
import { persist } from "zustand/middleware";
interface OpenAIStore {
apiKey: string | null;
setApiKey: (apiKey: string | null) => void;
}
export const useOpenAiStore = create<OpenAIStore>()(
persist(
(set) => ({
apiKey: null,
setApiKey: (apiKey) => set({ apiKey }),
}),
{ name: "openai" },
),
);

View File

@ -0,0 +1,79 @@
import { createId } from "@paralleldrive/cuid2";
import { ResumeDto } from "@reactive-resume/dto";
import { CustomSection, defaultSection, SectionKey } from "@reactive-resume/schema";
import { removeItemInLayout } from "@reactive-resume/utils";
import _set from "lodash.set";
import { temporal, TemporalState } from "zundo";
import { create } from "zustand";
import { devtools } from "zustand/middleware";
import { immer } from "zustand/middleware/immer";
import { useStoreWithEqualityFn } from "zustand/traditional";
import { debouncedUpdateResume } from "../services/resume";
type ResumeStore = {
resume: ResumeDto;
// Actions
setValue: (path: string, value: unknown) => void;
// Custom Section Actions
addSection: () => void;
removeSection: (sectionId: SectionKey) => void;
};
export const useResumeStore = create<ResumeStore>()(
temporal(
immer((set) => ({
resume: {} as ResumeDto,
setValue: (path, value) => {
set((state) => {
if (path === "visibility") {
state.resume.visibility = value as "public" | "private";
} else {
state.resume.data = _set(state.resume.data, path, value);
}
debouncedUpdateResume(JSON.parse(JSON.stringify(state.resume)));
});
},
addSection: () => {
const section: CustomSection = {
...defaultSection,
id: createId(),
name: "Custom Section",
items: [],
};
set((state) => {
state.resume.data.metadata.layout[0][0].push(`custom.${section.id}`);
state.resume.data = _set(state.resume.data, `sections.custom.${section.id}`, section);
debouncedUpdateResume(JSON.parse(JSON.stringify(state.resume)));
});
},
removeSection: (sectionId: SectionKey) => {
if (sectionId.startsWith("custom.")) {
const id = sectionId.split("custom.")[1];
set((state) => {
removeItemInLayout(sectionId, state.resume.data.metadata.layout);
delete state.resume.data.sections.custom[id];
debouncedUpdateResume(JSON.parse(JSON.stringify(state.resume)));
});
}
},
})),
{
limit: 100,
wrapTemporal: (fn) => devtools(fn),
partialize: ({ resume }) => ({ resume }),
},
),
);
export const useTemporalResumeStore = <T>(
selector: (state: TemporalState<Pick<ResumeStore, "resume">>) => T,
equality?: (a: T, b: T) => boolean,
) => useStoreWithEqualityFn(useResumeStore.temporal, selector, equality);