SPB Git forge
28commits 1branches 0releases
7.7 MBsize
maindefault branch
10 days agolast push
Python 66.3% TypeScript 22.7% JavaScript 8.6% HTML 1.4% CSS 0.7%
1.8 KB · 45 lines tsx
Raw Blame History
1'use client';2import { Bookmark, BookmarkCheck } from 'lucide-react';3import { useState } from 'react';4import { ownerApi } from '@/lib/client-api';5import { cn } from '@/lib/cn';6import { ensureOwnerToken, readWatched, useWatched, writeWatched } from '@/lib/owner';78/** Watch / unwatch a company (owner token generated on first use). Optimistic; mirrors the slug locally. */9export function WatchButton({ slug, name, className, size = 'md' }: { slug: string; name?: string; className?: string; size?: 'sm' | 'md' }) {10  const watched = useWatched();11  const on = watched.includes(slug);12  const [busy, setBusy] = useState(false);13  const [err, setErr] = useState<string | null>(null);14  const toggle = async () => {15    setBusy(true);16    setErr(null);17    const token = ensureOwnerToken();18    const api = ownerApi(token);19    const cur = readWatched();20    try {21      if (on) {22        writeWatched(cur.filter((s) => s !== slug));23        await api.unwatch(slug);24      } else {25        writeWatched([...cur, slug]);26        await api.watch(slug);27      }28    } catch (e) {29      writeWatched(cur);30      setErr((e as Error).message || 'Could not update watchlist');31    } finally {32      setBusy(false);33    }34  };35  return (36    <span className={cn('inline-flex flex-col items-start', className)}>37      <button type="button" onClick={toggle} disabled={busy} aria-pressed={on} className={cn('btn', size === 'sm' && 'btn-sm', on && 'border-accent bg-accent-soft text-accent')} data-watch={slug} title={on ? `Stop watching ${name ?? slug}` : `Watch ${name ?? slug}`}>38        {on ? <BookmarkCheck className="size-4" aria-hidden /> : <Bookmark className="size-4" aria-hidden />}39        {on ? 'Watching' : 'Watch'}40      </button>41      {err && <span className="mt-1 text-[11px] text-danger">{err}</span>}42    </span>43  );44}45