Files
teknav-bak/app/docs/superpowers/plans/2026-05-02-phase11-track1.md
T
arsam e9cd12dda6 Import remaining project documentation and reference notes
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:33:04 +03:30

6.3 KiB
Raw Blame History

Phase 11 Track 1 Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Close 5 functional gaps in the Teknav Admin Panel where backend support is already present but UI wiring is missing.

Architecture: Modify existing React components in teknav-admin.jsx to add form fields, filters, dedicated tabs, and bulk operation controls.

Tech Stack: React 18, Fastify (Backend), Prisma, custom CSS-in-JS (via teknav-ui.jsx).


Task 1: Article Editor Flags Toggles

Files:

  • Modify: teknav-admin.jsx

  • Step 1: Locate flags group in ArticleEditor Find the "نشانه‌گذاری" group in the ArticleEditor component (approx line 1500-1600).

  • Step 2: Add toggles for premiumOnly, sponsored, and featured Update the array of flags to include all three fields. Ensure premiumOnly uses a lock icon, sponsored uses a star/badge, and featured uses a star.

// Inside ArticleEditor flags group
{[
  { key: 'premiumOnly', label: 'فقط اعضای ویژه', icon: '🔒' },
  { key: 'sponsored', label: 'محتوای حمایت‌شده', icon: '⭐' },
  { key: 'featured', label: 'مقاله ویژه', icon: '★' },
].map(({ key, label, icon }) => (
  <div key={key} style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 12 }}>
    <label style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: '#263238', cursor: 'pointer' }}>
      <span style={{ fontSize: 14 }}>{icon}</span>
      <span>{label}</span>
    </label>
    <button
      type="button"
      onClick={() => set(key, !form[key])}
      style={{
        width: 44, height: 24, borderRadius: 12, border: 'none', cursor: 'pointer',
        background: form[key] ? BRAND.primary : '#D0CCC5',
        position: 'relative', transition: 'background 0.2s', flexShrink: 0,
      }}
    >
      <span style={{
        position: 'absolute', top: 3, width: 18, height: 18, borderRadius: '50%', background: '#fff',
        transition: 'inset-inline-start 0.2s',
        insetInlineStart: form[key] ? 23 : 3,
      }} />
    </button>
  </div>
))}
  • Step 3: Verify form state update Ensure handleSave correctly includes these new boolean fields in the data object sent to adminApi.createArticle or adminApi.updateArticle.

  • Step 4: Manual verification Open a "Published" article in the editor, toggle "Premium Only", save, and verify it persists (check local browser network tab).


Task 2: Content Freshness Filter

Files:

  • Modify: teknav-admin.jsx

  • Step 1: Locate filter bar in ArticlesManagement Find the ArticlesManagement component and its filter inputs (approx line 300-400).

  • Step 2: Add freshness filter dropdown Add a new <select> for freshnessFilter with options: همه | به‌روز | نیاز به بازنگری | قدیمی.

<select value={freshnessFilter} onChange={e => setFreshnessFilter(e.target.value)} style={{ ...inputStyle, maxWidth: 180 }} dir="rtl">
  <option value="">همه تازگی‌ها</option>
  <option value="up_to_date">به‌روز</option>
  <option value="needs_update">نیاز به بازنگری</option>
  <option value="outdated">قدیمی</option>
</select>
  • Step 3: Update filtering logic Ensure filtered useMemo includes the freshness filter logic:
if (freshnessFilter) list = list.filter(a => a.contentFreshnessStatus === freshnessFilter);
  • Step 4: Manual verification Change the dropdown value and ensure the table updates to show only articles with the matching status.

Task 3: Dedicated SEO Audit Tab

Files:

  • Modify: teknav-admin.jsx

  • Step 1: Register new tab in SIDEBAR_ITEMS Add { id: 'seo-audit', label: 'ممیزی SEO', icon: '◈' } to the admin role in SIDEBAR_ITEMS.

  • Step 2: Update AdminPanel to handle 'seo-audit' tab In the main AdminPanel render loop, add a case for activeTab === 'seo-audit'.

  • Step 3: Move SeoAuditPanel rendering Ensure SeoAuditPanel is rendered as the primary component for the new tab.

  • Step 4: Manual verification Click the "SEO Audit" item in the sidebar and verify it renders the full audit table.


Task 4: Engagement Analytics Enhancements

Files:

  • Modify: teknav-admin.jsx

  • Step 1: Expand EngagementAnalyticsPanel Enhance the existing EngagementAnalyticsPanel to show more detail.

  • Step 2: Add 7-day event count chart Re-use WeeklyChart or the area-SVG pattern to visualize engagement.weeklyData.

  • Step 3: Add Top 5 articles table Render engagement.topArticles in a simple list or table.

  • Step 4: Manual verification Open Analytics -> Engagement tab and verify charts and tables populate with real data.


Task 5: Bulk Comment Moderation UI

Files:

  • Modify: teknav-admin.jsx

  • Step 1: Add selection state to CommentsModeration Ensure selected Set state is active (it seems partially present in the current code section).

  • Step 2: Add floating action bar Render the bulk action bar at the bottom of the screen when selected.size > 0.

{selected.size > 0 && (
  <div style={{ position: 'fixed', bottom: 24, left: '50%', transform: 'translateX(-50%)', background: BRAND.ink, color: '#fff', borderRadius: 14, padding: '12px 20px', display: 'flex', alignItems: 'center', gap: 12, zIndex: 600 }}>
    <span style={{ fontWeight: 700 }}>{selected.size.toLocaleString('fa-IR')} مورد انتخاب شده</span>
    <button onClick={() => bulkAction('delete')} style={bulkBtnStyle}>حذف</button>
    <button onClick={() => bulkAction('approve')} style={bulkBtnStyle}>تأیید</button>
    <button onClick={() => setSelected(new Set())}>لغو</button>
  </div>
)}
  • Step 3: Wire bulkAction to API Call adminApi.bulkModerateComments(ids, action) and refresh the list.

  • Step 4: Manual verification Check 2-3 comments, click "Approve", and verify they are processed and the selection is cleared.