# Andishkade Foolad — Admin Panel

A standalone Node/Express + SQLite admin panel for managing articles published on the Andishkade Foolad site.

## Features

- Login (single admin, bcrypt-hashed password, JWT session)
- CRUD for articles with all fields used on the site:
  title, category, type, author / role / initial, publish date (Jalali string),
  pages, price, isFree, summary, body, cover image, tags, featured flag
- Cover image upload (multer, stored on disk under `uploads/`)
- Public read API (`GET /api/articles`) that the main React site can consume

## Stack

- Node 20+
- Express 4
- `better-sqlite3` (single-file `data.db`)
- `multer` for uploads
- `bcryptjs` + `jsonwebtoken` for auth
- Vanilla JS admin UI (no build step)

---

## First-time setup

```bash
cd panel
npm install
cp .env.example .env       # then edit .env, especially JWT_SECRET and ADMIN_PASSWORD
npm run seed               # creates the admin user from .env
npm start
```

Then open <http://localhost:3001>.

Login with the `ADMIN_USERNAME` / `ADMIN_PASSWORD` values from `.env`.

## API

All write endpoints require `Authorization: Bearer <token>`. The token is returned by `POST /api/auth/login`.

| Method | Path                  | Auth | Purpose                           |
|--------|-----------------------|------|-----------------------------------|
| POST   | `/api/auth/login`     | —    | `{username, password}` → `{token, user}` |
| GET    | `/api/auth/me`        | yes  | current user info                 |
| GET    | `/api/articles`       | —    | list articles (newest first)      |
| GET    | `/api/articles/:id`   | —    | single article                    |
| POST   | `/api/articles`       | yes  | create article                    |
| PUT    | `/api/articles/:id`   | yes  | update article                    |
| DELETE | `/api/articles/:id`   | yes  | delete article                    |
| POST   | `/api/uploads`        | yes  | multipart `file` → `{url}`        |
| GET    | `/api/health`         | —    | `{ok: true}`                      |

### Article shape

```jsonc
{
  "id": "abc123…",
  "title": "…",
  "category": "بازار جهانی",
  "type": "special",
  "author": "دکتر علی محمدی",
  "authorRole": "مدیر ارشد پژوهش",
  "authorInitial": "م",
  "publishDate": "بهمن ۱۴۰۳",
  "pages": 84,
  "price": 850000,
  "isFree": false,
  "summary": "…",
  "body": "متن کامل …",
  "coverImage": "/uploads/abc.jpg",
  "tags": ["تجارت جهانی", "صادرات"],
  "featured": true,
  "createdAt": "2026-05-26T13:20:00.000Z",
  "updatedAt": "2026-05-26T13:20:00.000Z"
}
```

This shape is intentionally compatible with the `Report` type in [`../src/data/reports.ts`](../src/data/reports.ts), so the main site can swap the hardcoded array for `fetch('/api/articles')` without touching its UI components.

## Wiring the main site to the panel

In the main Vite app, replace the hardcoded import:

```ts
// src/lib/articles.ts
const API = import.meta.env.VITE_PANEL_API || 'http://localhost:3001';

export async function fetchReports() {
  const res = await fetch(`${API}/api/articles`);
  return res.json();
}
```

Then in the consuming components (e.g. `LatestNewsBentoSection.tsx`), call `fetchReports()` inside a `useEffect` / React Query hook instead of the static `reports` array.

Set `VITE_PANEL_API` in the main app's `.env` to the panel's public URL when deploying.

## Deployment notes

- The panel listens on `PORT` (default 3001). It serves the admin UI at `/` and exposes `/api/*`.
- Persist the `data.db` file and the `uploads/` folder — these are your content. Both are gitignored.
- For HF Spaces, the panel is **not** the same image as the main site; deploy it as a separate Space (Docker SDK) or on a small VPS.
- Always change `JWT_SECRET` and `ADMIN_PASSWORD` in production.

## Reset admin password

```bash
sqlite3 data.db "DELETE FROM users WHERE username='admin';"
# edit .env with the new password, then:
npm run seed
```
