Files
teknav-bak/app/teknav-store.js
T
arsam ca05d58b07 Import source: app/teknav-store
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:26:28 +03:30

157 lines
5.4 KiB
JavaScript

// teknav-store.js — Frontend state management via localStorage (ES module)
import { TeknavData } from './teknav-data.js';
export const TeknavStore = (() => {
const DATA_VERSION = '2026-05-02-v1';
const LS = {
get: (k, def) => { try { const v = localStorage.getItem(k); return v ? JSON.parse(v) : def; } catch { return def; } },
set: (k, v) => { try { localStorage.setItem(k, JSON.stringify(v)); } catch {} },
};
// Version check — Clear old 2024 placeholder data
if (localStorage.getItem('teknav_data_version') !== DATA_VERSION) {
localStorage.removeItem('teknav_articles');
localStorage.removeItem('teknav_activity');
localStorage.setItem('teknav_data_version', DATA_VERSION);
}
// Session
const getUser = () => LS.get('teknav_user', null);
const setUser = (user) => LS.set('teknav_user', user);
const logout = () => { localStorage.removeItem('teknav_user'); };
const login = (_email, _password) => {
// localStorage auth removed. All auth goes through /api/auth/login.
return null;
};
// Articles (seed + created)
const getArticles = () => {
const created = LS.get('teknav_articles', []);
return [...TeknavData.articles, ...created];
};
const createArticle = (article) => {
const articles = LS.get('teknav_articles', []);
const newArt = { ...article, id: 'art_' + Date.now(), date: new Date().toLocaleDateString('fa-IR'), views: 0, reactions: 0 };
LS.set('teknav_articles', [newArt, ...articles]);
addActivity('مقاله جدید ایجاد شد', newArt.title, 'draft');
return newArt;
};
const updateArticle = (id, updates) => {
// Update in seed if exists
const seedIdx = TeknavData.articles.findIndex(a => a.id === id);
if (seedIdx !== -1) {
Object.assign(TeknavData.articles[seedIdx], updates);
return;
}
const articles = LS.get('teknav_articles', []);
const idx = articles.findIndex(a => a.id === id);
if (idx !== -1) { articles[idx] = { ...articles[idx], ...updates }; LS.set('teknav_articles', articles); }
addActivity('مقاله ویرایش شد', updates.title || id, 'edit');
};
const deleteArticle = (id) => {
const articles = LS.get('teknav_articles', []);
LS.set('teknav_articles', articles.filter(a => a.id !== id));
addActivity('مقاله حذف شد', id, 'delete');
};
// Saved articles
const getSaved = () => LS.get('teknav_saved', []);
const toggleSaved = (id) => {
const saved = getSaved();
const newSaved = saved.includes(id) ? saved.filter(s => s !== id) : [...saved, id];
LS.set('teknav_saved', newSaved);
return newSaved.includes(id);
};
const isSaved = (id) => getSaved().includes(id);
// Newsletter
const subscribeNewsletter = (email) => {
const subs = LS.get('teknav_newsletter', []);
if (subs.includes(email)) return false;
LS.set('teknav_newsletter', [...subs, email]);
return true;
};
// Reactions
const getReactions = () => LS.get('teknav_reactions', {});
const toggleReaction = (articleId, type) => {
const reactions = getReactions();
const key = `${articleId}_${type}`;
const reacted = reactions[key];
reactions[key] = !reacted;
LS.set('teknav_reactions', reactions);
return !reacted;
};
const hasReacted = (articleId, type) => getReactions()[`${articleId}_${type}`] || false;
// Activity log
const getActivity = () => {
const extra = LS.get('teknav_activity', []);
return [...extra, ...TeknavData.activityLog];
};
const addActivity = (action, target, type) => {
const log = LS.get('teknav_activity', []);
const user = getUser();
log.unshift({ id: Date.now(), user: user?.name || 'سیستم', action, target, time: 'همین الان', type });
LS.set('teknav_activity', log.slice(0, 50));
};
// Users management
const getUsers = () => {
const overrides = LS.get('teknav_users_override', {});
return TeknavData.users.map(u => ({ ...u, ...(overrides[u.id] || {}) }));
};
const updateUser = (id, updates) => {
const overrides = LS.get('teknav_users_override', {});
overrides[id] = { ...(overrides[id] || {}), ...updates };
LS.set('teknav_users_override', overrides);
};
// Categories management
const getCategories = () => {
const extra = LS.get('teknav_categories', []);
return [...TeknavData.categories, ...extra];
};
const addCategory = (cat) => {
const cats = LS.get('teknav_categories', []);
cats.push({ ...cat, id: 'cat_' + Date.now(), articleCount: 0, authorCount: 0, avgReadTime: 0 });
LS.set('teknav_categories', cats);
};
const deleteCategory = (id) => {
const cats = LS.get('teknav_categories', []);
LS.set('teknav_categories', cats.filter(c => c.id !== id));
};
// Tags management
const getTags = () => {
const extra = LS.get('teknav_tags', []);
return [...TeknavData.tags, ...extra];
};
const addTag = (name) => {
const tags = LS.get('teknav_tags', []);
tags.push({ id: Date.now(), name, count: 0 });
LS.set('teknav_tags', tags);
};
const deleteTag = (id) => {
const tags = LS.get('teknav_tags', []);
LS.set('teknav_tags', tags.filter(t => t.id !== id));
};
return {
getUser, setUser, logout, login,
getArticles, createArticle, updateArticle, deleteArticle,
getSaved, toggleSaved, isSaved,
subscribeNewsletter,
getReactions, toggleReaction, hasReacted,
getActivity, addActivity,
getUsers, updateUser,
getCategories, addCategory, deleteCategory,
getTags, addTag, deleteTag,
};
})();