Added theme switcher
This commit is contained in:
parent
c102d1047f
commit
ddd9c74988
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
24
app/root.tsx
24
app/root.tsx
|
@ -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" />
|
||||
|
|
|
@ -157,8 +157,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
|
|||
},
|
||||
});
|
||||
|
||||
console.log(feed);
|
||||
|
||||
return feed;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
import { createCookie } from "@remix-run/node";
|
||||
|
||||
export const theme = createCookie("theme");
|
|
@ -3,8 +3,7 @@ import { createCookieSessionStorage } from "@remix-run/node";
|
|||
export const { getSession, commitSession, destroySession } =
|
||||
createCookieSessionStorage({
|
||||
cookie: {
|
||||
name: "__session",
|
||||
path: "/",
|
||||
sameSite: "lax",
|
||||
sameSite: "strict",
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue