Added theme switcher

This commit is contained in:
Joonas 2023-11-14 22:08:37 +02:00
parent c102d1047f
commit ddd9c74988
8 changed files with 115 additions and 25 deletions

View File

@ -9,7 +9,7 @@ export function Card({
}) {
return (
<div
className={`flex z-10 flex-col bg-ctp-mantle gap-5 p-8 border w-full rounded-md ${className}`}
className={`flex z-10 flex-col bg-ctp-mantle/25 gap-5 p-8 border w-full rounded-md ${className}`}
>
{children}
</div>

View File

@ -20,7 +20,7 @@ export function Poster({
return (
<div className={`flex break-all items-center gap-3 ${className}`}>
<img
className="rounded-full border w-16"
className="rounded-full border w-12"
src={
pfp
? `
@ -66,7 +66,7 @@ export function Post({
return (
<div
key={post.id}
className="flex relative flex-col gap-4 p-6 transition-all bg-ctp-mantle hover:bg-ctp-base first:rounded-t-lg last:rounded-b-lg "
className="flex relative flex-col gap-4 p-6 transition-all bg-ctp-mantle/20 hover:bg-ctp-base first:rounded-t-lg last:rounded-b-lg "
>
{liker ? (
<Text type="subtitle">

View File

@ -23,6 +23,7 @@ import { SubTitle } from "./components/Typography";
import { Toast } from "./components/Toast";
import { prisma } from "./utils/prisma.server";
import { Poster } from "./components/Post";
import { theme } from "./utils/cookie.server";
export const links: LinksFunction = () => [{ rel: "stylesheet", href: styles }];
@ -32,12 +33,17 @@ export interface RootLoaderTypes {
name: string;
pfp: string;
toast: string;
theme: "latte" | "macchiato" | "mocha" | "frappe" | undefined;
}
export async function loader({ request }: LoaderFunctionArgs) {
const session = await getSession(request.headers.get("Cookie"));
const cookieHeader = request.headers.get("Cookie");
const session = await getSession(cookieHeader);
const message = session.get("globalMessage") || null;
if (session.has("userId")) {
const themeCookie = (await theme.parse(cookieHeader)) || {};
const data = await prisma.user.findUnique({
where: {
id: session.get("userId"),
@ -60,6 +66,7 @@ export async function loader({ request }: LoaderFunctionArgs) {
username: data.username,
name: data.name,
pfp: data.pfp,
theme: themeCookie.theme,
toast: message,
},
{
@ -86,7 +93,20 @@ export default function App() {
const data = useLoaderData<LoaderFunction>();
return (
<html className="ctp-mocha" lang="en">
<html
className={
data.theme === "latte"
? "ctp-latte"
: data.theme === "frappe"
? "ctp-frappe"
: data.theme === "macchiato"
? "ctp-macchiato"
: data.theme === "mocha"
? "ctp-mocha"
: ""
}
lang="en"
>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />

View File

@ -157,8 +157,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
},
});
console.log(feed);
return feed;
}

View File

@ -14,11 +14,15 @@ import { Card } from "~/components/Card";
import { FormInput, FormLabel } from "~/components/Form";
import { Title, Text } from "~/components/Typography";
import { editUser } from "~/models/user.server";
import { theme } from "~/utils/cookie.server";
import { profilePictureUploadHandler } from "~/utils/file.server";
import { commitSession, getSession } from "~/utils/session.server";
const themes = ["latte", "frappe", "macchiato", "mocha", "none"];
export async function action({ request }: ActionFunctionArgs) {
const session = await getSession(request.headers.get("Cookie"));
const cookieHeader = request.headers.get("Cookie");
const session = await getSession(cookieHeader);
if (!session.has("userId")) {
return redirect("/home");
}
@ -28,14 +32,46 @@ export async function action({ request }: ActionFunctionArgs) {
.formData()
.then((data) => Object.fromEntries(data));
if (formData.intent === "pfp") {
try {
formData = Object.fromEntries(
await unstable_parseMultipartFormData(req, profilePictureUploadHandler)
switch (formData.intent) {
case "pfp":
try {
formData = Object.fromEntries(
await unstable_parseMultipartFormData(
req,
profilePictureUploadHandler
)
);
} catch (e) {
console.log(e);
}
break;
case "theme":
if (!themes.includes(String(formData.theme))) {
return {
errors: {
theme: "Theme not found",
},
};
}
const themeCookie = (await theme.parse(cookieHeader)) || {};
themeCookie.theme = formData.theme;
return json(
{
success: {
theme: `Theme changed successfully!`,
},
},
{
headers: {
"Set-Cookie": await theme.serialize(themeCookie),
},
}
);
} catch (e) {
console.log(e);
}
default:
break;
}
const { username, errors } = await editUser(formData, session.get("userId"));
@ -51,9 +87,7 @@ export async function action({ request }: ActionFunctionArgs) {
return json(
{
success: {
[String(
formData.intent
)]: `Field ${formData.intent} changed successfully!`,
[String(formData.intent)]: `${formData.intent} changed successfully!`,
},
},
{
@ -203,9 +237,43 @@ export default function Settings() {
</Form>
</Card>
</details>
<Link to={`/logout`}>
<Text type="link">Sign out</Text>
</Link>
<details className="space-y-4">
<summary className="text-gray-600 cursor-pointer select-none">
<span className="text-ctp-text/75">Change theme</span>
</summary>
<Card>
<Form className="relative flex flex-col gap-3" method="POST">
<input type="hidden" name="intent" value="theme" />
<FormLabel>
<Text>Theme</Text>
<select
className="w-fit rounded-lg p-2 bg-ctp-crust border"
name="theme"
>
{themes.map((theme) => (
<option key={theme} className="capitalize" value={theme}>
{theme}
</option>
))}
</select>{" "}
<Text type="error">
{data?.errors?.theme ? data.errors.theme : ""}
</Text>
</FormLabel>
<Button type="submit">Submit</Button>
{data?.success?.theme ? (
<Text type="success">{data.success.theme}</Text>
) : (
""
)}
</Form>
</Card>
</details>
<div className="w-fit">
<Link to={`/logout`}>
<Text type="link">Sign out</Text>
</Link>
</div>
</div>
</div>
);

View File

@ -1,10 +1,12 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
*,
::before,
::after {
@apply dark:border-ctp-overlay0/75;
@apply dark:border-ctp-overlay0/50;
}
}
}

View File

@ -0,0 +1,3 @@
import { createCookie } from "@remix-run/node";
export const theme = createCookie("theme");

View File

@ -3,8 +3,7 @@ import { createCookieSessionStorage } from "@remix-run/node";
export const { getSession, commitSession, destroySession } =
createCookieSessionStorage({
cookie: {
name: "__session",
path: "/",
sameSite: "lax",
sameSite: "strict",
},
});