Add AccountList skeleton
This commit is contained in:
@@ -20,6 +20,7 @@ export default function Modal(props: ModalProps){
|
|||||||
delete divProps["backgroundClassName"];
|
delete divProps["backgroundClassName"];
|
||||||
delete divProps["close"];
|
delete divProps["close"];
|
||||||
delete divProps["className"];
|
delete divProps["className"];
|
||||||
|
delete divProps["top"];
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
|
import DangerMessage from "@/components/message/DangerMessage";
|
||||||
|
import SuccessMessage from "@/components/message/SuccessMessage";
|
||||||
import Modal from "@/components/modal/Modal";
|
import Modal from "@/components/modal/Modal";
|
||||||
import ModalBody from "@/components/modal/ModalBody";
|
import ModalBody from "@/components/modal/ModalBody";
|
||||||
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
type TimedModalProviderState = {
|
type TimedModalProviderState = {
|
||||||
addMessage: (timeout: number, message: React.ReactNode) => void;
|
addMessage: (message: React.ReactNode, timeout: number) => void;
|
||||||
|
addSuccessMessage: (message: string) => void;
|
||||||
|
addErrorMessage: (message: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const initialState: TimedModalProviderState = {
|
const initialState: TimedModalProviderState = {
|
||||||
addMessage: () => null
|
addMessage: () => null,
|
||||||
|
addSuccessMessage: () => null,
|
||||||
|
addErrorMessage: () => null
|
||||||
}
|
}
|
||||||
|
|
||||||
const TimedModalProviderContext = createContext<TimedModalProviderState>(initialState);
|
const TimedModalProviderContext = createContext<TimedModalProviderState>(initialState);
|
||||||
@@ -27,8 +33,6 @@ export function TimedModalProvider({
|
|||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("effect");
|
|
||||||
console.log(messages);
|
|
||||||
if(messages.length > 0){
|
if(messages.length > 0){
|
||||||
setDisplay(true);
|
setDisplay(true);
|
||||||
}
|
}
|
||||||
@@ -38,16 +42,30 @@ export function TimedModalProvider({
|
|||||||
}, [ messages ]);
|
}, [ messages ]);
|
||||||
|
|
||||||
|
|
||||||
const addMessage = (timeout: number, message: React.ReactNode) => {
|
const addMessage = (message: React.ReactNode, timeout: number) => {
|
||||||
setMessages([...messages, message]);
|
setMessages([...messages, message]);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setMessages(messagesRef.current.filter((m) => m !== message));
|
setMessages(messagesRef.current.filter((m) => m !== message));
|
||||||
}, timeout);
|
}, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const addSuccessMessage = (message: string) => {
|
||||||
|
addMessage(<SuccessMessage>{message}</SuccessMessage>, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addErrorMessage = (message: string) => {
|
||||||
|
addMessage(<DangerMessage>{message}</DangerMessage>, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentContext = {
|
||||||
|
addMessage,
|
||||||
|
addSuccessMessage,
|
||||||
|
addErrorMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TimedModalProviderContext.Provider value={{addMessage}}>
|
<TimedModalProviderContext.Provider value={currentContext}>
|
||||||
<Modal
|
<Modal
|
||||||
display={display}
|
display={display}
|
||||||
backgroundType="none"
|
backgroundType="none"
|
||||||
|
|||||||
@@ -1,7 +1,91 @@
|
|||||||
|
import { ButtonShape, ButtonSizeType, ButtonVariant } from "@/components/button/Button";
|
||||||
|
import Table from "@/components/table/Table";
|
||||||
|
import { elementBg } from "@/util/SkeletonUtil";
|
||||||
|
import AccountAdminButtons from "./AccountAdminButtons";
|
||||||
|
|
||||||
|
|
||||||
export default function AccountsListSkeleton(){
|
export default function AccountsListSkeleton(){
|
||||||
return (
|
const headElements: React.ReactNode[] = [
|
||||||
<div>
|
<div>
|
||||||
Accounts List Skeleton
|
ID
|
||||||
|
</div>,
|
||||||
|
<div>
|
||||||
|
Username
|
||||||
|
</div>,
|
||||||
|
<div>
|
||||||
|
Email
|
||||||
|
</div>,
|
||||||
|
<div>
|
||||||
|
Login Date
|
||||||
|
</div>,
|
||||||
|
<div>
|
||||||
|
Status
|
||||||
|
</div>,
|
||||||
|
<div
|
||||||
|
className="pl-16"
|
||||||
|
>
|
||||||
|
Actions
|
||||||
</div>
|
</div>
|
||||||
|
];
|
||||||
|
const bodyElements: React.ReactNode[][] = [
|
||||||
|
AccountSkeleton(),
|
||||||
|
AccountSkeleton(),
|
||||||
|
AccountSkeleton(),
|
||||||
|
AccountSkeleton(),
|
||||||
|
AccountSkeleton(),
|
||||||
|
AccountSkeleton(),
|
||||||
|
AccountSkeleton(),
|
||||||
|
AccountSkeleton(),
|
||||||
|
AccountSkeleton(),
|
||||||
|
AccountSkeleton()
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
tableHeadElements={headElements}
|
||||||
|
tableBodyElements={bodyElements}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function AccountSkeleton(): React.ReactNode[]{
|
||||||
|
const buttonsProps = {
|
||||||
|
buttonProps: {
|
||||||
|
variant: "ghost" as ButtonVariant,
|
||||||
|
size: "md" as ButtonSizeType,
|
||||||
|
shape: "square" as ButtonShape,
|
||||||
|
disabled: true
|
||||||
|
},
|
||||||
|
showForcePasswordResetModal: () => {},
|
||||||
|
showAccountPasswordSetModal: () => {},
|
||||||
|
showRevokeRefreshTokenModal: () => {},
|
||||||
|
showUpdateAccountModal: () => {},
|
||||||
|
showDeleteAccountModal: () => {}
|
||||||
|
}
|
||||||
|
const elements: React.ReactNode[] = [
|
||||||
|
<div
|
||||||
|
className={`h-6 w-72 mr-1 ${elementBg}`}
|
||||||
|
/>,
|
||||||
|
<div
|
||||||
|
className={`h-6 w-48 ${elementBg}`}
|
||||||
|
/>,
|
||||||
|
<div
|
||||||
|
className={`h-6 w-80 ${elementBg}`}
|
||||||
|
/>,
|
||||||
|
<div
|
||||||
|
className={`h-6 w-64 ${elementBg}`}
|
||||||
|
/>,
|
||||||
|
<div
|
||||||
|
className={`h-6 w-28 ${elementBg}`}
|
||||||
|
/>,
|
||||||
|
<div
|
||||||
|
className={`flex flex-row items-center justify-center gap-2 pl-16`}
|
||||||
|
>
|
||||||
|
<div className="py-4 border-l border-neutral-500"> </div>
|
||||||
|
<AccountAdminButtons {...buttonsProps}/>
|
||||||
|
</div>
|
||||||
|
];
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import PrimaryButton from "@/components/button/PrimaryButton";
|
import PrimaryButton from "@/components/button/PrimaryButton";
|
||||||
|
import DangerMessage from "@/components/message/DangerMessage";
|
||||||
import { useGetAccounts } from "@/hooks/AccountHooks";
|
import { useGetAccounts } from "@/hooks/AccountHooks";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import AccountsList from "./AccountsList";
|
import AccountsList from "./AccountsList";
|
||||||
@@ -16,13 +17,12 @@ export default function AccountsLoader(){
|
|||||||
return <AccountsListSkeleton/>
|
return <AccountsListSkeleton/>
|
||||||
}
|
}
|
||||||
else if(accountsQuery.isError){
|
else if(accountsQuery.isError){
|
||||||
//TODO:
|
return <DangerMessage>Error: {accountsQuery.error.message}</DangerMessage>
|
||||||
return <div>Error: {accountsQuery.error.message}</div>
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* TODO: Add Account Button */}
|
{/* Add Account Button */}
|
||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
className="mb-8"
|
className="mb-8"
|
||||||
onClick={() => setDisplayCreateAccountModal(true)}
|
onClick={() => setDisplayCreateAccountModal(true)}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import TextInput from "@/components/input/TextInput";
|
|||||||
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
||||||
import { useCreateAccount, useUpdateAccount } from "@/hooks/AccountHooks";
|
import { useCreateAccount, useUpdateAccount } from "@/hooks/AccountHooks";
|
||||||
import { Account, AccountStatus } from "@/interface/Account";
|
import { Account, AccountStatus } from "@/interface/Account";
|
||||||
|
import { useTimedModal } from "@/providers/TimedModalProvider";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
@@ -35,17 +36,31 @@ export default function AccountModal({
|
|||||||
|
|
||||||
const updateAccountMutate = useUpdateAccount();
|
const updateAccountMutate = useUpdateAccount();
|
||||||
const createAccountMutate = useCreateAccount();
|
const createAccountMutate = useCreateAccount();
|
||||||
|
const { addSuccessMessage, addErrorMessage } = useTimedModal();
|
||||||
|
|
||||||
if((updateAccountMutate.isSuccess) || (createAccountMutate.isSuccess)){
|
|
||||||
updateAccountMutate.reset();
|
useEffect(() => {
|
||||||
|
if(createAccountMutate.isSuccess){
|
||||||
createAccountMutate.reset();
|
createAccountMutate.reset();
|
||||||
|
addSuccessMessage(`Account ${username} created successfully`);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
else if((updateAccountMutate.isError) || (updateAccountMutate.isError)){
|
else if(updateAccountMutate.isSuccess){
|
||||||
//TODO: Add message modal here
|
updateAccountMutate.reset();
|
||||||
console.log(updateAccountMutate.error);
|
addSuccessMessage(`Account ${username} updated successfully`);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
else if(createAccountMutate.isError){
|
||||||
|
createAccountMutate.reset();
|
||||||
|
addErrorMessage(`Error creating account ${username}: ${createAccountMutate.error.message}`);
|
||||||
console.log(createAccountMutate.error);
|
console.log(createAccountMutate.error);
|
||||||
}
|
}
|
||||||
|
else if(updateAccountMutate.isError){
|
||||||
|
updateAccountMutate.reset();
|
||||||
|
addErrorMessage(`Error updating account ${username}: ${updateAccountMutate.error.message}`);
|
||||||
|
console.log(updateAccountMutate.error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
const updateAccount = () => {
|
const updateAccount = () => {
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import PasswordInput from "@/components/input/PasswordInput";
|
|||||||
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
||||||
import { useResetPassword } from "@/hooks/AccountHooks";
|
import { useResetPassword } from "@/hooks/AccountHooks";
|
||||||
import { Account } from "@/interface/Account";
|
import { Account } from "@/interface/Account";
|
||||||
import { useState } from "react";
|
import { useTimedModal } from "@/providers/TimedModalProvider";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function AccountPasswordRestModal({
|
export default function AccountPasswordRestModal({
|
||||||
@@ -17,6 +18,7 @@ export default function AccountPasswordRestModal({
|
|||||||
account: Account | undefined;
|
account: Account | undefined;
|
||||||
}){
|
}){
|
||||||
const [ newPassword, setNewPassword ] = useState<string>("");
|
const [ newPassword, setNewPassword ] = useState<string>("");
|
||||||
|
const { addSuccessMessage, addErrorMessage } = useTimedModal();
|
||||||
|
|
||||||
|
|
||||||
const passwordResetMutate = useResetPassword(account?.accountId ?? "");
|
const passwordResetMutate = useResetPassword(account?.accountId ?? "");
|
||||||
@@ -27,14 +29,18 @@ export default function AccountPasswordRestModal({
|
|||||||
passwordResetMutate.mutate(newPassword);
|
passwordResetMutate.mutate(newPassword);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
if(passwordResetMutate.isSuccess){
|
if(passwordResetMutate.isSuccess){
|
||||||
passwordResetMutate.reset();
|
passwordResetMutate.reset();
|
||||||
|
addSuccessMessage(`Successfully reset password for ${account?.username}`);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
else if(passwordResetMutate.isError){
|
else if(passwordResetMutate.isError){
|
||||||
//TODO: Add message modal here
|
passwordResetMutate.reset();
|
||||||
|
addErrorMessage(`Failed to reset password for ${account?.username}: ${passwordResetMutate.error.message}`);
|
||||||
console.log(passwordResetMutate.error);
|
console.log(passwordResetMutate.error);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import SecondaryButton from "@/components/button/SecondaryButton";
|
|||||||
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
||||||
import { useDeleteAccount } from "@/hooks/AccountHooks";
|
import { useDeleteAccount } from "@/hooks/AccountHooks";
|
||||||
import { Account } from "@/interface/Account";
|
import { Account } from "@/interface/Account";
|
||||||
|
import { useTimedModal } from "@/providers/TimedModalProvider";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function DeleteAccountModal({
|
export default function DeleteAccountModal({
|
||||||
@@ -15,20 +17,26 @@ export default function DeleteAccountModal({
|
|||||||
account: Account | undefined;
|
account: Account | undefined;
|
||||||
}){
|
}){
|
||||||
const deleteAccountMutate = useDeleteAccount(account?.accountId ?? "");
|
const deleteAccountMutate = useDeleteAccount(account?.accountId ?? "");
|
||||||
|
const { addSuccessMessage, addErrorMessage } = useTimedModal();
|
||||||
|
|
||||||
|
|
||||||
const deleteAccount = () => {
|
const deleteAccount = () => {
|
||||||
deleteAccountMutate.mutate();
|
deleteAccountMutate.mutate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
if(deleteAccountMutate.isSuccess){
|
if(deleteAccountMutate.isSuccess){
|
||||||
deleteAccountMutate.reset();
|
deleteAccountMutate.reset();
|
||||||
|
addSuccessMessage(`Successfully deleted ${account?.username}`);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
else if(deleteAccountMutate.isError){
|
else if(deleteAccountMutate.isError){
|
||||||
//TODO: Add message modal here
|
deleteAccountMutate.reset();
|
||||||
|
addErrorMessage(`Error deleting ${account?.username}: ${deleteAccountMutate.error.message}`);
|
||||||
console.log(deleteAccountMutate.error);
|
console.log(deleteAccountMutate.error);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RaidBuilderModal
|
<RaidBuilderModal
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import SecondaryButton from "@/components/button/SecondaryButton";
|
|||||||
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
||||||
import { useForcePasswordReset } from "@/hooks/AccountHooks";
|
import { useForcePasswordReset } from "@/hooks/AccountHooks";
|
||||||
import { Account } from "@/interface/Account";
|
import { Account } from "@/interface/Account";
|
||||||
|
import { useTimedModal } from "@/providers/TimedModalProvider";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function ForcePasswordResetModal({
|
export default function ForcePasswordResetModal({
|
||||||
@@ -14,21 +16,26 @@ export default function ForcePasswordResetModal({
|
|||||||
close: () => void;
|
close: () => void;
|
||||||
account: Account | undefined;
|
account: Account | undefined;
|
||||||
}){
|
}){
|
||||||
const accountMutate = useForcePasswordReset(account?.accountId ?? "");
|
const forcePasswordResetMutate = useForcePasswordReset(account?.accountId ?? "");
|
||||||
|
const { addSuccessMessage, addErrorMessage } = useTimedModal();
|
||||||
|
|
||||||
|
|
||||||
const forcePasswordReset = () => {
|
const forcePasswordReset = () => {
|
||||||
accountMutate.mutate();
|
forcePasswordResetMutate.mutate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(accountMutate.isSuccess){
|
useEffect(() => {
|
||||||
accountMutate.reset();
|
if(forcePasswordResetMutate.isSuccess){
|
||||||
|
forcePasswordResetMutate.reset();
|
||||||
|
addSuccessMessage(`Successfully forced password reset for ${account?.username}`);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
else if(accountMutate.isError){
|
else if(forcePasswordResetMutate.isError){
|
||||||
//TODO: Add message modal here
|
forcePasswordResetMutate.reset();
|
||||||
console.log(accountMutate.error);
|
addErrorMessage(`Error forcing password reset for ${account?.username}: ${forcePasswordResetMutate.error.message}`);
|
||||||
|
console.log(forcePasswordResetMutate.error);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ import SecondaryButton from "@/components/button/SecondaryButton";
|
|||||||
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
import RaidBuilderModal from "@/components/modal/RaidBuilderModal";
|
||||||
import { useRevokeRefreshToken } from "@/hooks/AccountHooks";
|
import { useRevokeRefreshToken } from "@/hooks/AccountHooks";
|
||||||
import { Account } from "@/interface/Account";
|
import { Account } from "@/interface/Account";
|
||||||
|
import { useTimedModal } from "@/providers/TimedModalProvider";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
|
||||||
export default function RevokeRefreshTokenModal({
|
export default function RevokeRefreshTokenModal({
|
||||||
@@ -15,20 +17,25 @@ export default function RevokeRefreshTokenModal({
|
|||||||
account: Account | undefined;
|
account: Account | undefined;
|
||||||
}){
|
}){
|
||||||
const revokeRefreshTokenMutate = useRevokeRefreshToken(account?.accountId ?? "");
|
const revokeRefreshTokenMutate = useRevokeRefreshToken(account?.accountId ?? "");
|
||||||
|
const { addSuccessMessage, addErrorMessage } = useTimedModal();
|
||||||
|
|
||||||
|
|
||||||
const revokeRefreshToken = () => {
|
const revokeRefreshToken = () => {
|
||||||
revokeRefreshTokenMutate.mutate();
|
revokeRefreshTokenMutate.mutate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
if(revokeRefreshTokenMutate.isSuccess){
|
if(revokeRefreshTokenMutate.isSuccess){
|
||||||
revokeRefreshTokenMutate.reset();
|
revokeRefreshTokenMutate.reset();
|
||||||
|
addSuccessMessage(`Refresh token for ${account?.username} was successfully revoked`);
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
else if(revokeRefreshTokenMutate.isError){
|
else if(revokeRefreshTokenMutate.isError){
|
||||||
//TODO: Add message modal here
|
revokeRefreshTokenMutate.reset();
|
||||||
|
addErrorMessage(`Error revoking refresh token for ${account?.username}: ${revokeRefreshTokenMutate.error.message}`);
|
||||||
console.log(revokeRefreshTokenMutate.error);
|
console.log(revokeRefreshTokenMutate.error);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
1
src/util/SkeletonUtil.ts
Normal file
1
src/util/SkeletonUtil.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export const elementBg = "rounded-lg bg-neutral-700 dark:bg-neutral-200 animate-pulse";
|
||||||
Reference in New Issue
Block a user