-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #57 from Prodeko/better-admin-tools
- Loading branch information
Showing
17 changed files
with
263 additions
and
34 deletions.
There are no files selected for viewing
2 changes: 2 additions & 0 deletions
2
prisma/migrations/20250113182505_add_admin_deposit_method/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
-- AlterEnum | ||
ALTER TYPE "DepositMethod" ADD VALUE 'ADMIN'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -217,4 +217,5 @@ enum DepositMethod { | |
MANUAL_MOBILEPAY | ||
STRIPE | ||
ACCOUNT_MIGRATION | ||
ADMIN | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { AdminTitle } from "@/components/ui/AdminTitle"; | ||
import { EditProductForm } from "@/components/ui/EditProductForm"; | ||
|
||
const NewProduct = () => { | ||
return ( | ||
<div className="flex w-full max-w-screen-lg flex-col gap-8 pb-6 lg:w-[80%]"> | ||
<AdminTitle withBackButton title="New product" /> | ||
<div className="px-8"> | ||
<EditProductForm /> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default NewProduct; |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
"use client"; | ||
|
||
import { format } from "date-fns"; | ||
import { useRef, useState } from "react"; | ||
import toast from "react-hot-toast"; | ||
import { HiPencil, HiPlus, HiX } from "react-icons/hi"; | ||
|
||
import { ClientUser } from "@/common/types"; | ||
import { AnimatedPopup, PopupRefActions } from "@/components/ui/AnimatedPopup"; | ||
import { FatButton } from "@/components/ui/Buttons/FatButton"; | ||
import { IconButton } from "@/components/ui/Buttons/IconButton"; | ||
import { InputWithLabel } from "@/components/ui/Input"; | ||
import { adminAddFundsAction } from "@/server/actions/transaction/addFunds"; | ||
import { Role, User } from "@prisma/client"; | ||
|
||
interface Props { | ||
user: ClientUser; | ||
} | ||
|
||
const EditUserButton = ( | ||
<IconButton buttonType="button" Icon={HiPencil} sizing="xs" /> | ||
); | ||
|
||
export const ManageUserDialog = ({ user }: Props) => { | ||
const [modifyBalanceAmount, setModifyBalanceAmount] = useState<number | "">( | ||
"", | ||
); | ||
|
||
const popupRef = useRef<PopupRefActions>(undefined); | ||
|
||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||
const value = Math.round(parseFloat(e.target.value) * 100) / 100; | ||
if (!Number.isNaN(value)) { | ||
setModifyBalanceAmount(value); | ||
} else { | ||
setModifyBalanceAmount(""); | ||
} | ||
}; | ||
|
||
const addToBalance = async () => { | ||
try { | ||
if (modifyBalanceAmount === "" || modifyBalanceAmount === 0) | ||
throw new Error("Please enter a valid amount"); | ||
await adminAddFundsAction(modifyBalanceAmount, user.id); | ||
toast.success("Balance added successfully"); | ||
} catch (error) { | ||
toast.error(`Failed to add balance: ${error}`); | ||
} | ||
setModifyBalanceAmount(""); | ||
}; | ||
|
||
const removeFromBalance = async () => { | ||
try { | ||
if (modifyBalanceAmount === "" || modifyBalanceAmount === 0) | ||
throw new Error("Please enter a valid amount"); | ||
await adminAddFundsAction(-modifyBalanceAmount, user.id); | ||
toast.success("Balance removed successfully"); | ||
} catch (error) { | ||
toast.error(`Failed to remove balance: ${error}`); | ||
} | ||
setModifyBalanceAmount(""); | ||
}; | ||
|
||
return ( | ||
<AnimatedPopup ref={popupRef} TriggerComponent={EditUserButton}> | ||
<div className="no-scrollbar flex flex-col gap-6 overflow-hidden rounded-xl bg-neutral-50 px-3 py-6 md:px-12 md:py-12 portrait:max-h-[80vh] portrait:w-[80vw] landscape:max-h-[80vh] landscape:w-[50vw] "> | ||
<div className="flex w-full items-center justify-between"> | ||
<p className="text-xl font-bold text-primary-400 md:text-3xl"> | ||
Manage user | ||
</p> | ||
{/* biome-ignore lint/a11y/useKeyWithClickEvents: <explanation> */} | ||
<div | ||
className="flex h-10 w-10 cursor-pointer items-center justify-center rounded-full border-2 border-primary-400 bg-primary-50 text-lg text-primary-400 md:h-16 md:w-16 md:border-2 md:text-4xl" | ||
onClick={() => popupRef?.current?.closeContainer()} | ||
> | ||
<HiX /> | ||
</div> | ||
</div> | ||
<div className="flex w-full flex-col gap-4 text-lg text-neutral-500 md:text-xl"> | ||
<span className="text-xl font-medium text-neutral-700 md:text-2xl"> | ||
{user.firstName} {user.lastName} | ||
</span>{" "} | ||
<div className="">Username: {user.userName}</div> | ||
<div className="">Role: {user.role}</div> | ||
<div className=""> | ||
Created: {format(user.createdAt, "dd.MM.yyyy")} | ||
</div> | ||
</div> | ||
|
||
<div className="flex flex-col gap-4"> | ||
<InputWithLabel | ||
labelText="Add or remove from balance" | ||
placeholder="Amount to add/remove" | ||
type="number" | ||
tabIndex={-1} | ||
value={modifyBalanceAmount} | ||
onChange={handleInputChange} | ||
/> | ||
<div className="flex gap-4"> | ||
<FatButton | ||
buttonType="button" | ||
intent={"secondary"} | ||
text="Remove" | ||
onClick={() => removeFromBalance()} | ||
/> | ||
<FatButton | ||
buttonType="button" | ||
intent={"primary"} | ||
text="Add" | ||
onClick={() => addToBalance()} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
</AnimatedPopup> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
"use client"; | ||
|
||
import { ClientUser } from "@/common/types"; | ||
import { useAutoAnimate } from "@formkit/auto-animate/react"; | ||
import { User } from "@prisma/client"; | ||
|
||
import { ManageUserDialog } from "./ManageUserDialog"; | ||
|
||
interface Props { | ||
users: ClientUser[]; | ||
} | ||
|
||
export const UserList = ({ users }: Props) => { | ||
const [parent] = useAutoAnimate<HTMLDivElement>({ duration: 200 }); | ||
|
||
return ( | ||
<section className="flex flex-col gap-3"> | ||
<div className="tex-lg flex w-full flex-col items-start justify-between gap-4 px-5 text-neutral-800 md:flex-row md:items-center md:gap-6 md:px-12 md:text-xl"> | ||
<span className="flex-none text-neutral-500"> | ||
Displaying {users.length} users | ||
</span> | ||
</div> | ||
<div | ||
ref={parent} | ||
className="flex flex-col divide-y-2 divide-neutral-200 px-5 md:px-12 " | ||
> | ||
{users.map((user) => ( | ||
<div | ||
key={user.id} | ||
className="text-md flex w-full items-center justify-between py-5 text-neutral-500 md:py-5 md:text-xl" | ||
> | ||
<div> | ||
<span className="text-xl font-medium text-neutral-700 md:text-2xl"> | ||
{user.firstName} {user.lastName} | ||
</span>{" "} | ||
({user.userName}) | ||
</div> | ||
{/* biome-ignore lint/a11y/useKeyWithClickEvents: <explanation> */} | ||
<ManageUserDialog user={user} /> | ||
</div> | ||
))} | ||
</div> | ||
</section> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { AdminTitle } from "@/components/ui/AdminTitle"; | ||
import { getAllUsers } from "@/server/db/queries/account"; | ||
|
||
import { UserList } from "./UserList"; | ||
|
||
const ManageUsers = async () => { | ||
const users = await getAllUsers(); | ||
return ( | ||
<div className="no-scrollbar flex h-fit w-full max-w-screen-lg flex-col gap-8 overflow-y-scroll px-0 lg:w-[80%]"> | ||
<AdminTitle title="Manage users" /> | ||
<UserList users={users} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ManageUsers; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.