# TODO ## Styling Redesign (matching design images) - [x] Redesign shared nav bar (purple gradient top, flat, POSTERG / RÉPERTOIRE / À PROPOS) - [x] Redesign shared search bar (full-width, icon, bottom border only, white bg) - [x] Rewrite `common.css` (nav + search bar components) - [x] Rewrite `main.css` (home page — white bg, media card grid, label below) - [x] Rewrite `search.css` (répertoire index — 4-col ANNÉES/CATÉGORIES/ÉTUDIANTES/MOTS-CLÉS) - [x] Rewrite `tfe.css` (TFE page — 2-col, large author/title left, media right) - [x] Add `apropos.css` (À Propos — 2-col, large monospace text) - [x] Rewrite `admin.css` (dark bg, purple gradient nav, bottom-border-only form inputs) - [x] Update `templates/nav.php` (new shared nav partial) - [x] Update `templates/search-bar.php` (new shared search bar partial) - [x] Rewrite `public/index.php` (home page with new layout) - [x] Rewrite `public/search.php` (répertoire index view + search results view) - [x] Rewrite `public/tfe.php` (individual TFE page) - [x] Create `public/apropos.php` (À Propos page) - [x] Rewrite `templates/admin/head.php` (admin nav) - [x] Rewrite `templates/admin/footer.php` (clean close) - [x] Rewrite `public/admin/add.php` (form with row layout) - [x] Rewrite `public/admin/index.php` (dark table) - [x] Rewrite `public/admin/edit.php` (form with row layout) - [x] Rewrite `public/admin/login.php` (centered dark login box) - [x] Rewrite `public/admin/thanks.php` (dark info cards) - [x] Rewrite `public/admin/import.php` (clean dark form) ## Justfile / Ops - [x] Simplify `serve` and `deploy` to one recipe each - [x] Remove sysadmin recipes (server-logs, server-status, deploy-nginx, deploy-admin-tools) - [x] Extract server scripts to `scripts/` (deploy-server.sh, manage-admin-users.sh) - [x] Guard `deploy-db` against overwriting existing remote database - [x] Update README.md and docs/SERVER_SETUP.md to reflect current structure --- ## NEW FEATURES ### 1 — License page (public) Create a public-facing `/licence.php` page, styled consistently with `apropos.php`. - [ ] **`public/licence.php`** — new public page; fetches content from `pages` table (slug `'licenses'`); renders with `nl2br` / Markdown; uses `apropos.css` layout or a new `licence.css` if divergent styling needed - [ ] **`templates/nav.php`** — add "Licence" link between "Répertoire" and "À Propos" (or after "À Propos"); apply `site-nav__link--active` when `$currentNav === 'licence'` - [ ] The `pages` table already has an `INSERT OR IGNORE` seed for slug `'licenses'` in `storage/schema.sql` — no schema change needed here; verify the row exists in the live DB and add a migration if not --- ### 2 — Admin: WYSIWYG/Markdown editors for static pages Allow admins to edit the content of the "À propos" and "Licence" pages from the admin panel, stored in the existing `pages` table. #### 2a — `src/Database.php` - [ ] `getPage(string $slug): array|null` — `SELECT * FROM pages WHERE slug = ?` - [ ] `savePage(string $slug, string $content): void` — `UPDATE pages SET content = ?, updated_at = CURRENT_TIMESTAMP WHERE slug = ?`; throw if slug not found #### 2b — Admin pages editor UI - [ ] **`public/admin/pages.php`** — list all editable pages (fetch all from `pages` table); links to edit each one; reuse `.admin-table` styles - [ ] **`public/admin/pages-edit.php`** — edit form for a single page (slug passed via GET `?slug=`); loads page content; renders a **EasyMDE** (or SimpleMDE) Markdown WYSIWYG editor via CDN; POST action → `actions/page.php` - Include EasyMDE from CDN: `https://cdn.jsdelivr.net/npm/easymde/dist/easymde.min.js` + matching CSS - Textarea `name="content"` pre-filled with `$page['content']`; hidden input `name="slug"` with the page slug - CSRF token as hidden input #### 2c — `public/admin/actions/page.php` - [ ] Auth guard + CSRF check - [ ] Validate `slug` ∈ `['about', 'licenses', 'charte', 'contact']` - [ ] Validate `content` length ≤ 65 535 chars (TEXT column limit) - [ ] Call `$db->savePage($slug, $content)` - [ ] Set `$_SESSION['success']`; redirect to `../pages.php` #### 2d — Public pages render Markdown - [ ] **`public/apropos.php`** — replace hardcoded HTML body text with content from `$db->getPage('about')`; render Markdown via a PHP parser (use **Parsedown** via Composer, or a ~150-line zero-dependency inline parser if Composer is not available in this project — check `composer.json`) - [ ] **`public/licence.php`** — same: render `$db->getPage('licenses')` as Markdown - [ ] Choose Markdown renderer: check if Composer is available; if not, bundle `vendor/Parsedown.php` as a single-file include (MIT licensed, copy-paste friendly) #### 2e — Nav links in admin - [ ] **`templates/admin/head.php`** — add "Pages statiques" nav item linking to `/admin/pages.php`; apply active class when on `pages.php` or `pages-edit.php` --- ### 3 — License field on TFE forms Add a "Licence" dropdown to the Add and Edit TFE forms. The `license_types` table already exists in the schema with an `id`, `name`, `description` structure but has no seed data yet. #### 3a — Schema / DB - [ ] **`storage/schema.sql`** — add seed `INSERT OR IGNORE` for common Creative Commons licences into `license_types`: `CC BY 4.0`, `CC BY-SA 4.0`, `CC BY-ND 4.0`, `CC BY-NC 4.0`, `CC BY-NC-SA 4.0`, `CC BY-NC-ND 4.0`, `Tous droits réservés`, `Domaine public` - [ ] **`storage/migrations/003_seed_license_types.sql`** — same inserts wrapped in `INSERT OR IGNORE` so they're safe to run on an existing DB; also contains no structural changes (no ALTER TABLE needed — `theses.license_id` FK already exists in the schema) - [ ] Verify live DB has `license_types` table; if missing (older DB without that table), add `CREATE TABLE IF NOT EXISTS` to the migration #### 3b — `src/Database.php` - [ ] `getLicenseTypes(): array` — `SELECT * FROM license_types ORDER BY name` - [ ] `getAllLicenseTypes(): array` — alias for form-loading consistency #### 3c — Add form (`public/admin/add.php`) - [ ] Load `$licenseTypes = $db->getAllLicenseTypes()` alongside existing reference data - [ ] Add "Licence" `` row; pre-select current `$thesis['license_id']` (note: view exposes `license_type` as the name string; need to separately query `theses.license_id` for the raw FK value, or add it to the view — see 3f) - [ ] In the POST handler: `UPDATE theses SET … license_id = ? …` with the submitted value #### 3f — View update - [ ] **`storage/schema.sql`** — update `v_theses_full` view to also `SELECT t.license_id` (the raw FK) alongside the existing `lt.name as license_type`; required so the edit form can pre-select the correct `