title: don't re-render when updating post
This commit is contained in:
parent
8fe7299258
commit
881e693e76
18 changed files with 79 additions and 70 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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're trying to view has expired.</h2>
|
||||
<Note type="error">
|
||||
<strong>Error:</strong> The Drift you're trying to view has expired.
|
||||
</Note>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -23,4 +23,4 @@ const Description = ({ onChange, description }: props) => {
|
|||
)
|
||||
}
|
||||
|
||||
export default memo(Description)
|
||||
export default Description
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -41,4 +41,4 @@ const DocumentList = ({
|
|||
)
|
||||
}
|
||||
|
||||
export default memo(DocumentList)
|
||||
export default DocumentList
|
||||
|
|
|
@ -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) =>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
.actionWrapper {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding-top: 4px;
|
||||
}
|
||||
|
||||
.actionWrapper .actions {
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
|
||||
.tooltip {
|
||||
/* animate */
|
||||
animation: fadein 300ms;
|
||||
}
|
||||
|
||||
@keyframes fadein {
|
||||
from { opacity: 0; }
|
||||
to { opacity: 1; }
|
||||
}
|
24
client/app/components/tooltip/tooltip.module.css
Normal file
24
client/app/components/tooltip/tooltip.module.css
Normal 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; }
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -179,10 +179,3 @@ textarea {
|
|||
padding: var(--gap-half);
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--fg);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue