mirror of
https://github.com/documenso/documenso.git
synced 2025-11-13 16:23:06 +10:00
saving ux minus refactor
This commit is contained in:
@ -78,14 +78,21 @@ type UserType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function TopNavigation() {
|
export default function TopNavigation() {
|
||||||
const [user, setUser] = useState<UserType>();
|
const router = useRouter();
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
|
const [user, setUser] = useState({
|
||||||
|
email: "",
|
||||||
|
name: "",
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setUser(session.data?.user);
|
fetch("/api/users/me").then((res) => {
|
||||||
}, [session]);
|
res.json().then((j) => {
|
||||||
|
setUser(j);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, [session, user]);
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
navigation.forEach((element) => {
|
navigation.forEach((element) => {
|
||||||
element.current = router.route.endsWith("/" + element.href.split("/")[1]);
|
element.current = router.route.endsWith("/" + element.href.split("/")[1]);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Fragment, useState } from "react";
|
import { ChangeEvent, Fragment, useEffect, useState } from "react";
|
||||||
import { Disclosure, Menu, Switch, Transition } from "@headlessui/react";
|
import { Disclosure, Menu, Switch, Transition } from "@headlessui/react";
|
||||||
import { MagnifyingGlassIcon } from "@heroicons/react/20/solid";
|
import { MagnifyingGlassIcon } from "@heroicons/react/20/solid";
|
||||||
import {
|
import {
|
||||||
@ -19,6 +19,7 @@ import avatarFromInitials from "avatar-from-initials";
|
|||||||
import { useSession } from "next-auth/react";
|
import { useSession } from "next-auth/react";
|
||||||
import { User } from "next-auth";
|
import { User } from "next-auth";
|
||||||
import { Value } from "sass";
|
import { Value } from "sass";
|
||||||
|
import { updateUser } from "@documenso/features";
|
||||||
|
|
||||||
const subNavigation = [
|
const subNavigation = [
|
||||||
{
|
{
|
||||||
@ -41,13 +42,44 @@ function classNames(...classes: any) {
|
|||||||
|
|
||||||
export default function Setttings() {
|
export default function Setttings() {
|
||||||
const session = useSession();
|
const session = useSession();
|
||||||
let user = session.data?.user;
|
const [user, setUser] = useState({
|
||||||
|
email: "",
|
||||||
|
name: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetch("/api/users/me").then((res) => {
|
||||||
|
res.json().then((j) => {
|
||||||
|
setUser(j);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, [session]);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
subNavigation.forEach((element) => {
|
subNavigation.forEach((element) => {
|
||||||
element.current = element.href == router.route;
|
element.current = element.href == router.route;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [savingTimeout, setSavingTimeout] = useState<any>();
|
||||||
|
function handleNameChange(e: ChangeEvent<HTMLInputElement>): void {
|
||||||
|
let u = { ...user };
|
||||||
|
u.name = e.target.value;
|
||||||
|
setUser(u);
|
||||||
|
clearTimeout(savingTimeout);
|
||||||
|
const t = setTimeout(() => {
|
||||||
|
updateUser(u);
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
setSavingTimeout(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleKeyPress = (event: any) => {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
clearTimeout(savingTimeout);
|
||||||
|
updateUser(user);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Head>
|
<Head>
|
||||||
@ -60,7 +92,10 @@ export default function Setttings() {
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
<div className="mx-auto max-w-screen-xl px-4 pb-6 sm:px-6 lg:px-8 lg:pb-16">
|
<div
|
||||||
|
className="mx-auto max-w-screen-xl px-4 pb-6 sm:px-6 lg:px-8 lg:pb-16"
|
||||||
|
hidden={!user.email}
|
||||||
|
>
|
||||||
<div className="overflow-hidden rounded-lg bg-white shadow">
|
<div className="overflow-hidden rounded-lg bg-white shadow">
|
||||||
<div className="divide-y divide-gray-200 lg:grid lg:grid-cols-12 lg:divide-y-0 lg:divide-x">
|
<div className="divide-y divide-gray-200 lg:grid lg:grid-cols-12 lg:divide-y-0 lg:divide-x">
|
||||||
<aside className="py-6 lg:col-span-3">
|
<aside className="py-6 lg:col-span-3">
|
||||||
@ -121,7 +156,8 @@ export default function Setttings() {
|
|||||||
name="first-name"
|
name="first-name"
|
||||||
id="first-name"
|
id="first-name"
|
||||||
value={user?.name || ""}
|
value={user?.name || ""}
|
||||||
onChange={() => {}}
|
onChange={(e) => handleNameChange(e)}
|
||||||
|
onKeyDown={handleKeyPress}
|
||||||
autoComplete="given-name"
|
autoComplete="given-name"
|
||||||
className="mt-1 block w-full rounded-md border border-gray-300 py-2 px-3 shadow-sm focus:border-neon focus:outline-none focus:ring-neon sm:text-sm"
|
className="mt-1 block w-full rounded-md border border-gray-300 py-2 px-3 shadow-sm focus:border-neon focus:outline-none focus:ring-neon sm:text-sm"
|
||||||
/>
|
/>
|
||||||
@ -143,6 +179,13 @@ export default function Setttings() {
|
|||||||
className="mt-1 block w-full rounded-md border border-gray-300 py-2 px-3 shadow-sm focus:border-neon focus:outline-none focus:ring-neon sm:text-sm"
|
className="mt-1 block w-full rounded-md border border-gray-300 py-2 px-3 shadow-sm focus:border-neon focus:outline-none focus:ring-neon sm:text-sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => updateUser(user)}
|
||||||
|
className="inline-flex items-center justify-center rounded-md border border-transparent bg-neon px-10 py-2 text-sm font-medium text-white shadow-sm hover:bg-neon-dark focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 sm:w-auto"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
28
apps/web/pages/api/users/me.ts
Normal file
28
apps/web/pages/api/users/me.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import {
|
||||||
|
defaultHandler,
|
||||||
|
defaultResponder,
|
||||||
|
getUserFromToken,
|
||||||
|
} from "@documenso/lib/server";
|
||||||
|
import prisma from "@documenso/prisma";
|
||||||
|
|
||||||
|
import type { NextApiRequest, NextApiResponse } from "next";
|
||||||
|
|
||||||
|
async function getHandler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
|
const user = await getUserFromToken(req, res);
|
||||||
|
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
|
return prisma.user.findFirstOrThrow({
|
||||||
|
where: {
|
||||||
|
id: user.id,
|
||||||
|
},
|
||||||
|
select: {
|
||||||
|
email: true,
|
||||||
|
name: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defaultHandler({
|
||||||
|
GET: Promise.resolve({ default: defaultResponder(getHandler) }),
|
||||||
|
});
|
||||||
@ -2,7 +2,8 @@ import toast from "react-hot-toast";
|
|||||||
|
|
||||||
export const updateUser = async (user: any) => {
|
export const updateUser = async (user: any) => {
|
||||||
if (!user) return;
|
if (!user) return;
|
||||||
toast.promise(
|
toast
|
||||||
|
.promise(
|
||||||
fetch("/api/users", {
|
fetch("/api/users", {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: {
|
headers: {
|
||||||
@ -15,5 +16,8 @@ export const updateUser = async (user: any) => {
|
|||||||
success: `Saved!`,
|
success: `Saved!`,
|
||||||
error: "Changes could not save user :/",
|
error: "Changes could not save user :/",
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
.then(() => {
|
||||||
|
// location.reload();
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user