Submatter/apps/web/lib/stores/sidebar-store.ts
varutasu fcd6a59a2c
Some checks failed
CI / Lint, type-check, test (push) Failing after 4m25s
Deploy homelab (CT 116) / Deploy to CT 116 (push) Successful in 14m28s
Implement chat sidebar with Favorites/Channels/DMs sections, search/filter, and expansion state
2026-11-02 22:28:55 +00:00

97 lines
No EOL
2.8 KiB
TypeScript

import { create } from "zustand";
type ExpandedNodeMap = Record<string, boolean>;
export type SidebarItem = {
id: string;
label: string;
type: "post" | "draft" | "channel" | "dm";
preview?: string;
count?: number;
selected?: boolean;
};
type SidebarState = {
favorites: SidebarItem[];
channels: SidebarItem[];
dms: SidebarItem[];
expandedSections: Record<string, boolean>;
isCollapsed: boolean;
expandedNodes: ExpandedNodeMap;
toggleSection: (section: "favorites" | "channels" | "dms") => void;
setExpandedSection: (section: "favorites" | "channels" | "dms", expanded: boolean) => void;
getExpandedSection: (section: "favorites" | "channels" | "dms") => boolean;
toggleCollapse: () => void;
isSidebarNodeExpanded: (nodeId: string) => boolean;
toggleNode: (nodeId: string) => void;
setNodeExpanded: (nodeId: string, expanded: boolean) => void;
toggle: () => void;
};
export const useSidebarStore = create<SidebarState>((set, get) => ({
favorites: [
{ id: "fav-1", label: "All Posts", type: "post", count: 5 },
{ id: "fav-2", label: "Drafts", type: "draft", count: 3 },
],
channels: [
{ id: "chan-1", label: "Model Provider Registry", type: "channel", count: 10 },
{ id: "chan-2", label: "Task Tracker", type: "channel", count: 8 },
],
dms: [
{ id: "dm-1", label: "Alice", type: "dm", preview: "Hi there!" },
{ id: "dm-2", label: "Bob & Carol", type: "dm", preview: "Planning next sprint" },
],
expandedSections: {
favorites: true,
channels: true,
dms: true,
},
isCollapsed: false,
expandedNodes: {},
toggleSection: (section: "favorites" | "channels" | "dms") =>
set((state) => ({
expandedSections: {
...state.expandedSections,
[section]: !state.expandedSections[section],
},
})),
setExpandedSection: (section: "favorites" | "channels" | "dms", expanded: boolean) =>
set((state) => ({
expandedSections: {
...state.expandedSections,
[section]: expanded,
},
})),
getExpandedSection: (section: "favorites" | "channels" | "dms") => {
const state = get();
return state.expandedSections[section];
},
toggleCollapse: () => set((state) => ({ isCollapsed: !state.isCollapsed })),
isSidebarNodeExpanded: (nodeId: string) => {
const state = get();
return state.expandedNodes[nodeId] ?? false;
},
toggleNode: (nodeId: string) =>
set((state) => ({
expandedNodes: {
...state.expandedNodes,
[nodeId]: !state.expandedNodes[nodeId],
},
})),
setNodeExpanded: (nodeId: string, expanded: boolean) =>
set((state) => ({
expandedNodes: {
...state.expandedNodes,
[nodeId]: expanded,
},
})),
toggle: () => set((state) => ({ isCollapsed: !state.isCollapsed })),
}));