Built Twitter Like App - 19

Add Edit Function

  1. Add edit API
  2. Add EditModal
  3. Add Hook
  4. Add EditModal to App.ts

Add edit API

Add file pages/api/edit.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import { NextApiRequest, NextApiResponse } from 'next';
import prisma from '@/libs/prismadb';

export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if ( req.method !== 'PATCH'){
return res.status(405).end();
}

try{
const { name, username, bio, profileImage, coverImage,userId } = req.body;

console.log('user username:', name, username, bio )

if(!name || !username ){
throw new Error('Missing fields!');
}

const updatedUser = await prisma.user.update({
where: {
id: userId
},
data: {
name,
username,
bio,
profileImage,
coverImage
}
});

return res.status(200).json(updatedUser);
} catch (error){
console.log(error);
return res.status(400).end();
}
}

Add EditModal

Add file components/modals/EditModal.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import axios from "axios";
import { useCallback, useEffect, useState } from "react";
import toast from "react-hot-toast";

import useCurrentUser from "@/hooks/useCurrentUser"
import useEditModal from "@/hooks/useEditModal";
import useUser from "@/hooks/useUser";
import Input from "../Input";
import ModalBox from "../ModalBox";

const EditModal = () =>{
const { data: currentUser } = useCurrentUser();
const { mutate: mutateFetchedUser } = useUser(Number(currentUser?.id));
const editModal = useEditModal();

const [profileImage, setProfileImage] = useState('');
const [coverImage, setCoverImage] = useState('');
const [name, setName] = useState('');
const [username, setUsername] = useState('');
const [bio, setBio] = useState('');
const [userId, setUserId] = useState('');

useEffect(() =>{
setProfileImage(currentUser?.profileImage);
setCoverImage(currentUser?.coverImage);
setName(currentUser?.name);
setUsername(currentUser?.username);
setBio(currentUser?.bio);
setUserId(currentUser?.id);
},[currentUser]);

const [isLoading, setIsLoading] = useState(false);

const onSubmit = useCallback( async () =>{
try{
setIsLoading(true);

await axios.patch('/api/edit', {
name,
username,
bio,
profileImage,
coverImage,
userId
});
mutateFetchedUser();

toast.success('Updated');

editModal.onClose();
} catch(error) {
toast.error('Something went wrong')
} finally {
setIsLoading(false);
}
},[name,username,bio,profileImage,coverImage,userId,editModal,mutateFetchedUser])

const bodyContent = (
<div className="flex flex-col gap-4">
<Input
placeholder="Name"
onChange={(e)=> setName(e.target.value)}
value={ name }
disabled={isLoading}
/>
<Input
placeholder="Username"
onChange={(e)=> setUsername(e.target.value)}
value={ username }
disabled={isLoading}
/>
<Input
placeholder="Bio"
onChange={(e)=> setBio(e.target.value)}
value={ bio }
disabled={isLoading}
/>
</div>
);

return(
<ModalBox
disabled={isLoading}
isOpen={editModal.isOpen}
title="Edit your profile"
actionLabel="Save"
onClose={editModal.onClose}
onSubmit={onSubmit}
body={bodyContent}
/>
);
}

export default EditModal;

Add Hooks

Add file hooks/useEditModal.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { create } from "zustand";

interface EditModalStore{
isOpen: boolean;
onOpen: ()=> void;
onClose: ()=> void;
};

const useEditModal = create<EditModalStore>((set) =>({
isOpen: false,
onOpen: () => set({ isOpen: true}),
onClose: () => set({ isOpen: false})
}));

export default useEditModal;

Add EditModal to _App.tsx

Modify file pages/_app.tsx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import type { AppProps } from 'next/app';
import { Toaster } from 'react-hot-toast';
import { SessionProvider } from 'next-auth/react';

import Layout from '../components/Layout';
import LoginModal from '../components/modals/LoginModal';
import RegisterModal from '../components/modals/RegisterModal';
import EditModal from '@/components/modals/EditModal';
import '../styles/globals.css';

export default function App({ Component, pageProps }: AppProps) {
return (
<SessionProvider session={ pageProps.session }>
<Toaster />
<EditModal />
<RegisterModal />
<LoginModal />
<Layout>
<Component {...pageProps} />
</Layout>
</SessionProvider>
)
}

Bind EditModal to “Edit” Button

Modify file components/users/UserBio.tsx

1
2
3
4
5
6
7
...
import useEditModal from '@/hooks/useEditModal';
...
const editModal = useEditModal();
...
<Button secondary label='Edit' onClick={ editModal.onOpen } />
...

Demo

Edit Mode:

Click Edit Button:

Click Save Button:

请我喝杯咖啡吧~

支付宝
微信