A simple Admin page to manage user list in Remix & MYSQL

In the earlier tutorial, you learn to do authentication in Remix & MYSQL database. A visitor is able to create a new user account with profile photo and login to the remix app.

Now we continue the tutorial by creating a simple admin page to manage user list. An authorized user will be able to see the user list, update an existing user, and remove the user from the database. 

In the user folder, create index.jsx file. The index.js file is the admin page. It lists all registered users and has buttons to edit and delete a specific user. 

import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { redirect } from "@remix-run/node";
import {db} from "../../utils/db";
import {getUserId} from "../../utils/session";

export const loader = async ({request}) => {
    const uid=await getUserId(request);
    if(!uid) return redirect('user/login');
    try{
    let users={};
    users = await db.users.findMany();
    return json({users});

    }catch(err){
        console.error(err);
        return {};
    }
};

export const meta = () => {
    const title = 'user list';
    const description = 'Here is my User List page! You can update and delete user';
  
    return {
      charset: 'utf-8',
      title,
      description,
      keywords: 'Remix,Mysql,user list, update, delete',
      
    };
  };
export default function Index() {
 const {users} = useLoaderData();

 return (
    <div className="overflow-x-auto w-full">
    <table className="table w-full">
    <thead>
            <tr>
                <th>
                    ID
                </th>
                <th>
                    First Name
                </th>
                <th>
                    Last Name
                </th>
                <th>
                    User Name
                </th>
                <th>
                    Email
                </th>
                <th>Photo</th>
                <th>
                    Actions
                </th>
            </tr>
        </thead>    
        <tbody>
    {
        users && users.map(user =>{

            return(
                <tr key={user.id}>
                <th>{user.id}</th>
                <td>{user.firstName}</td>
                <td>{user.lastName}</td>
                <td>{user.username}</td>
                <td>{user.email}</td>
                <td><img width="50px" height="50px" src={`/uploads/${user.photo}`}/></td>
                <td>
                <div className="btn-group btn-group-vertical lg:btn-group-horizontal">
                <a href={`user/${user.id}`} className="btn">EDIT</a>
                <a href={`user/delconfirm?uid=${user.id}`}  className="btn">DELETE</a>
                </div>
                </td>
                </tr>
            );
        })
    }
    </tbody>
   </table>

  </div>
 );
}



Create $userid.jsx file, delconfirm.jsx, and delete.jsx files.  A page begins with $ is a dynamic route in Remix. The route user/$userid can match user/1, user/abc, etc. In this tutorial, the route user/$userid is to update user with a specific id. The delconfirm page simply displays a page to confirm user deletion. From the delconfirm page, if Delete link is clicked, it redirects to the delete page. In the delete page, the action to delete the user will be performed.

user/$userid.jsx
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { redirect } from "@remix-run/node";
import {db} from "../../utils/db";
import {getUserId} from "../../utils/session";

export const loader = async ({request}) => {
    const uid=await getUserId(request);
    if(!uid) return redirect('user/login');
    try{
    let users={};
    users = await db.users.findMany();
    return json({users});

    }catch(err){
        console.error(err);
        return {};
    }
};

export const meta = () => {
    const title = 'user list';
    const description = 'Here is my User List page! You can update and delete user';
  
    return {
      charset: 'utf-8',
      title,
      description,
      keywords: 'Remix,Mysql,user list, update, delete',
      
    };
  };
export default function Index() {
 const {users} = useLoaderData();

 return (
    <div className="overflow-x-auto w-full">
    <table className="table w-full">
    <thead>
            <tr>
                <th>
                    ID
                </th>
                <th>
                    First Name
                </th>
                <th>
                    Last Name
                </th>
                <th>
                    User Name
                </th>
                <th>
                    Email
                </th>
                <th>Photo</th>
                <th>
                    Actions
                </th>
            </tr>
        </thead>    
        <tbody>
    {
        users && users.map(user =>{

            return(
                <tr key={user.id}>
                <th>{user.id}</th>
                <td>{user.firstName}</td>
                <td>{user.lastName}</td>
                <td>{user.username}</td>
                <td>{user.email}</td>
                <td><img width="50px" height="50px" src={`/uploads/${user.photo}`}/></td>
                <td>
                <div className="btn-group btn-group-vertical lg:btn-group-horizontal">
                <a href={`user/${user.id}`} className="btn">EDIT</a>
                <a href={`user/delconfirm?uid=${user.id}`}  className="btn">DELETE</a>
                </div>
                </td>
                </tr>
            );
        })
    }
    </tbody>
   </table>

  </div>
 );
}

user/delconfirm.jsx
import { redirect } from "@remix-run/node";

import { 
  useLoaderData, 
} from "@remix-run/react";
export const loader = async ({request}) => {
  try {
    const url = new URL(request.url);
    const search = new URLSearchParams(url.search);
    const userid = search.get("uid");
    
    return {userid};

   } catch (err) {
    console.error(err);
    redirect("/user");
    return {};
   }
};

export default function DeleteUser() {
  const {userid}=useLoaderData();
  return (
    <div className="grid h-screen place-items-center">
      <div className="shadow">
       Are you sure to delet the user?<a className="text-red-200" href={`delete?uid=${userid}`}>Delete</a>
      </div>
    </div>
  )
}

user/delete.jsx
import { redirect } from "@remix-run/node";
import {db} from "../../utils/db";
import {getUserId} from "../../utils/session";
export const loader = async ({request}) => {
  const uid=await getUserId(request);
  if(!uid) return redirect('user/login');
  
  try {
    const url = new URL(request.url);
    const search = new URLSearchParams(url.search);
    const userid = search.get("uid");

    await db.users.delete({
      where:{
        id:parseInt(userid)
      }
    });

   return redirect('/user');

   } catch (err) {
    console.error(err);
    redirect("/user");
    return {};
   }
};

Save the Remix project. Then try to update and delete a user.


Congratulation! You completely have developed a full stack website using Remix and MYSQL.

Comments

Popular posts from this blog

Authentication: Register & Login Upload form data with file in Remix & Mysql

Style Remix app with Tailwind CSS