fileViews.ts2.2 KBView on GitHub
import { Clock, FolderOpen, Trash2, type LucideIcon } from 'lucide-react';

/**
 * The file explorer's VIEWS — the collections you can look at instead of the folder tree.
 *
 * `tree` is not one of them in the data sense; it is the explorer's normal state, and it is
 * in this list because the menu has to offer a way back out of the other two. Everything
 * else maps 1:1 onto a `documents.list({ view })` value.
 *
 * Shared rather than declared next to the menu, because the breadcrumb (FileExplorerTabs)
 * and the menu (CompanyExplorer) live in different components and must agree on both the
 * set and its labels — the crumb says the same word the menu row said.
 *
 * There is no "Shared with me". Nothing in the product shares a document with a PERSON —
 * `user/` is a private drawer and the server will not open another person's row — so the
 * collection could only ever have listed teammates' private files. See `documents.list`.
 */
export const FILE_VIEWS = ['tree', 'recent', 'deleted'] as const;

export type FileView = (typeof FILE_VIEWS)[number];

/**
 * The view the explorer is in when nobody has chosen one.
 *
 * Typed as the literal, not as `FileView`: `fileView !== DEFAULT_FILE_VIEW` is what tells
 * TypeScript the remaining value is a COLLECTION, which is exactly the guarantee
 * `FileViewList` needs from its caller. Widened to `FileView`, that comparison narrows
 * nothing and the call site needs a cast.
 */
export const DEFAULT_FILE_VIEW = 'tree' satisfies FileView;

/**
 * How long a deleted file stays restorable, mirrored from the server's
 * `DELETED_DOCUMENT_RETENTION_DAYS`. Duplicated rather than imported because the number is
 * shown to the reader here and enforced there — the server is the authority, and this is a
 * label. If they ever disagree the UI is the one that is wrong.
 */
export const DELETED_RETENTION_DAYS = 30;

export const FILE_VIEW_LABELS: Record<FileView, string> = {
  tree: 'All files',
  recent: 'Recent',
  deleted: 'Deleted',
};

export const FILE_VIEW_ICONS: Record<FileView, LucideIcon> = {
  tree: FolderOpen,
  recent: Clock,
  deleted: Trash2,
};

export function isFileView(value: string): value is FileView {
  return (FILE_VIEWS as readonly string[]).includes(value);
}