From d2e04f5b23c93433eaea17d8b61a3edd09d0834a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ant=C3=B4nio?= Date: Thu, 16 Jan 2025 09:51:43 -0300 Subject: [PATCH 1/5] fea: add admin & admin/login routes - implemented a mocked auth check for admin routes - added /admin and /admin/login routes --- app/routes.ts | 7 ++++- app/routes/admin.login.tsx | 64 ++++++++++++++++++++++++++++++++++++++ app/routes/admin.tsx | 25 +++++++++++++++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 app/routes/admin.login.tsx create mode 100644 app/routes/admin.tsx diff --git a/app/routes.ts b/app/routes.ts index a4c86c3..16ccc57 100644 --- a/app/routes.ts +++ b/app/routes.ts @@ -3,4 +3,9 @@ import { flatRoutes } from "@react-router/fs-routes"; const routes = await flatRoutes(); -export default [...routes, route("/*", "./catchall.tsx")] satisfies RouteConfig; +const allRoutes = [ + ...routes, + route("/*", "./catchall.tsx"), +] satisfies RouteConfig; + +export default allRoutes; diff --git a/app/routes/admin.login.tsx b/app/routes/admin.login.tsx new file mode 100644 index 0000000..556d86a --- /dev/null +++ b/app/routes/admin.login.tsx @@ -0,0 +1,64 @@ +import { GithubIcon } from "@packages/components/icons/GithubIcon"; +import { + type ActionFunction, + type ActionFunctionArgs, + Form, + useActionData, + useLoaderData, +} from "react-router"; + +const REDIRECT_URI = "http://localhost:3000/api/auth/callback/github"; +export function loader() { + return { title: "Login", redirectUri: REDIRECT_URI }; +} + +export async function action({ request }: ActionFunctionArgs) { + const url = new URL(request.url); + // TODO: setup a redirect to GitHub provider + return { title: "Signed In", redirectUri: url }; +} + +export default function LoginPage({ errors = "" }) { + const initialState = useLoaderData(); + const currentState = useActionData(); + + console.log({ initialState, currentState }); + + const githubButton = ( +
+ + {currentState?.title ?? initialState.title} with GitHub +
+ ); + + return ( +
+
+
+

+ Welcome to PodCodar Admin 👋 +

+ +

+ Welcome back! Please sign in to continue +

+
+ +
+ + +

+ We use GitHub for authentication to keep things simple and secure. +

+
+ + {errors &&

{errors}

} +
+
+ ); +} diff --git a/app/routes/admin.tsx b/app/routes/admin.tsx new file mode 100644 index 0000000..1e23841 --- /dev/null +++ b/app/routes/admin.tsx @@ -0,0 +1,25 @@ +import Section from "@packages/components/Section"; +import { type LoaderFunctionArgs, Outlet, redirect } from "react-router"; + +export function loader({ request }: LoaderFunctionArgs) { + const url = new URL(request.url); + + // if it's not the login page, ignore auth check + const isLogin = url.pathname === "/admin/login"; + if (isLogin) return; + + // TODO: redirect if no sessions is available + const session = null; + const isAuth = !!session; + if (!isAuth) { + return redirect("/admin/login"); + } +} + +export default function AdminPage() { + return ( +
+ +
+ ); +} From 0d40e77c70ecbe77e3c2b1e56b835a183a956c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ant=C3=B4nio?= Date: Thu, 16 Jan 2025 09:53:46 -0300 Subject: [PATCH 2/5] ref: bun fmt --- biome.json | 2 +- docs/.vitepress/config.mts | 117 +++++++++++++++++--------------- docs/.vitepress/theme/config.ts | 88 ++++++++++++------------ docs/.vitepress/theme/index.ts | 5 +- postcss.config.mjs | 6 +- 5 files changed, 112 insertions(+), 106 deletions(-) diff --git a/biome.json b/biome.json index f889bcd..ce01c46 100644 --- a/biome.json +++ b/biome.json @@ -1,7 +1,7 @@ { "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json", "files": { - "ignore": ["build/*"] + "ignore": ["build/*", "migrations/*"] }, "organizeImports": { "enabled": true diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 75dceba..1e494d6 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -1,60 +1,67 @@ -import { defineConfigWithTheme } from 'vitepress' +import { defineConfigWithTheme } from "vitepress"; -import type { ThemeConfig } from "vitepress-carbon" +import type { ThemeConfig } from "vitepress-carbon"; import { withMermaid } from "vitepress-plugin-mermaid"; -import { carbonConfig } from './theme/config' +import { carbonConfig } from "./theme/config"; // https://vitepress.dev/reference/site-config let config = defineConfigWithTheme({ - extends: carbonConfig, - title: "PodCodar Engineering Wiki", - description: "Engineering documentation for PodCodar Developers", - - srcDir: "src", - base: "/webapp/", - - themeConfig: { - // https://vitepress.dev/reference/default-theme-config - nav: [ - { text: "Home", link: "/" }, - { text: "Guidelines", link: "/guidelines" }, - { text: "Board", link: "https://github.com/orgs/podcodar/projects/13", target: "_blank" }, - ], - - search: { - provider: "local", - }, - - sidebar: [ - { - text: "Vitepress Examples", - link: "/vitepress/", - items: [ - { text: "Markdown Examples", link: "/vitepress/markdown-examples" }, - { text: "Runtime API Examples", link: "/vitepress/api-examples" }, - ], - }, - { - text: "Guidelines", - link: "/guidelines/", - items: [ - { text: "Code Standards", link: "/guidelines/coding-standards" }, - { text: "Git Workflow", link: "/guidelines/git-workflow" }, - { text: "Pull Request Guidelines", link: "/guidelines/pull-requests" }, - { text: "Code Review Guidelines", link: "/guidelines/code-review" }, - ], - } - ], - - socialLinks: [ - { - icon: "github", - link: "https://github.com/podcodar/webapp/", - }, - ], - }, -}) - -config = withMermaid(config) - -export default config + extends: carbonConfig, + title: "PodCodar Engineering Wiki", + description: "Engineering documentation for PodCodar Developers", + + srcDir: "src", + base: "/webapp/", + + themeConfig: { + // https://vitepress.dev/reference/default-theme-config + nav: [ + { text: "Home", link: "/" }, + { text: "Guidelines", link: "/guidelines" }, + { + text: "Board", + link: "https://github.com/orgs/podcodar/projects/13", + target: "_blank", + }, + ], + + search: { + provider: "local", + }, + + sidebar: [ + { + text: "Vitepress Examples", + link: "/vitepress/", + items: [ + { text: "Markdown Examples", link: "/vitepress/markdown-examples" }, + { text: "Runtime API Examples", link: "/vitepress/api-examples" }, + ], + }, + { + text: "Guidelines", + link: "/guidelines/", + items: [ + { text: "Code Standards", link: "/guidelines/coding-standards" }, + { text: "Git Workflow", link: "/guidelines/git-workflow" }, + { + text: "Pull Request Guidelines", + link: "/guidelines/pull-requests", + }, + { text: "Code Review Guidelines", link: "/guidelines/code-review" }, + ], + }, + ], + + socialLinks: [ + { + icon: "github", + link: "https://github.com/podcodar/webapp/", + }, + ], + }, +}); + +config = withMermaid(config); + +export default config; diff --git a/docs/.vitepress/theme/config.ts b/docs/.vitepress/theme/config.ts index 1f24a72..3d56b7e 100644 --- a/docs/.vitepress/theme/config.ts +++ b/docs/.vitepress/theme/config.ts @@ -1,52 +1,52 @@ // reference https://github.com/brenoepics/vitepress-carbon/blob/main/packages/theme/src/theme/config/baseConfig.ts -import type { UserConfig } from 'vitepress' -import type { ThemeConfig } from 'vitepress-carbon' +import type { UserConfig } from "vitepress"; +import type { ThemeConfig } from "vitepress-carbon"; -const deps = ['vitepress/theme', '@vueuse/core', 'body-scroll-lock'] +const deps = ["vitepress/theme", "@vueuse/core", "body-scroll-lock"]; export const carbonConfig: UserConfig = { - scrollOffset: ['header', '.VPLocalNav'], - appearance: { - initialValue: 'dark' - }, - vite: { - ssr: { - noExternal: [...deps, /\.css$/, /^vitepress-carbon/] - }, - optimizeDeps: { - exclude: deps - } - }, + scrollOffset: ["header", ".VPLocalNav"], + appearance: { + initialValue: "dark", + }, + vite: { + ssr: { + noExternal: [...deps, /\.css$/, /^vitepress-carbon/], + }, + optimizeDeps: { + exclude: deps, + }, + }, - head: [], + head: [], - markdown: { - headers: { - level: [2, 3] - }, - config(_md) { } - }, + markdown: { + headers: { + level: [2, 3], + }, + config(_md) {}, + }, - transformHead({ assets }) { - const font = assets.find((file) => /Mona-Sans\.\w+\.woff2/.test(file)) - if (font) { - return [ - [ - 'link', - { - rel: 'preload', - href: font, - as: 'font', - type: 'font/woff2', - crossorigin: '' - } - ] - ] - } - }, + transformHead({ assets }) { + const font = assets.find((file) => /Mona-Sans\.\w+\.woff2/.test(file)); + if (font) { + return [ + [ + "link", + { + rel: "preload", + href: font, + as: "font", + type: "font/woff2", + crossorigin: "", + }, + ], + ]; + } + }, - shouldPreload(link) { - // make algolia chunk prefetch instead of preload - return !link.includes('Algolia') - } -} + shouldPreload(link) { + // make algolia chunk prefetch instead of preload + return !link.includes("Algolia"); + }, +}; diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts index 705f079..6e5ad52 100644 --- a/docs/.vitepress/theme/index.ts +++ b/docs/.vitepress/theme/index.ts @@ -1,4 +1,3 @@ -import { VPCarbon } from "vitepress-carbon" - -export default VPCarbon +import { VPCarbon } from "vitepress-carbon"; +export default VPCarbon; diff --git a/postcss.config.mjs b/postcss.config.mjs index 1a69fd2..f6c3605 100644 --- a/postcss.config.mjs +++ b/postcss.config.mjs @@ -1,8 +1,8 @@ /** @type {import('postcss-load-config').Config} */ const config = { - plugins: { - tailwindcss: {}, - }, + plugins: { + tailwindcss: {}, + }, }; export default config; From 69f933823735f6114f699a2bca479196ed19e0fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ant=C3=B4nio?= Date: Sat, 18 Jan 2025 12:37:43 -0300 Subject: [PATCH 3/5] fea: add hero component --- packages/components/HeroSection.tsx | 45 +++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 packages/components/HeroSection.tsx diff --git a/packages/components/HeroSection.tsx b/packages/components/HeroSection.tsx new file mode 100644 index 0000000..2ccf61a --- /dev/null +++ b/packages/components/HeroSection.tsx @@ -0,0 +1,45 @@ +import { Illustration } from "@packages/components/icons"; + +import { links } from "@packages/config/site"; +import { LocalizedText } from "@packages/locale/context"; +import Section from "./Section"; + +export default function HeroSection() { + return ( +
+
+
+

+ , + }} + /> +

+ +

+ +

+ +
+ + + + + + + +
+
+ +
+ +
+
+
+ ); +} From 1de59dbe7f20ee4b52c26c3a581acf546442ee90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Ant=C3=B4nio?= Date: Sat, 18 Jan 2025 13:11:25 -0300 Subject: [PATCH 4/5] fea: add hero section --- app/routes/_index.tsx | 46 +- packages/components/CallToActionSection.tsx | 38 -- packages/components/HeroSection.tsx | 8 +- packages/components/icons/Illustration.tsx | 691 ++++++++++---------- packages/locale/en.yml | 7 +- packages/locale/pt.yml | 8 +- 6 files changed, 379 insertions(+), 419 deletions(-) delete mode 100644 packages/components/CallToActionSection.tsx diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx index a2b0f1a..da2bedd 100644 --- a/app/routes/_index.tsx +++ b/app/routes/_index.tsx @@ -1,5 +1,5 @@ -import CallToActionSection from "@packages/components/CallToActionSection"; import Footer from "@packages/components/Footer"; +import HeroSection from "@packages/components/HeroSection"; import MentoringSection from "@packages/components/MentoringSection"; import RoadmapSection from "@packages/components/RoadmapSection"; import TechSection from "@packages/components/TechSection"; @@ -9,35 +9,35 @@ import WhyItWorksSection from "@packages/components/WhyItWorksSection"; import { description, title } from "@packages/config/site"; import { Database } from "@packages/repositories/db"; import { - type LoaderFunctionArgs, - type MetaFunction, - useLoaderData, + type LoaderFunctionArgs, + type MetaFunction, + useLoaderData, } from "react-router"; export const meta: MetaFunction = () => { - return [{ title }, { name: "description", content: description }]; + return [{ title }, { name: "description", content: description }]; }; export async function loader({ context }: LoaderFunctionArgs) { - const db = new Database( - context.cloudflare.env.TURSO_CONNECTION_URL, - context.cloudflare.env.TURSO_AUTH_TOKEN, - ); - const testimonials = await db.testimonials; - return { testimonials }; + const db = new Database( + context.cloudflare.env.TURSO_CONNECTION_URL, + context.cloudflare.env.TURSO_AUTH_TOKEN, + ); + const testimonials = await db.testimonials; + return { testimonials }; } export default function Index() { - const { testimonials } = useLoaderData(); - return ( - <> - - - - - - -