Skip to content

Commit

Permalink
Merge pull request #160 from denoland/change-display-name
Browse files Browse the repository at this point in the history
feat: change display name
  • Loading branch information
iuioiua authored May 4, 2023
2 parents 61bd428 + 0e08435 commit 92fe2b4
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 34 deletions.
70 changes: 36 additions & 34 deletions fresh.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,24 @@ import * as $0 from "./routes/_404.tsx";
import * as $1 from "./routes/_500.tsx";
import * as $2 from "./routes/_middleware.ts";
import * as $3 from "./routes/account/_middleware.ts";
import * as $4 from "./routes/account/index.tsx";
import * as $5 from "./routes/account/manage.ts";
import * as $6 from "./routes/account/reset-password.tsx";
import * as $7 from "./routes/account/upgrade.ts";
import * as $8 from "./routes/api/stripe-webhooks.ts";
import * as $9 from "./routes/blog/[slug].tsx";
import * as $10 from "./routes/blog/index.tsx";
import * as $11 from "./routes/feed.ts";
import * as $12 from "./routes/forgot-password.tsx";
import * as $13 from "./routes/index.tsx";
import * as $14 from "./routes/item/[id].tsx";
import * as $15 from "./routes/login/index.tsx";
import * as $16 from "./routes/login/oauth.ts";
import * as $17 from "./routes/login/success.tsx";
import * as $18 from "./routes/logout.ts";
import * as $19 from "./routes/signup.tsx";
import * as $20 from "./routes/submit.tsx";
import * as $4 from "./routes/account/display-name.tsx";
import * as $5 from "./routes/account/index.tsx";
import * as $6 from "./routes/account/manage.ts";
import * as $7 from "./routes/account/reset-password.tsx";
import * as $8 from "./routes/account/upgrade.ts";
import * as $9 from "./routes/api/stripe-webhooks.ts";
import * as $10 from "./routes/blog/[slug].tsx";
import * as $11 from "./routes/blog/index.tsx";
import * as $12 from "./routes/feed.ts";
import * as $13 from "./routes/forgot-password.tsx";
import * as $14 from "./routes/index.tsx";
import * as $15 from "./routes/item/[id].tsx";
import * as $16 from "./routes/login/index.tsx";
import * as $17 from "./routes/login/oauth.ts";
import * as $18 from "./routes/login/success.tsx";
import * as $19 from "./routes/logout.ts";
import * as $20 from "./routes/signup.tsx";
import * as $21 from "./routes/submit.tsx";
import * as $$0 from "./islands/AuthFragmentCatcher.tsx";

const manifest = {
Expand All @@ -32,23 +33,24 @@ const manifest = {
"./routes/_500.tsx": $1,
"./routes/_middleware.ts": $2,
"./routes/account/_middleware.ts": $3,
"./routes/account/index.tsx": $4,
"./routes/account/manage.ts": $5,
"./routes/account/reset-password.tsx": $6,
"./routes/account/upgrade.ts": $7,
"./routes/api/stripe-webhooks.ts": $8,
"./routes/blog/[slug].tsx": $9,
"./routes/blog/index.tsx": $10,
"./routes/feed.ts": $11,
"./routes/forgot-password.tsx": $12,
"./routes/index.tsx": $13,
"./routes/item/[id].tsx": $14,
"./routes/login/index.tsx": $15,
"./routes/login/oauth.ts": $16,
"./routes/login/success.tsx": $17,
"./routes/logout.ts": $18,
"./routes/signup.tsx": $19,
"./routes/submit.tsx": $20,
"./routes/account/display-name.tsx": $4,
"./routes/account/index.tsx": $5,
"./routes/account/manage.ts": $6,
"./routes/account/reset-password.tsx": $7,
"./routes/account/upgrade.ts": $8,
"./routes/api/stripe-webhooks.ts": $9,
"./routes/blog/[slug].tsx": $10,
"./routes/blog/index.tsx": $11,
"./routes/feed.ts": $12,
"./routes/forgot-password.tsx": $13,
"./routes/index.tsx": $14,
"./routes/item/[id].tsx": $15,
"./routes/login/index.tsx": $16,
"./routes/login/oauth.ts": $17,
"./routes/login/success.tsx": $18,
"./routes/logout.ts": $19,
"./routes/signup.tsx": $20,
"./routes/submit.tsx": $21,
},
islands: {
"./islands/AuthFragmentCatcher.tsx": $$0,
Expand Down
96 changes: 96 additions & 0 deletions routes/account/display-name.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2023 the Deno authors. All rights reserved. MIT license.
import type { Handlers, PageProps } from "$fresh/server.ts";
import Logo from "@/components/Logo.tsx";
import Head from "@/components/Head.tsx";
import {
BUTTON_STYLES,
INPUT_STYLES,
NOTICE_STYLES,
} from "@/utils/constants.ts";
import {
getOrCreateUser,
getUserDisplayName,
setUserDisplayName,
type User,
} from "@/utils/db.ts";
import type { AccountState } from "./_middleware.ts";

interface DisplayNamePageData {
user: User;
}

export const handler: Handlers<DisplayNamePageData, AccountState> = {
async GET(_req, ctx) {
const user = await getOrCreateUser(
ctx.state.session.user.id,
ctx.state.session.user.email!,
);
return ctx.render({ user });
},
async POST(req, ctx) {
try {
const form = await req.formData();
const displayName = form.get("display_name");

if (typeof displayName !== "string") {
throw new Error("Display name must be a string");
}

await setUserDisplayName(ctx.state.session.user.id, displayName);
return new Response(null, {
headers: { location: "/account" },
status: 307,
});
} catch (error) {
return new Response(null, {
headers: {
location: `/account/display-name?error=${
encodeURIComponent(error.message)
}`,
},
status: 307,
});
}
},
};

const POSSIBLE_ERROR_MESSAGES = [
"Display name must be a string",
"User does not exist",
];

export default function DisplayNamePage(props: PageProps<DisplayNamePageData>) {
const errorMessage = props.url.searchParams.get("error");

return (
<>
<Head title="Change display name" />
<div class="max-w-xs flex h-screen m-auto">
<div class="m-auto w-72">
<a href="/">
<Logo class="mb-8" />
</a>
<h1 class="text-center my-8 text-2xl font-bold">
Change display name
</h1>
{errorMessage && POSSIBLE_ERROR_MESSAGES.includes(errorMessage) && (
<div class={NOTICE_STYLES}>{errorMessage}</div>
)}
<form method="POST" class="space-y-4">
<input
type="text"
value={getUserDisplayName(props.data.user)}
placeholder="Display name"
name="display_name"
required
class={INPUT_STYLES}
/>
<button type="submit" class={`${BUTTON_STYLES} w-full`}>
Update
</button>
</form>
</div>
</div>
</>
);
}
3 changes: 3 additions & 0 deletions routes/account/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export default function AccountPage(props: PageProps<AccountPageData>) {
<p>
{getUserDisplayName(props.data.user)}
</p>
<p>
<a href="/account/display-name" class="underline">Edit</a>
</p>
</li>
<li class="py-4">
<p>
Expand Down
15 changes: 15 additions & 0 deletions utils/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,18 @@ export async function getOrCreateUser(id: string, email: string) {
export function getUserDisplayName(user: User) {
return user.displayName || user.id;
}

export async function setUserDisplayName(
userId: User["id"],
displayName: User["displayName"],
) {
const userKey = ["users", userId];
const userRes = await kv.get<User>(userKey);

if (!userRes.versionstamp) throw new Error("User does not exist");

await kv.atomic()
.check(userRes)
.set(userKey, { ...userRes.value, displayName })
.commit();
}

0 comments on commit 92fe2b4

Please sign in to comment.