SPB Git forge

spb/job-ka

Public
229commits 1branches 0releases
38.1 MBsize
maindefault branch
45 min agolast push
HTML 82.1% Python 14.6% TypeScript 1.9% CSS 1% JavaScript 0.5%
3.7 KB · 100 lines tsx
Raw Blame History
1/**2 * =============================================================================3 * Job·Ka — Groupe KA4 * Auteur  : Simon-Pierre Boucher5 * Contact : contact@spboucher.ai6 * Fichier : frontend/src/pages/Favoris.tsx7 * Rôle    : Mes favoris ♥ « Mon univers Ka » — offres mises en favoris,8 *           lues au hub Groupe KA (magasin central, aucun stockage local).9 *           Rangées éditoriales alignées sur la liste d'offres (job-row).10 * Créé    : 2026-08-23   Modifié : 2026-08-2511 * =============================================================================12 */13import { Link } from "react-router-dom";14import { FavItem, goLogin, useFav } from "../favorites";1516/** /emploi/<uid> local si l'url du favori pointe vers job-ka.com. */17function localPath(f: FavItem): string | null {18  if (!f.url) return `/emploi/${encodeURIComponent(f.item_id)}`;19  try {20    const u = new URL(f.url);21    if (u.hostname.endsWith("job-ka.com")) return u.pathname + u.search;22  } catch { /* url invalide : lien externe ignoré */ }23  return null;24}2526function FavCard({ f }: { f: FavItem }) {27  const { toggle } = useFav();28  const path = localPath(f);29  const inner = (30    <>31      <div className="jr-main">32        <h3 className="jr-title">{f.title}</h3>33        {f.subtitle && <p className="jr-org"><span className="employer">{f.subtitle}</span></p>}34      </div>35      <div className="jr-side">36        {f.price_label37          ? <span className="jr-salary">{f.price_label}</span>38          : <span className="jr-nosalary">Salaire non affiché</span>}39      </div>40      <button41        type="button"42        className="fav-btn on"43        aria-label="Retirer de mes favoris (Mon univers Ka)"44        title="Retirer de mes favoris (Mon univers Ka)"45        onClick={(e) => { e.preventDefault(); e.stopPropagation(); toggle(f); }}46      >47        <svg viewBox="0 0 24 24" aria-hidden="true">48          <path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z" />49        </svg>50      </button>51    </>52  );53  return path54    ? <Link to={path} className="job-row">{inner}</Link>55    : <a href={f.url} className="job-row" target="_blank" rel="noopener noreferrer">{inner}</a>;56}5758export default function FavorisPage() {59  const { ready, connected, items } = useFav();6061  return (62    <main className="container">63      <h1>Mes favoris</h1>64      <p className="muted">65        Vos offres d'emploi mises en favoris ♥ — synchronisées avec votre66        compte <b>Mon univers Ka</b> sur toutes les plateformes du Groupe KA.67      </p>68      {!ready && <div className="empty">Chargement…</div>}69      {ready && !connected && (70        <div className="empty">71          <p>Connectez-vous avec votre KA ID pour retrouver vos favoris.</p>72          <button type="button" className="btn" onClick={goLogin}>73            Se connecter avec KA ID74          </button>75        </div>76      )}77      {ready && connected && items.length === 0 && (78        <div className="empty">79          <p>Aucun favori pour l'instant — touchez le cœur ♥ sur une offre80          pour la retrouver ici.</p>81          <Link className="btn" to="/">Parcourir les offres</Link>82        </div>83      )}84      {ready && connected && items.length > 0 && (85        <div className="job-list">86          {items.map((f) => <FavCard key={f.item_id} f={f} />)}87        </div>88      )}89      {ready && connected && (90        <p className="muted" style={{ marginTop: 24 }}>91          Tous vos favoris Groupe KA (logements, propriétés, produits…) :{" "}92          <a href="https://www.groupe-ka.com/compte" target="_blank" rel="noopener noreferrer">93            Mon univers Ka ↗94          </a>95        </p>96      )}97    </main>98  );99}100