map / src /savedBookshelf.js
PH70248's picture
Add files using upload-large-folder tool
618aeaa verified
Raw
History Blame Contribute Delete
2.61 kB
export const SAVED_BOOKS_STORAGE_KEY = "world-citybook-saved-books";
export function normalizeSavedBookRecords(value) {
const items = Array.isArray(value) ? value : [];
const records = [];
const byId = new Map();
items.forEach((item) => {
const bookId = typeof item === "string" ? item.trim() : String(item?.bookId || "").trim();
if (!bookId) return;
const savedAt = typeof item === "object" && item?.savedAt ? String(item.savedAt) : "";
if (byId.has(bookId)) {
const existing = byId.get(bookId);
existing.savedAt = latestTimestamp(existing.savedAt, savedAt);
return;
}
const record = { bookId, savedAt };
byId.set(bookId, record);
records.push(record);
});
return records;
}
export function savedBookIds(records) {
return normalizeSavedBookRecords(records).map((record) => record.bookId);
}
export function paginateShelfItems(items, options = {}) {
const source = Array.isArray(items) ? items : [];
const pageSize = Math.max(1, Math.floor(Number(options.pageSize) || 1));
const totalPages = Math.max(1, Math.ceil(source.length / pageSize));
const page = clampInteger(options.page, 0, totalPages - 1);
const start = page * pageSize;
return {
page,
pageSize,
totalPages,
items: source.slice(start, start + pageSize),
};
}
export function buildFixedShelfRows(items, options = {}) {
const source = Array.isArray(items) ? items : [];
const rowSize = Math.max(1, Math.floor(Number(options.rowSize) || 1));
const rowCount = Math.max(1, Math.floor(Number(options.rowCount) || 1));
return Array.from({ length: rowCount }, (_, rowIndex) => {
const start = rowIndex * rowSize;
return source.slice(start, start + rowSize);
});
}
export function upsertSavedBook(records, bookId, savedAt = new Date().toISOString()) {
const normalizedBookId = String(bookId || "").trim();
if (!normalizedBookId) return normalizeSavedBookRecords(records);
const next = normalizeSavedBookRecords(records).filter((record) => record.bookId !== normalizedBookId);
return [{ bookId: normalizedBookId, savedAt }, ...next];
}
export function removeSavedBook(records, bookId) {
const normalizedBookId = String(bookId || "").trim();
return normalizeSavedBookRecords(records).filter((record) => record.bookId !== normalizedBookId);
}
function latestTimestamp(left, right) {
if (!left) return right || "";
if (!right) return left;
return right > left ? right : left;
}
function clampInteger(value, min, max) {
const number = Math.floor(Number(value) || 0);
return Math.min(Math.max(number, min), max);
}