Skip to content

Commit

Permalink
feat: Add November 2024 Challenge to the Website (#1286)
Browse files Browse the repository at this point in the history
* feat: add november 2024 challenge

* chore: add completed challenge alert to october 2024

* chore: update challenge homepage

* fix: wording and grammar

* Prettified Code!

* fix: minor wording change

* abstract writing challenge data

---------

Co-authored-by: adiati98 <[email protected]>
Co-authored-by: Dan Ott <[email protected]>
  • Loading branch information
3 people authored Oct 31, 2024
1 parent 653b902 commit 428c748
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/app/monthlychallenges/(challenges)/nov-2023/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable react/no-unescaped-entities */
import { Fragment } from 'react';
import { createMetaData } from '@/util/createMetaData.server';
import { getChallengeData } from '@/data/monthlyChallenges/nov-2023';
import { getWritingChallengeData } from '@/data/monthlyChallenges/NaNoWriMo';
import LeadText from '@/components/content/LeadText';
import Link from 'next/link';
import DefaultLayout from '@/components/layouts/DefaultLayout';
Expand All @@ -24,7 +24,7 @@ export const metadata = handle.meta;
async function getData() {
const { title } = handle.meta;

const data = await getChallengeData();
const data = await getWritingChallengeData('NaNoWriMo 2024');

const description = `Current status: ${data.totals.totalCount.toLocaleString()} out of ${
data.currentGoal?.title
Expand Down
266 changes: 266 additions & 0 deletions src/app/monthlychallenges/(challenges)/nov-2024/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
/* eslint-disable react/no-unescaped-entities */
import { Fragment } from 'react';
import { createMetaData } from '@/util/createMetaData.server';
import { getWritingChallengeData } from '@/data/monthlyChallenges/NaNoWriMo';
import LeadText from '@/components/content/LeadText';
import DefaultLayout from '@/components/layouts/DefaultLayout';

const handle = {
listTitle: 'November, 2024: 50k words!',
meta: {
title: 'Monthly Theme & Challenge for November, 2024: 50k words!',
description:
'November challenge -> Blogging: we all work together to hit 50,000 words.',
},
date: '2024-11-01',
hero: {
heroHeader: '',
},
};

export const metadata = handle.meta;

async function getData() {
const { title } = handle.meta;

const data = await getWritingChallengeData('NaNoWriMo 2024');

const description = `Current status: ${data.totals.totalCount.toLocaleString()} out of ${
data.currentGoal?.title
} words`;

return {
...data,
meta: createMetaData({ title, description }),
};
}

export default async function Challenge() {
const { sortedList, totals, completedGoals, currentGoal, meta } =
await getData();

return (
<DefaultLayout
heroHeader={meta.title as string}
heroSubheader={meta.description as string}
>
<h1>
<small>Monthly Challenge for November 2024:</small> Let's write 50k
words together!
</h1>

<LeadText>
<p>
This month, we're working together to blog 50,000 words! Based off the{' '}
<a href="https://nanowrimo.org/">
NaNoWriMo (National Novel Writing Month) Challenge
</a>
, we'll be doing the tech and non-tech take on writing and working
together towards the goal while posting on our own blogs.
</p>
<p>Get those blog posts up!</p>
</LeadText>

{totals.totalPosts > 0 && (
<>
{completedGoals.length ? (
<>
<h2>
<small>Current status:</small>
</h2>

<ul>
{completedGoals.map((goal, i) => (
<li key={i} className="lead">
{goal.title} goal completed!!!
</li>
))}
</ul>

<div className="h3">
Stretch Goal {completedGoals.length}:{' '}
{totals.totalCount.toLocaleString()} out of{' '}
{currentGoal?.value.toLocaleString()} words
</div>
</>
) : (
<h2>
Current status: {totals.totalCount.toLocaleString()} out of{' '}
{currentGoal?.title} words
</h2>
)}

<div className="progress my-4" style={{ height: '3em' }}>
<div
className="progress-bar progress-bar progress-bar-striped"
role="progressbar"
style={{
width: `${
(totals.totalCount / (currentGoal?.value || 1)) * 100
}%`,
}}
aria-valuenow={totals.totalCount}
aria-valuemin={0}
aria-valuemax={currentGoal?.value}
>
{totals.totalCount.toLocaleString()} Words
</div>
</div>

<h2 className="mt-5">Our Posts:</h2>

{sortedList.map((author, i) => (
<Fragment key={i}>
<div className="header-anchor-wrapper header-anchor-wrapper-h3">
<h3 id={`${author.slug}`} tabIndex={-1}>
{author.name}
</h3>
<a className="header-anchor" href={`#${author.slug}`}>
<span className="sr-only">
Permalink to {author.name}'s posts
</span>
<span aria-hidden="true">#</span>
</a>
</div>

<ul>
{author.posts.map((post, j) => (
<li key={j}>
<a href={post.url}>{post.title}</a>
<code>({post.count.toLocaleString()} words)</code>
</li>
))}
</ul>
</Fragment>
))}

<h2 className="mt-5">Totals:</h2>

<table className="table mt-5" style={{ maxWidth: '600px' }}>
<thead className="thead-dark">
<tr>
<th scope="col">Member Totals</th>
<th scope="col" className="text-right">
Posts
</th>
<th scope="col" className="text-right">
Total Words
</th>
</tr>
</thead>
<tbody>
{totals.list.map((author, i) => (
<tr key={i}>
<td>{author.name}</td>
<td className="text-right">
{author.posts.toLocaleString()}
</td>
<td className="text-right">
{author.total.toLocaleString()}
</td>
</tr>
))}
</tbody>
<tfoot>
<tr>
<th scope="col">Total</th>
<th scope="col" className="text-right">
{totals.totalPosts.toLocaleString()}
</th>
<th scope="col" className="text-right">
{totals.totalCount.toLocaleString()} words
</th>
</tr>
</tfoot>
</table>
</>
)}

<h2>How to Participate</h2>

<p>
Once you've written and published your content,{' '}
<a
href="https://airtable.com/app10kd5ewHiLTjxn/shrgRjUFpNjLN1V12"
target="_blank"
rel="noreferrer"
>
add your entry to our VC NaNoWriMo entry form
</a>
!
</p>

<p>
<a
href="https://airtable.com/app10kd5ewHiLTjxn/shrgRjUFpNjLN1V12"
target="_blank"
rel="noreferrer"
className="btn btn-primary btn-lg"
>
Add Your Entry!
</a>
</p>

<h3>What kind of content counts towards the challenge?</h3>

<p>
Any tech-related or non-tech blog posts, articles, or novels published
in November! For tech-related posts, feel free to include code samples
in your word count totals (if it's a word and you wrote it, we'll count
it 😊).
</p>

<p>
While we love good documentation here at Virtual Coffee, README docs, or
anything else you would typically consider documentation, it doesn't
count for this challenge.
</p>

<h3>What if I'm not confident about my writing?</h3>

<p>
We all start somewhere. The more you practice, the better you'll get. We
have volunteers willing to proofread and give you feedback on your
writing. Just put a link to your draft in the{' '}
<code>#monthly-challenge</code> or <code>#content-creation</code>{' '}
channel and ask for the help you need.
</p>

<h3>What if I don't know what to write about?</h3>

<p>
We've got you covered with extensive topic lists in{' '}
<a href="https://github.com/Virtual-Coffee/virtualcoffee.io/discussions/711">
this discussion
</a>{' '}
and{' '}
<a href="https://github.com/Virtual-Coffee/virtualcoffee.io/discussions/458">
this discussion
</a>
.
</p>

<p>And remember, we're always here to help ❤️</p>

<h2>Resources</h2>
<ul>
<li>
<a href="https://www.youtube.com/watch?v=hD6uRvCtA_0">
How to Grow Your Tech Career Through Writing
</a>
</li>
<li>
<a href="https://twitter.com/amandanat/status/1448662631938596879?s=20">
Amanda Natividad's Twitter thread: 11 prompts so you'll never run
out of content ideas
</a>
</li>
<li>
<a href="https://dev.to/andrewbaisden/100-blog-topic-ideas-for-your-next-article-no-more-writers-block-2e0j">
100 Blog Topic Ideas for your Next Article
</a>
</li>
</ul>
</DefaultLayout>
);
}
5 changes: 5 additions & 0 deletions src/app/monthlychallenges/(challenges)/oct-2024/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export const metadata = handle.meta;
export default function Challenge() {
return (
<>
<div className="alert alert-success">
This monthly challenge is complete. Congratulations! Please join us for
the <Link href="/monthlychallenges/nov-2024">next challenge</Link>!
</div>

<h1>
<small>Monthly Challenge for October 2024:</small> It's Hacktoberfest!
Participate in open source, learn, and have fun!
Expand Down
19 changes: 11 additions & 8 deletions src/app/monthlychallenges/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,33 +190,37 @@ const challengeList: Challenge[] = [
],
},
{
current: true,
title: 'Blogging Challenge',
subtitle: `A Community Challenge to hit a word count goal for all our tech blogs.`,
subtitle: `A Community Challenge to hit a word count goal for all our tech and non-tech blogs.`,
description: (
<>
<p>
Based off the NaNoWriMo (National Novel Writing Month) Challenge, this
challenge is the tech take on writing and working together towards the
Based on the NaNoWriMo (National Novel Writing Month) Challenge, this
challenge is the tech and non-tech take on writing and working together towards the
goal while posting on our own blogs.
</p>
<p>
{/* <p>
Learn more about this challenge in{' '}
<a href="https://dev.to/virtualcoffee/blogging-2023-monthly-challenge-3kng">
this blog post
</a>
.
</p>
</p> */}
<p>
To view all of the details of this year&apos;s challenge,{' '}
<Link href="/monthlychallenges/nov-2023">
check out the November 2023 challenge page
<Link href="/monthlychallenges/nov-2024">
check out the November 2024 challenge page
</Link>
.
</p>
</>
),
links: [
{
href: '/monthlychallenges/nov-2023',
title: 'November, 2023',
}, {
href: '/monthlychallenges/nov-2022',
title: 'November, 2022',
},
Expand All @@ -231,7 +235,6 @@ const challengeList: Challenge[] = [
],
},
{
current: true,
title: 'Hacktoberfest',
subtitle: `Participate in open source, learn, and have fun!`,
description: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ type NovRow = {
created_at: string;
};

async function fetchRecords() {
async function fetchRecords(viewName: string) {
if (process.env.PUBLIC_AIRTABLE_API_KEY) {
const base = new Airtable({
apiKey: process.env.PUBLIC_AIRTABLE_API_KEY,
}).base('app10kd5ewHiLTjxn');

const result = await base<NovRow>('NaNoWriMo')
.select({
view: 'NaNoWriMo 2023',
view: viewName,
})
.all();

Expand Down Expand Up @@ -91,8 +91,8 @@ type PostMap = Record<
}
>;

export async function getChallengeData() {
const tableRows = await fetchRecords();
export async function getWritingChallengeData(viewName: string) {
const tableRows = await fetchRecords(viewName);

const totalCount = tableRows.reduce((total, row) => {
return total + row.WordCount;
Expand Down

0 comments on commit 428c748

Please sign in to comment.