@@ -71,42 +71,59 @@ export default function Grants({
72 const [activeTags, setTags] = useState([]);
72 const [activeTags, setTags] = useState([]);
73 const [activeTypes, setTypes] = useState(types);
73 const [activeTypes, setTypes] = useState(types);
74+ const [includeOpen, setIncludeOpen] = useState(true);
74 const [includeCompleted, setIncludeCompleted] = useState(false);
75 const [includeCompleted, setIncludeCompleted] = useState(false);
76+ const [includeInProgress, setIncludeInProgress] = useState(false);
75 const [tab, setTab] = useState(0);
77 const [tab, setTab] = useState(0);
76 const post = {
78 const post = {
77 title: "Grants",
79 title: "Grants",
78 description: "Contribute to the Urbit project while earning address space.",
80 description: "Contribute to the Urbit project while earning address space.",
81− const postsByCompletion = posts.filter((post) => {
83+ const annotatedPosts = posts.map((post) => {
82− return includeCompleted
84+ if (post.extra.completed) {
83− ? true
85+ return { ...post, status: "completed" };
84− : !post.extra.completed && post.extra.assignee === "";
86+ } else if (post.extra.assignee && post.extra.assignee.length > 0) {
87+ return { ...post, status: "wip" };
89+ return { ...post, status: "open" };
93+ const byStatus = (post) => {
95+ (includeOpen ? post.status === "open" : false) ||
96+ (includeCompleted ? post.status === "completed" : false) ||
97+ (includeInProgress ? post.status === "wip" : false)
101+ const postsByStatus = annotatedPosts.filter(byStatus);
87− const filteredPosts = postsByCompletion.filter((post) => {
103+ const filteredPosts = annotatedPosts.filter((post) => {
88 // Posts are returned if they match both the selected category and selected tags, or if the user has no category filters set.
104 // Posts are returned if they match both the selected category and selected tags, or if the user has no category filters set.
89 const hasCategory = post.taxonomies.grant_category.some((category) =>
105 const hasCategory = post.taxonomies.grant_category.some((category) =>
90 activeTags.includes(category)
106 activeTags.includes(category)
92 const noTagsSelected = activeTags.length === 0;
109 const noTagsSelected = activeTags.length === 0;
93 const hasType = post.taxonomies.grant_type.some((type) =>
110 const hasType = post.taxonomies.grant_type.some((type) =>
94 activeTypes.includes(type)
111 activeTypes.includes(type)
97− return (hasCategory || noTagsSelected) && hasType;
114+ return (hasCategory || noTagsSelected) && byStatus(post) && hasType;
100− const allCount = postsByCompletion.length;
117+ const allCount = postsByStatus.length;
102 const counts = {
119 const counts = {
103− Bounty: postsByCompletion.filter((post) =>
120+ Bounty: postsByStatus.filter((post) =>
104 post.taxonomies.grant_type.includes("Bounty")
121 post.taxonomies.grant_type.includes("Bounty")
105 ).length,
122 ).length,
106− Apprenticeship: postsByCompletion.filter((post) =>
123+ Apprenticeship: postsByStatus.filter((post) =>
107 post.taxonomies.grant_type.includes("Apprenticeship")
124 post.taxonomies.grant_type.includes("Apprenticeship")
108 ).length,
125 ).length,
109− Proposal: postsByCompletion.filter((post) =>
126+ Proposal: postsByStatus.filter((post) =>
110 post.taxonomies.grant_type.includes("Proposal")
127 post.taxonomies.grant_type.includes("Proposal")
111 ).length,
128 ).length,
@@ -123,7 +140,7 @@ export default function Grants({
123 // Heading and introduction
140 // Heading and introduction
125 <Section wide short>
142 <Section wide short>
126− <div className="flex flex-column justify-between">
143+ <div className="flex flex-column justify-between pb-16">
128 <h1 className="pb-16">Grants</h1>
145 <h1 className="pb-16">Grants</h1>
129 <p className="mb-8">
146 <p className="mb-8">
@@ -137,7 +154,23 @@ export default function Grants({
137 at urbit.org, Tlon developers, and community mentors.
154 at urbit.org, Tlon developers, and community mentors.
140− <TableOfContents staticPosition noh3s />
157+ </div>
158+ <div className="flex flex-wrap">
159+ <Link href="#find-a-grant">
160+ <button className="button-lg bg-green text-white mr-2">
164+ <Link href="#proposals">
165+ <button className="button-lg bg-blue text-white mr-2">
169+ <Link href="#gifts">
170+ <a className="button-lg bg-ultraDeepWall text-white mr-2">
142 </Section>
175 </Section>
@@ -171,12 +204,79 @@ export default function Grants({
173 </Section>
206 </Section>
174− {
207+ {/* Submit a proposal */}
209+ <h2 className="mb-16" id="proposals">
212+ <p className="mb-8">
213+ Contributors are also welcome to have their personal projects
214+ considered as a proposal. If you'd like to propose a project for the
215+ grants program, first review our
216+ <a href="/grant-submission-guide">submission guide</a>, and feel
218+ <a href="https://airtable.com/shrCi54rEDxgSZr3z">
219+ submit your proposal
224+ <Link href="#find-a-grant">
226+ className="button-lg bg-blue text-white mr-2"
228+ setIncludeInProgress(true);
229+ setIncludeCompleted(true);
231+ setTypes(["Proposal"]);
240+ <div className="pb-16">
241+ <h2 className="pb-16" id="gifts">
244+ <p className="mb-8">
245+ Gifts are given post-facto for exceptional contributions.
247+ {/* Uncomment once people added to content/gifts folder. */}
248+ {/* {gifts.map((e) => {
250+ <div className="bg-wall rounded-xl p-4 my-8 flex justify-between">
251+ <p className="font-semibold">
256+ <a className="type-p" href={e.link}>Link</a>
260+ <div className="flex flex-wrap">
263+ className={`w-full md:w-1/2 pr-0 pb-8 md:pr-4`}
264+ key={giftPosts[0].slug}
265+ section={giftPosts[0].section}
269+ className={`w-full md:w-1/2 pl-0 pb-8 md:pl-4`}
270+ key={giftPosts[1].slug}
271+ section={giftPosts[1].section}
175− // Find a Grant
276+ {/* Find a Grant */}
177 <Section wide>
277 <Section wide>
178 <h2 id="find-a-grant" className="pb-8">
278 <h2 id="find-a-grant" className="pb-8">
179− Find A Grant
279+ Find a Grant
181 <h5 className="text-black font-semibold my-2">Work Programs</h5>
281 <h5 className="text-black font-semibold my-2">Work Programs</h5>
182 <div className="flex flex-wrap items-center pb-2">
282 <div className="flex flex-wrap items-center pb-2">
@@ -233,6 +333,13 @@ export default function Grants({
235 <div className="pb-8 flex items-center">
335 <div className="pb-8 flex items-center">
337+ className="mr-4 badge-sm bg-black text-white"
338+ onClick={() => setIncludeOpen(!includeOpen)}
340+ {includeOpen ? "Exclude Open" : "Include Open"}
237 className="mr-4 badge-sm bg-black text-white"
344 className="mr-4 badge-sm bg-black text-white"
238 onClick={() => setIncludeCompleted(!includeCompleted)}
345 onClick={() => setIncludeCompleted(!includeCompleted)}
@@ -240,6 +347,15 @@ export default function Grants({
240 {includeCompleted ? "Exclude Completed" : "Include Completed"}
347 {includeCompleted ? "Exclude Completed" : "Include Completed"}
241 </button>
348 </button>
351+ className="mr-4 badge-sm bg-black text-white"
352+ onClick={() => setIncludeInProgress(!includeInProgress)}
355+ ? "Exclude In Progress"
356+ : "Include In Progress"}
244 Showing {filteredPosts.length} grant
360 Showing {filteredPosts.length} grant
245 {filteredPosts.length === 1 ? "" : "s"}
361 {filteredPosts.length === 1 ? "" : "s"}
@@ -250,63 +366,6 @@ export default function Grants({
250 return <GrantPreview grant={post} />;
366 return <GrantPreview grant={post} />;
252 </Section>
368 </Section>
253− {/* Submit a proposal */}
255− <h2 className="mb-16" id="proposals">
258− <p className="mb-8">
259− Contributors are also welcome to have their personal projects
260− considered as a proposal. If you'd like to propose a project for the
261− grants program, first review our
262− <a href="/grant-submission-guide">submission guide</a>, and feel
264− <a href="https://airtable.com/shrCi54rEDxgSZr3z">
265− submit your proposal
274− <div className="pb-16">
275− <h2 className="pb-16" id="gifts">
278− <p className="mb-8">
279− Gifts are given post-facto for exceptional contributions.
281− {/* Uncomment once people added to content/gifts folder. */}
282− {/* {gifts.map((e) => {
284− <div className="bg-wall rounded-xl p-4 my-8 flex justify-between">
285− <p className="font-semibold">
290− <a className="type-p" href={e.link}>Link</a>
294− <div className="flex flex-wrap">
297− className={`w-full md:w-1/2 pr-0 pb-8 md:pr-4`}
298− key={giftPosts[0].slug}
299− section={giftPosts[0].section}
303− className={`w-full md:w-1/2 pl-0 pb-8 md:pl-4`}
304− key={giftPosts[1].slug}
305− section={giftPosts[1].section}
310 </SingleColumn>
369 </SingleColumn>
311 <Footer />
370 <Footer />
312 </Container>
371 </Container>