Skip to content

Commit

Permalink
style improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
Nipsuli committed Apr 23, 2022
1 parent 06b4bfc commit 767087c
Show file tree
Hide file tree
Showing 21 changed files with 17,279 additions and 9,273 deletions.
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
SUPABASE_SERVICE_KEY=<read from supabase start>
PUBLIC_SUPABASE_ANON_KEY=<read from supabase start>
SUPABASE_URL=http://localhost:54321
SERVER_URL=http://localhost:8788
SERVER_URL=http://localhost:8788
COOKIE_SECRET_1=<random chars>
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ node_modules

/.cache
/functions/\[\[path\]\].js
/functions/\[\[path\]\].js.map
/public/build
.env

# Supabase
**/supabase/.branches
**/supabase/.temp
supabase/config.toml
.mf/
21 changes: 21 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
// Required: The website to display
"liveFrame.url": "http://localhost:8788",

// Optional: Title for the pane tab heading
"liveFrame.title": "Simple B2B app",

// Optional: Which pane to open the frame in
"liveFrame.pane": "Beside",

// "files.autoSave": "afterDelay",
// "files.autoSaveDelay": 50,
"files.associations": {
"*.css": "tailwindcss"
},

"editor.quickSuggestions": {
"strings": true
}

}
63 changes: 63 additions & 0 deletions app/auth.server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type { AppLoadContext } from "@remix-run/cloudflare";
import {
createCloudflareKVSessionStorage,
createCookie,
} from "@remix-run/cloudflare";
import type { Session } from "@supabase/supabase-js";
import { Authenticator, AuthorizationError } from "remix-auth";
import { SupabaseStrategy } from "remix-auth-supabase";
import { supabaseAdmin } from "./supabase.server";

export const getAuth = (context: AppLoadContext) => {
const sessionCookie = createCookie("__session", {
secrets: [context.COOKIE_SECRET_1],
sameSite: true,
});

const sessionStorage = createCloudflareKVSessionStorage({
kv: context.SESSION_KV,
cookie: sessionCookie,
});

const authStrategy = new SupabaseStrategy(
{
supabaseClient: supabaseAdmin(context),
sessionStorage,
sessionKey: "sb:session",
sessionErrorKey: "sb:error",
},
async ({ req }) => {
const form = await req.formData();
const session = form?.get("session");
if (typeof session !== "string")
throw new AuthorizationError("session not found");

return JSON.parse(session);
}
);

const authenticator = new Authenticator<Session>(sessionStorage, {
sessionKey: authStrategy.sessionKey,
sessionErrorKey: authStrategy.sessionErrorKey,
});

authenticator.use(authStrategy, "sb-auth");

return {
authenticator,
authStrategy,
};
};

export const getSession = async (
context: AppLoadContext,
request: Request,
redirectBack: boolean = true
) => {
const redirect = redirectBack
? `?redirectTo=${new URL(request.url).pathname}`
: "";
return getAuth(context).authStrategy.checkSession(request, {
failureRedirect: `/signin${redirect}`,
});
};
50 changes: 50 additions & 0 deletions app/components/darkModeToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import React, { useEffect, useState } from "react";

const updateDark = (dark: Boolean) => {
if (typeof document === "undefined") return;
const d = document.documentElement;
const themes = ["light", "dark"];

d.classList.remove(...themes);
d.classList.add(dark ? "dark" : "light");
localStorage.setItem("dark", JSON.stringify(dark));
};

const loadDark = () => {
if (typeof document === "undefined") return true;
const prefersDarkMode = matchMedia("(prefers-color-scheme: dark)").matches;
const lsDark =
localStorage.getItem("dark") || JSON.stringify(prefersDarkMode);
return Boolean(JSON.parse(lsDark));
};

const DarkModeToggle = ({ className }: { className?: string }) => {
const [dark, setDark] = useState(loadDark());

useEffect(() => {
updateDark(dark);
}, [dark]);

const toggleDark = () => {
setDark(!dark);
};

const moon =
"M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z";
const sun =
"M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z";

return (
<svg
className={className || "darktoggle"}
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
onClick={() => toggleDark()}
>
<path fillRule="evenodd" d={dark ? sun : moon} clipRule="evenodd" />
</svg>
);
};

export default DarkModeToggle;
2 changes: 2 additions & 0 deletions app/custom-types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,7 @@ declare module '@remix-run/cloudflare' {
SUPABASE_URL: string;
SUPABASE_SERVICE_KEY: string;
PUBLIC_SUPABASE_ANON_KEY: string;
COOKIE_SECRET_1: string;
SESSION_KV: KVNamespace;
}
}
3 changes: 1 addition & 2 deletions app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { EntryContext } from "@remix-run/cloudflare";
import { RemixServer } from "@remix-run/react";
import { renderToString } from "react-dom/server";
import { injectStylesIntoStaticMarkup } from '@mantine/ssr';

export default function handleRequest(
request: Request,
Expand All @@ -15,7 +14,7 @@ export default function handleRequest(

responseHeaders.set("Content-Type", "text/html");

return new Response(`<!DOCTYPE html>${injectStylesIntoStaticMarkup(markup)}`, {
return new Response(`<!DOCTYPE html>${markup}`, {
status: responseStatusCode,
headers: responseHeaders,
});
Expand Down
24 changes: 15 additions & 9 deletions app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import type { LoaderFunction, MetaFunction } from "@remix-run/cloudflare";
import type {
LinksFunction,
LoaderFunction,
MetaFunction,
} from "@remix-run/cloudflare";
import {
Links,
LiveReload,
Expand All @@ -9,6 +13,10 @@ import {
useCatch,
useLoaderData,
} from "@remix-run/react";
import DarkModeToggle from "./components/darkModeToggle";
import styles from "./tailwind.css";

export const links: LinksFunction = () => [{ rel: "stylesheet", href: styles }];

export const meta: MetaFunction = () => ({
charset: "utf-8",
Expand All @@ -17,19 +25,18 @@ export const meta: MetaFunction = () => ({
});

export const loader: LoaderFunction = ({ context }) => {
if (!context.SUPABASE_URL)
throw new Error('SUPABASE_URL is required')
if (!context.SUPABASE_URL) throw new Error("SUPABASE_URL is required");

if (!context.PUBLIC_SUPABASE_ANON_KEY)
throw new Error('PUBLIC_SUPABASE_ANON_KEY is required')
throw new Error("PUBLIC_SUPABASE_ANON_KEY is required");

return {
env: {
SUPABASE_URL: context.SUPABASE_URL,
PUBLIC_SUPABASE_ANON_KEY: context.PUBLIC_SUPABASE_ANON_KEY,
},
}
}
};
};

export default function App() {
const { env } = useLoaderData<Window>();
Expand All @@ -42,12 +49,11 @@ export default function App() {
</head>
<body>
<Outlet />
<DarkModeToggle />
<ScrollRestoration />
<script
dangerouslySetInnerHTML={{
__html: `window.env = ${JSON.stringify(
env,
)}`,
__html: `window.env = ${JSON.stringify(env)}`,
}}
/>
<Scripts />
Expand Down
45 changes: 45 additions & 0 deletions app/routes/__auth/auth.callback.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { useEffect } from "react";
import { useSearchParams, useSubmit } from "@remix-run/react";
import { supabase } from "~/supabase.client";
import type { ActionFunction } from "@remix-run/cloudflare";
import { getAuth } from "~/auth.server";
import { Loading, Typography } from "@supabase/ui";

export const action: ActionFunction = async ({ request, context }) => {
const data = await request.clone().formData()
const redirectTo = data.get('redirectTo')?.toString() ?? '/'
await getAuth(context).authenticator.authenticate('sb-auth', request, {
successRedirect: redirectTo,
failureRedirect: '/signin'
})
}

const AuthCallBack = () => {
const submit = useSubmit()
const [searchParams] = useSearchParams();
const redirectTo = searchParams.get("redirectTo");

useEffect(() => {
const { data: authListner } = supabase().auth.onAuthStateChange((event, session) => {
if (event === 'SIGNED_IN') {
const formData = new FormData()
formData.append('session', JSON.stringify(session))
if (redirectTo) formData.append('redirectTo', redirectTo)
submit(formData, { method: 'post' })
}
})

return () => {
authListner?.unsubscribe()
}

}, [submit, redirectTo])

return (
<div className="auth-container">
<Loading active><Typography.Text>Authenticating</Typography.Text></Loading>
</div>
)
}

export default AuthCallBack;
14 changes: 0 additions & 14 deletions app/routes/__auth/auth.css

This file was deleted.

25 changes: 25 additions & 0 deletions app/routes/__auth/logout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { ActionFunction, LoaderFunction } from "@remix-run/cloudflare"
import { Form } from "@remix-run/react"
import { Button } from "@supabase/ui"
import { getSession, getAuth } from "~/auth.server"

export const action: ActionFunction = async ({ request, context }) => {
await getAuth(context).authenticator.logout(request, { redirectTo: '/signin' })
}

export const loader:LoaderFunction = async ({ request, context }) => {
await getSession(context, request, false)
return {}
}

const Logout = () => {
return (
<>
<Form method="post">
<Button className="btn-poo">logout</Button>
</Form>
</>
)
}

export default Logout
29 changes: 15 additions & 14 deletions app/routes/__auth/signin.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,35 @@
import { useState, useEffect } from "react";
import { Auth } from "@supabase/ui";
import { supabase } from "~/supabase.client";
import styles from "~/routes/__auth/auth.css"
import type { LoaderFunction } from "@remix-run/cloudflare";
import { useLoaderData, useSearchParams } from "@remix-run/react";

export const links = () => {
// using tailwind only in signin with supabase
return [
{
rel: "stylesheet",
href: "https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css",
},
{
rel: "stylesheet",
href: styles
}
];
export const loader: LoaderFunction = ({ context }) => {
if (!context.SERVER_URL) throw new Error("SEVER_URL is required");

return {
server_url: context.SERVER_URL,
};
};

const Index = () => {
const [isClient, setIsclient] = useState(false);
useEffect(() => setIsclient(true), []);
const { server_url } = useLoaderData();
const [searchParams] = useSearchParams();
const redirectTo = searchParams.get("redirectTo");

if (isClient) {
return (
<Auth
className="dark auth-box"
className="auth-container"
providers={["google"]}
supabaseClient={supabase()}
magicLink={true}
view={"magic_link"}
redirectTo={`${server_url}/auth/callback${
redirectTo ? "?redirectTo=" + redirectTo : ""
}`}
/>
);
}
Expand Down
Loading

0 comments on commit 767087c

Please sign in to comment.