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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
import { useState } from "react";
import { useMutation, useQuery } from "urql";
import { AddFeedForm, FeedList } from "../components";
import {
GetFeedsDocument,
MarkFeedReadDocument,
MarkFeedUnreadDocument,
UnsubscribeFeedDocument,
} from "../graphql/generated/graphql";
export function Settings() {
const [{ data: feedsData }, refetchFeeds] = useQuery({
query: GetFeedsDocument,
});
const [, markFeedRead] = useMutation(MarkFeedReadDocument);
const [, markFeedUnread] = useMutation(MarkFeedUnreadDocument);
const [, unsubscribeFeed] = useMutation(UnsubscribeFeedDocument);
const [selectedFeeds, setSelectedFeeds] = useState<Set<string>>(new Set());
const handleFeedAdded = () => {
refetchFeeds();
};
const handleFeedUnsubscribed = () => {
refetchFeeds();
setSelectedFeeds(new Set());
};
const handleSelectFeed = (feedId: string, selected: boolean) => {
const newSelection = new Set(selectedFeeds);
if (selected) {
newSelection.add(feedId);
} else {
newSelection.delete(feedId);
}
setSelectedFeeds(newSelection);
};
const handleSelectAll = () => {
if (!feedsData?.feeds) return;
if (selectedFeeds.size === feedsData.feeds.length) {
setSelectedFeeds(new Set());
} else {
setSelectedFeeds(new Set(feedsData.feeds.map((feed) => feed.id)));
}
};
const handleBulkMarkRead = async () => {
const promises = Array.from(selectedFeeds).map((feedId) =>
markFeedRead({ id: feedId }),
);
await Promise.all(promises);
refetchFeeds();
};
const handleBulkMarkUnread = async () => {
const promises = Array.from(selectedFeeds).map((feedId) =>
markFeedUnread({ id: feedId }),
);
await Promise.all(promises);
refetchFeeds();
};
const handleBulkUnsubscribe = async () => {
const confirmed = window.confirm(
`Are you sure you want to unsubscribe from ${selectedFeeds.size} selected feeds?`,
);
if (!confirmed) return;
const promises = Array.from(selectedFeeds).map((feedId) =>
unsubscribeFeed({ id: feedId }),
);
await Promise.all(promises);
handleFeedUnsubscribed();
};
const hasFeeds = feedsData?.feeds && feedsData.feeds.length > 0;
const hasSelectedFeeds = selectedFeeds.size > 0;
return (
<div className="mx-auto max-w-4xl">
<h1 className="mb-6 text-2xl font-bold text-gray-900">Feed Settings</h1>
{/* Subscribe to New Feed Section */}
<div className="mb-8">
<h2 className="mb-4 text-xl font-semibold text-gray-800">
Subscribe to New Feed
</h2>
<AddFeedForm onFeedAdded={handleFeedAdded} />
</div>
{/* Manage Feeds Section */}
<div className="mb-8">
<div className="flex items-center justify-between mb-4">
<h2 className="text-xl font-semibold text-gray-800">Manage Feeds</h2>
{hasFeeds && (
<div className="flex items-center gap-4">
<label className="flex items-center gap-2 text-sm text-gray-600">
<input
type="checkbox"
checked={selectedFeeds.size === feedsData.feeds.length}
onChange={handleSelectAll}
className="rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/>
Select All ({feedsData.feeds.length} feeds)
</label>
</div>
)}
</div>
{/* Bulk Operations */}
{hasSelectedFeeds && (
<div className="mb-4 rounded-lg bg-blue-50 border border-blue-200 p-4">
<div className="flex items-center justify-between">
<span className="text-sm font-medium text-blue-900">
{selectedFeeds.size} feed{selectedFeeds.size > 1 ? "s" : ""}{" "}
selected
</span>
<div className="flex gap-2">
<button
type="button"
onClick={handleBulkMarkRead}
className="rounded px-3 py-1 text-sm font-medium text-blue-700 hover:bg-blue-100"
>
Mark All Read
</button>
<button
type="button"
onClick={handleBulkMarkUnread}
className="rounded px-3 py-1 text-sm font-medium text-blue-700 hover:bg-blue-100"
>
Mark All Unread
</button>
<button
type="button"
onClick={handleBulkUnsubscribe}
className="rounded px-3 py-1 text-sm font-medium text-red-700 hover:bg-red-100"
>
Unsubscribe Selected
</button>
</div>
</div>
</div>
)}
<FeedList
onFeedUnsubscribed={handleFeedUnsubscribed}
selectedFeeds={selectedFeeds}
onSelectFeed={handleSelectFeed}
/>
</div>
</div>
);
}
|