Every column's header is a button that sorts the table by it, and clicking it again sorts the other way. A column starts with the most useful first: titles A to Z, the latest dates and highest values, Yes before No, hidden first, and marks in the menu's order. Statuses sort in the filters' order rather than alphabetically, and titles by their words and numbers, ignoring case and punctuation. Rows with no value in the column (no date, no value, no marks) go last either way, and rows that tie are newest release first. The sort is remembered with the other preferences, and is newest release first until another is chosen, as before. Sorting has moved out of filterOpportunities, which now keeps the order it's given.
29 lines
830 B
TypeScript
29 lines
830 B
TypeScript
// localStorage can throw (privacy modes, storage disabled, quota), so every
|
|
// access is guarded and falls back to "nothing stored".
|
|
|
|
/** The stored value of key, or null if there is none or storage is unavailable. */
|
|
export function readStored(key: string): string | null {
|
|
try {
|
|
return window.localStorage.getItem(key);
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** Stores value under key, if storage is available. */
|
|
export function writeStored(key: string, value: string): void {
|
|
try {
|
|
window.localStorage.setItem(key, value);
|
|
} catch {
|
|
/* preference just won't persist */
|
|
}
|
|
}
|
|
|
|
// index.html reads the theme key too, before the app loads.
|
|
export const STORAGE_KEYS = {
|
|
theme: 'job_search.theme',
|
|
filtersOpen: 'job_search.filtersOpen',
|
|
filters: 'job_search.filters',
|
|
sort: 'job_search.sort',
|
|
} as const;
|