-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit c7201b9
Showing
51 changed files
with
9,694 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/** | ||
* This is intended to be a basic starting point for linting in your app. | ||
* It relies on recommended configs out of the box for simplicity, but you can | ||
* and should modify this configuration to best suit your team's needs. | ||
*/ | ||
|
||
/** @type {import('eslint').Linter.Config} */ | ||
module.exports = { | ||
root: true, | ||
parserOptions: { | ||
ecmaVersion: "latest", | ||
sourceType: "module", | ||
ecmaFeatures: { | ||
jsx: true, | ||
}, | ||
}, | ||
env: { | ||
browser: true, | ||
commonjs: true, | ||
es6: true, | ||
}, | ||
|
||
// Base config | ||
extends: ["eslint:recommended"], | ||
|
||
overrides: [ | ||
// React | ||
{ | ||
files: ["**/*.{js,jsx,ts,tsx}"], | ||
plugins: ["react", "jsx-a11y"], | ||
extends: [ | ||
"plugin:react/recommended", | ||
"plugin:react/jsx-runtime", | ||
"plugin:react-hooks/recommended", | ||
"plugin:jsx-a11y/recommended", | ||
], | ||
settings: { | ||
react: { | ||
version: "detect", | ||
}, | ||
formComponents: ["Form"], | ||
linkComponents: [ | ||
{ name: "Link", linkAttribute: "to" }, | ||
{ name: "NavLink", linkAttribute: "to" }, | ||
], | ||
"import/resolver": { | ||
typescript: {}, | ||
}, | ||
}, | ||
}, | ||
|
||
// Typescript | ||
{ | ||
files: ["**/*.{ts,tsx}"], | ||
plugins: ["@typescript-eslint", "import"], | ||
parser: "@typescript-eslint/parser", | ||
settings: { | ||
"import/internal-regex": "^~/", | ||
"import/resolver": { | ||
node: { | ||
extensions: [".ts", ".tsx"], | ||
}, | ||
typescript: { | ||
alwaysTryTypes: true, | ||
}, | ||
}, | ||
}, | ||
extends: [ | ||
"plugin:@typescript-eslint/recommended", | ||
"plugin:import/recommended", | ||
"plugin:import/typescript", | ||
], | ||
}, | ||
|
||
// Node | ||
{ | ||
files: [".eslintrc.cjs"], | ||
env: { | ||
node: true, | ||
}, | ||
}, | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
name: Deploy | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
deploy: | ||
runs-on: ubuntu-latest | ||
name: Deploy | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
|
||
- name: Install Node.js | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: 20 | ||
|
||
- name: Install pnpm | ||
uses: pnpm/action-setup@v4 | ||
with: | ||
version: 9 | ||
run_install: false | ||
|
||
- name: Install dependencies | ||
run: pnpm install | ||
|
||
- name: Deploy | ||
uses: cloudflare/wrangler-action@v3 | ||
with: | ||
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
node_modules | ||
|
||
/.wrangler | ||
/build | ||
.env | ||
.dev.vars |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# Welcome to Remix + Cloudflare Workers! | ||
|
||
- 📖 [Remix docs](https://remix.run/docs) | ||
- 📖 [Remix Cloudflare docs](https://remix.run/guides/vite#cloudflare) | ||
|
||
## Development | ||
|
||
Run the dev server: | ||
|
||
```sh | ||
npm run dev | ||
``` | ||
|
||
To run Wrangler: | ||
|
||
```sh | ||
npm run build | ||
npm start | ||
``` | ||
|
||
## Typegen | ||
|
||
Generate types for your Cloudflare bindings in `wrangler.toml`: | ||
|
||
```sh | ||
npm run typegen | ||
``` | ||
|
||
You will need to rerun typegen whenever you make changes to `wrangler.toml`. | ||
|
||
## Deployment | ||
|
||
If you don't already have an account, then [create a cloudflare account here](https://dash.cloudflare.com/sign-up) and after verifying your email address with Cloudflare, go to your dashboard and set up your free custom Cloudflare Workers subdomain. | ||
|
||
Once that's done, you should be able to deploy your app: | ||
|
||
```sh | ||
npm run deploy | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { Octokit } from '@octokit/core' | ||
import * as process from 'node:process' | ||
|
||
export const client = (url: string, options: RequestInit) => { | ||
return fetch(url, options) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error(response.statusText, { cause: response }) | ||
} | ||
return response.json() | ||
}) | ||
.catch((error: Error) => { | ||
if (process.env.NODE_ENV !== 'production') console.error(error) | ||
return Promise.reject(error) | ||
}) | ||
} | ||
|
||
export const octokit = new Octokit({ | ||
auth: process.env.GITHUB_TOKEN, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { octokit } from './client' | ||
|
||
export const IssuesAPI = { | ||
get: () => | ||
octokit.request('GET /repos/{owner}/{repo}/issues', { | ||
owner: 'MarcosNASA', | ||
repo: 'is-sexism-over.tech', | ||
state: 'closed', | ||
labels: 'testimonial', | ||
sort: 'created', | ||
direction: 'desc', | ||
headers: { | ||
'X-GitHub-Api-Version': '2022-11-28', | ||
}, | ||
}), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* By default, Remix will handle hydrating your app on the client for you. | ||
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ | ||
* For more information, see https://remix.run/file-conventions/entry.client | ||
*/ | ||
|
||
import { RemixBrowser } from "@remix-run/react"; | ||
import { startTransition, StrictMode } from "react"; | ||
import { hydrateRoot } from "react-dom/client"; | ||
|
||
startTransition(() => { | ||
hydrateRoot( | ||
document, | ||
<StrictMode> | ||
<RemixBrowser /> | ||
</StrictMode> | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
/** | ||
* By default, Remix will handle generating the HTTP Response for you. | ||
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨ | ||
* For more information, see https://remix.run/file-conventions/entry.server | ||
*/ | ||
|
||
import type { AppLoadContext, EntryContext } from "@remix-run/cloudflare"; | ||
import { RemixServer } from "@remix-run/react"; | ||
import { isbot } from "isbot"; | ||
import { renderToReadableStream } from "react-dom/server"; | ||
|
||
export default async function handleRequest( | ||
request: Request, | ||
responseStatusCode: number, | ||
responseHeaders: Headers, | ||
remixContext: EntryContext, | ||
// This is ignored so we can keep it in the template for visibility. Feel | ||
// free to delete this parameter in your app if you're not using it! | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
loadContext: AppLoadContext | ||
) { | ||
const body = await renderToReadableStream( | ||
<RemixServer context={remixContext} url={request.url} />, | ||
{ | ||
signal: request.signal, | ||
onError(error: unknown) { | ||
// Log streaming rendering errors from inside the shell | ||
console.error(error); | ||
responseStatusCode = 500; | ||
}, | ||
} | ||
); | ||
|
||
if (isbot(request.headers.get("user-agent") || "")) { | ||
await body.allReady; | ||
} | ||
|
||
responseHeaders.set("Content-Type", "text/html"); | ||
return new Response(body, { | ||
headers: responseHeaders, | ||
status: responseStatusCode, | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import React from 'react' | ||
import { type Experience } from '~/features/experience/domain' | ||
import { Countdown as CountdownDomain } from '~/features/countdown/domain' | ||
import { Text } from '~/features/text/domain' | ||
import { Styles } from '~/features/ui/domain' | ||
import { Anchor } from '~/features/ui/components/Anchor' | ||
|
||
export const Countdown = ({ | ||
lastExperience, | ||
}: { | ||
lastExperience?: Experience | ||
}) => { | ||
const [countdown, setCountdown] = React.useState(() => | ||
lastExperience | ||
? CountdownDomain.countdown(lastExperience.createdAt) | ||
: { days: 0, hours: 0, minutes: 0, seconds: 0 }, | ||
) | ||
|
||
const isOver = lastExperience | ||
? CountdownDomain.isOver(lastExperience.createdAt) | ||
: true | ||
|
||
React.useEffect(() => { | ||
if (!lastExperience) return | ||
const interval = setInterval(() => { | ||
setCountdown(CountdownDomain.countdown(lastExperience.createdAt)) | ||
}, 1000) | ||
return () => clearInterval(interval) | ||
}, [lastExperience]) | ||
|
||
if (isOver) { | ||
return ( | ||
<div className="group flex flex-col items-start md:items-center justify-center gap-1 lg:gap-4"> | ||
<div className="flex flex-col gap-0 text-start md:text-center text-4xl md:text-9xl font-yeseva font-bold"> | ||
<span>Sexism is</span> | ||
<span | ||
className={Styles.cn( | ||
'flex md:justify-center items-center', | ||
'text-pink-400', | ||
'h-[0px] group-hover:h-[1.5ch] opacity-0 group-hover:opacity-100', | ||
'[transition:height_0.6s_0s_ease-in,opacity_0.3s_0.3s_ease-out]', | ||
)} | ||
> | ||
not | ||
</span> | ||
<span>over!</span> | ||
</div> | ||
|
||
<div className={Styles.cn('text-2xl lg:text-2xl text-zinc-400')}> | ||
<Anchor href="https://github.com/MarcosNASA/is-sexism-over.tech/issues/new"> | ||
Share your experience | ||
</Anchor>{' '} | ||
to reset the countdown | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
return ( | ||
<div className="flex flex-col justify-center items-center gap-6"> | ||
<div className="flex flex-col justify-center items-center gap-2 font-yeseva"> | ||
<div className="flex justify-center items-center gap-4 tabular-nums"> | ||
<div className="flex flex-col lg:flex-row justify-center items-center gap-2"> | ||
<span className="text-2xl lg:text-5xl font-bold"> | ||
{String(countdown.days).padStart(2, '0')}{' '} | ||
</span> | ||
<span className="text-3xl lg:text-4xl font-semibold"> | ||
{Text.pluralize(countdown.days, { singular: 'day' })} | ||
</span> | ||
</div> | ||
<div className="flex flex-col lg:flex-row justify-center items-center gap-2"> | ||
<span className="text-2xl lg:text-5xl font-bold"> | ||
{String(countdown.hours).padStart(2, '0')}{' '} | ||
</span> | ||
<span className="text-3xl lg:text-4xl font-semibold"> | ||
{Text.pluralize(countdown.hours, { singular: 'hour' })} | ||
</span> | ||
</div> | ||
<div className="flex flex-col lg:flex-row justify-center items-center gap-2"> | ||
<span className="text-2xl lg:text-5xl font-bold"> | ||
{String(countdown.minutes).padStart(2, '0')}{' '} | ||
</span> | ||
<span className="text-3xl lg:text-4xl font-semibold"> | ||
{Text.pluralize(countdown.minutes, { singular: 'minute' })} | ||
</span> | ||
</div> | ||
<div className="flex flex-col lg:flex-row justify-center items-center gap-2"> | ||
<span className="text-2xl lg:text-5xl font-bold"> | ||
{String(countdown.seconds).padStart(2, '0')}{' '} | ||
</span> | ||
<span className="text-3xl lg:text-4xl font-semibold"> | ||
{Text.pluralize(countdown.seconds, { singular: 'second' })} | ||
</span> | ||
</div> | ||
</div> | ||
|
||
<span className="text-2xl lg:text-5xl font-yeseva font-bold"> | ||
left for sexism to be over | ||
</span> | ||
</div> | ||
|
||
<div className="text-2xl text-zinc-400"> | ||
<Anchor href="https://github.com/MarcosNASA/is-sexism-over.tech/issues/new"> | ||
Share your experience | ||
</Anchor>{' '} | ||
to reset the countdown | ||
</div> | ||
</div> | ||
) | ||
} | ||
|
||
const CountdownSkeleton = () => { | ||
return <div className="w-full" /> | ||
} | ||
|
||
Countdown.Skeleton = CountdownSkeleton |
Oops, something went wrong.