title: don't re-render when updating post

This commit is contained in:
Max Leiter 2022-11-17 23:39:52 -08:00
parent 8fe7299258
commit 881e693e76
18 changed files with 79 additions and 70 deletions

View file

@ -59,14 +59,10 @@
margin: 0;
}
.cardContent {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: var(--gap-half);
padding-top: 200px;
.chevron {
transition: transform 0.2s ease-in-out;
}
@media screen and (max-width: 82rem) {
[data-state="open"] .chevron {
transform: rotate(180deg);
}

View file

@ -49,8 +49,11 @@ const FileDropdown = ({ files }: { files: File[] }) => {
return (
<Popover>
<Popover.Trigger className={clsx(buttonStyles.button)}>
<div className={buttonStyles.icon}>
<Popover.Trigger className={buttonStyles.button}>
<div
className={clsx(buttonStyles.icon, styles.chevron)}
style={{ marginRight: 6 }}
>
<ChevronDown />
</div>
<span>

View file

@ -1,11 +1,11 @@
"use client"
import { Note, Text } from "@geist-ui/core/dist"
import Note from "@components/note"
export default function ExpiredPage() {
return (
<Note type="error" label={false}>
<h2>Error: The Drift you&apos;re trying to view has expired.</h2>
<Note type="error">
<strong>Error:</strong> The Drift you&apos;re trying to view has expired.
</Note>
)
}

View file

@ -23,4 +23,4 @@ const Description = ({ onChange, description }: props) => {
)
}
export default memo(Description)
export default Description

View file

@ -6,9 +6,17 @@
.actionWrapper .actions {
position: absolute;
right: 0;
top: 4px;
top: -34px;
}
/* small screens, top: 0 */
@media (max-width: 767px) {
.actionWrapper .actions {
top: 0;
}
}
@media (max-width: 768px) {
.actionWrapper .actions {
position: relative;

View file

@ -41,4 +41,4 @@ const DocumentList = ({
)
}
export default memo(DocumentList)
export default DocumentList

View file

@ -164,13 +164,18 @@ const Post = ({
const onChangeExpiration = (date: Date) => setExpiresAt(date)
const onChangeTitle = (e: ChangeEvent<HTMLInputElement>) => {
const onChangeTitle = useCallback((e: ChangeEvent<HTMLInputElement>) => {
e.preventDefault()
setTitle(e.target.value)
}
}, [])
const onChangeDescription = (e: ChangeEvent<HTMLInputElement>) => {
setDescription(e.target.value)
}
const onChangeDescription = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
e.preventDefault()
setDescription(e.target.value)
},
[]
)
const updateDocTitle = (i: number) => (title: string) => {
setDocs((docs) =>

View file

@ -1,4 +1,4 @@
import type { ChangeEvent } from "react"
import { ChangeEvent, memo } from "react"
import Input from "@components/input"
import styles from "./title.module.css"
@ -37,4 +37,4 @@ const Title = ({ onChange, title }: props) => {
)
}
export default Title
export default memo(Title)

View file

@ -37,6 +37,7 @@
.actionWrapper {
position: relative;
z-index: 1;
padding-top: 4px;
}
.actionWrapper .actions {

View file

@ -1,5 +1,5 @@
import PostPage from "app/(posts)/post/[id]/components/post-page"
import { notFound } from "next/navigation"
import { notFound, redirect } from "next/navigation"
import { getPostById, Post } from "@lib/server/prisma"
import { getCurrentUser } from "@lib/server/session"
@ -57,7 +57,7 @@ const getPost = async (id: string) => {
if (post.expiresAt && !isAuthorOrAdmin) {
const expirationDate = new Date(post.expiresAt)
if (expirationDate < new Date()) {
return notFound()
return redirect("/expired")
}
}

View file

@ -1,17 +0,0 @@
import { Page } from "@geist-ui/core/dist"
const Error = ({ status }: { status: number }) => {
return (
<Page title={status.toString() || "Error"}>
{status === 404 ? (
<h1>This page cannot be found.</h1>
) : (
<section>
<p>An error occurred: {status}</p>
</section>
)}
</Page>
)
}
export default Error

View file

@ -9,7 +9,6 @@ const Note = ({
children: React.ReactNode
} & React.ComponentProps<"div">) => (
<div className={`${styles.note} ${styles[type]}`} {...props}>
<strong className={styles.type}>{type}:</strong>
{children}
</div>
)

View file

@ -1,5 +1,4 @@
.note {
font-size: 0.8em;
color: var(--fg);
margin: 0;
padding: var(--gap);
@ -20,8 +19,14 @@
background: #f33;
}
[data-theme="light"] .warning,
[data-theme="light"] .error {
color: var(--bg);
}
.type {
color: var(--fg);
margin-right: 0.5em;
font-size: initial;
text-transform: capitalize;
}

View file

@ -1,6 +1,6 @@
import Card from "@components/card"
import * as RadixTooltip from "@radix-ui/react-tooltip"
import "./tooltip.css"
import styles from "./tooltip.module.css"
const Tooltip = ({
children,
@ -17,9 +17,8 @@ const Tooltip = ({
<RadixTooltip.Trigger asChild className={className}>
{children}
</RadixTooltip.Trigger>
<RadixTooltip.Content>
<Card className="tooltip">{content}</Card>
<Card className={styles.tooltip}>{content}</Card>
</RadixTooltip.Content>
</RadixTooltip.Root>
)

View file

@ -1,10 +0,0 @@
.tooltip {
/* animate */
animation: fadein 300ms;
}
@keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}

View file

@ -0,0 +1,24 @@
.tooltip {
animation: fadein 300ms;
}
[data-side='top'] .tooltip{
margin-bottom: var(--gap);
}
.tooltip[data-side='bottom'] {
margin-top: var(--gap);
}
.tooltip[data-side='left'] {
margin-right: var(--gap);
}
.tooltip[data-side='right'] {
margin-left: var(--gap);
}
@keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}

View file

@ -1,6 +1,9 @@
"use client"
import { Note, Input, Textarea, Button, useToasts } from "@geist-ui/core/dist"
import Button from "@components/button"
import Input from "@components/input"
import Note from "@components/note"
import { useToasts } from "@geist-ui/core/dist"
import { User } from "next-auth"
import { useState } from "react"
@ -57,7 +60,7 @@ const Profile = ({ user }: { user: User }) => {
return (
<>
<Note type="warning" marginBottom={"var(--gap)"}>
<Note type="warning">
This information will be publicly available on your profile
</Note>
<form
@ -83,7 +86,7 @@ const Profile = ({ user }: { user: User }) => {
<label htmlFor="email">Email</label>
<Input
id="email"
htmlType="email"
type="email"
width={"100%"}
placeholder="my@email.io"
value={user.email || undefined}
@ -92,12 +95,12 @@ const Profile = ({ user }: { user: User }) => {
</div>
<div>
<label htmlFor="bio">Biography (max 250 characters)</label>
<Textarea
<textarea
id="bio"
width="100%"
style={{ width: "100%" }}
maxLength={250}
placeholder="I enjoy..."
value={bio || ""}
value={bio}
onChange={handleBioChange}
/>
</div>

View file

@ -179,10 +179,3 @@ textarea {
padding: var(--gap-half);
border-radius: var(--radius);
}
textarea:focus {
outline: none;
border-color: var(--fg);
}