summaryrefslogtreecommitdiff
path: root/apps/web/app/reader/settings/_components/muted-phrases-settings.tsx
blob: b22079175d60de2f64ffb264dbd6cb3c1ec9c1b4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
"use client"

import { useState } from "react"
import { useMutedKeywords } from "@/lib/queries/use-muted-keywords"
import {
  useAddMutedKeyword,
  useDeleteMutedKeyword,
} from "@/lib/queries/use-muted-keyword-mutations"
import { useUserProfile } from "@/lib/queries/use-user-profile"
import { TIER_LIMITS } from "@asa-news/shared"

function MutedPhraseRow({
  phrase,
}: {
  phrase: { identifier: string; keyword: string }
}) {
  const [showUnmuteConfirm, setShowUnmuteConfirm] = useState(false)
  const deletePhrase = useDeleteMutedKeyword()

  return (
    <div className="flex items-center justify-between border-b border-border px-4 py-3 last:border-b-0">
      <span className="text-text-primary">{phrase.keyword}</span>
      {showUnmuteConfirm ? (
        <div className="flex items-center gap-1">
          <span className="text-text-dim">confirm?</span>
          <button
            onClick={() => {
              deletePhrase.mutate({ keywordIdentifier: phrase.identifier })
              setShowUnmuteConfirm(false)
            }}
            className="px-2 py-1 text-status-error transition-colors hover:text-text-primary"
          >
            yes
          </button>
          <button
            onClick={() => setShowUnmuteConfirm(false)}
            className="px-2 py-1 text-text-secondary transition-colors hover:text-text-primary"
          >
            no
          </button>
        </div>
      ) : (
        <button
          onClick={() => setShowUnmuteConfirm(true)}
          className="px-2 py-1 text-text-secondary transition-colors hover:text-status-error disabled:opacity-50"
        >
          unmute
        </button>
      )}
    </div>
  )
}

export function MutedPhrasesSettings() {
  const [newPhrase, setNewPhrase] = useState("")
  const { data: phrases, isLoading } = useMutedKeywords()
  const { data: userProfile } = useUserProfile()
  const addPhrase = useAddMutedKeyword()

  const tier = userProfile?.tier ?? "free"
  const tierLimits = TIER_LIMITS[tier]

  function handleAddPhrase(event: React.FormEvent) {
    event.preventDefault()
    const trimmedPhrase = newPhrase.trim()

    if (!trimmedPhrase) return

    addPhrase.mutate({ keyword: trimmedPhrase })
    setNewPhrase("")
  }

  if (isLoading) {
    return <p className="px-4 py-6 text-text-dim">loading muted phrases ...</p>
  }

  const phraseList = phrases ?? []

  return (
    <div>
      <div className="border-b border-border px-4 py-3">
        <p className="mb-1 text-text-dim">
          {phraseList.length} / {tierLimits.maximumMutedKeywords} phrases used
        </p>
        <p className="mb-2 text-text-dim">
          entries containing muted phrases are hidden from your timeline
        </p>
        <form onSubmit={handleAddPhrase} className="flex gap-2">
          <input
            type="text"
            value={newPhrase}
            onChange={(event) => setNewPhrase(event.target.value)}
            placeholder="phrase to mute"
            className="min-w-0 flex-1 border border-border bg-background-primary px-3 py-2 text-text-primary outline-none placeholder:text-text-dim focus:border-text-dim"
          />
          <button
            type="submit"
            disabled={addPhrase.isPending || !newPhrase.trim()}
            className="border border-border bg-background-tertiary px-4 py-2 text-text-primary transition-colors hover:bg-border disabled:opacity-50"
          >
            mute
          </button>
        </form>
      </div>
      {phraseList.length === 0 ? (
        <p className="px-4 py-6 text-text-dim">no muted phrases</p>
      ) : (
        phraseList.map((phrase) => (
          <MutedPhraseRow key={phrase.identifier} phrase={phrase} />
        ))
      )}
    </div>
  )
}