Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

disabled login button when fields are empty #870

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions src/actions/payoutMethods/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,6 @@ const deleteSolanaHandler = async (
};
};



export const addUpi = createSafeAction(upiIdInsertSchema, addUpiHandler);

export const addSolanaAddress = createSafeAction(
Expand Down
8 changes: 4 additions & 4 deletions src/actions/payoutMethods/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { z } from 'zod';
export const payoutMethodSchema = z.object({
upiId: z
.string()
.refine((value) => /^[0-9A-Za-z._-]{2,256}@[A-Za-z]{2,64}$/.test(value), {
.refine((value) => (/^[0-9A-Za-z._-]{2,256}@[A-Za-z]{2,64}$/).test(value), {
message: 'Enter a valid UPI address',
})
.optional(),
solanaAddress: z
.string()
.refine((value) => /^[A-Za-z0-9]{44}$/.test(value), {
.refine((value) => (/^[A-Za-z0-9]{44}$/).test(value), {
message: 'Enter a valid Solana address',
})
.optional(),
Expand All @@ -18,13 +18,13 @@ export const payoutMethodSchema = z.object({
export const upiIdInsertSchema = z.object({
upiId: z
.string()
.refine((value) => /^[0-9A_Za-z._-]{2,256}@[A_Za-z]{2,64}$/.test(value), {
.refine((value) => (/^[0-9A_Za-z._-]{2,256}@[A_Za-z]{2,64}$/).test(value), {
message: 'Invalid UPI address',
}),
});

export const solanaAddressInsertSchema = z.object({
solanaAddress: z.string().refine((value) => /^[A-Za-z0-9]{44}$/.test(value), {
solanaAddress: z.string().refine((value) => (/^[A-Za-z0-9]{44}$/).test(value), {
message: 'Invalid Solana address',
}),
});
Expand Down
16 changes: 13 additions & 3 deletions src/actions/payoutMethods/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { z } from 'zod';
import { payoutMethodDeleteSchema, solanaAddressInsertSchema, upiIdInsertSchema } from './schema';
import {
payoutMethodDeleteSchema,
solanaAddressInsertSchema,
upiIdInsertSchema,
} from './schema';
import { ActionState } from '@/lib/create-safe-action';
import { SolanaAddress, UpiId } from '@prisma/client';
import { Delete } from '@/lib/utils';
Expand All @@ -8,7 +12,13 @@ export type InputTypeCreateUpi = z.infer<typeof upiIdInsertSchema>;
export type ReturnTypeCreateUpi = ActionState<InputTypeCreateUpi, UpiId>;

export type InputTypeCreateSolana = z.infer<typeof solanaAddressInsertSchema>;
export type ReturnTypeCreateSolana = ActionState<InputTypeCreateSolana, SolanaAddress>;
export type ReturnTypeCreateSolana = ActionState<
InputTypeCreateSolana,
SolanaAddress
>;

export type DeleteTypePayoutMethod = z.infer<typeof payoutMethodDeleteSchema>;
export type ReturnTypePayoutMethodDelete = ActionState<DeleteTypePayoutMethod, Delete>;
export type ReturnTypePayoutMethodDelete = ActionState<
DeleteTypePayoutMethod,
Delete
>;
272 changes: 149 additions & 123 deletions src/app/payout-methods/page.tsx
Original file line number Diff line number Diff line change
@@ -1,141 +1,167 @@
"use client"
import { useEffect, useState } from "react";
import { Button } from "@/components/ui/button";
import NewPayoutDialog from "@/components/NewPayoutDialog";
import { Trash } from "lucide-react"
import { deleteSolanaAddress, deleteUpiId, getPayoutMethods } from "@/actions/payoutMethods";
import { SolanaAddress, UpiId } from "@prisma/client";
import { useAction } from "@/hooks/useAction";
import { toast } from "sonner";
'use client';
import { useEffect, useState } from 'react';
import { Button } from '@/components/ui/button';
import NewPayoutDialog from '@/components/NewPayoutDialog';
import { Trash } from 'lucide-react';
import {
deleteSolanaAddress,
deleteUpiId,
getPayoutMethods,
} from '@/actions/payoutMethods';
import { SolanaAddress, UpiId } from '@prisma/client';
import { useAction } from '@/hooks/useAction';
import { toast } from 'sonner';

export default function Page() {
const [isDialogBoxOpen, setIsDialogBoxOpen] = useState<boolean>(false);
const [btnClicked, setBtnClicked] = useState<string>('');

const [isDialogBoxOpen, setIsDialogBoxOpen] = useState<boolean>(false)
const [btnClicked, setBtnClicked] = useState<string>("")
const openDialog = (e: any) => {
setIsDialogBoxOpen(true);
setBtnClicked(e.target.id);
};

const openDialog = (e: any) => {
setIsDialogBoxOpen(true)
setBtnClicked(e.target.id)
}

const closeDialog = () => setIsDialogBoxOpen(false)
const closeDialog = () => setIsDialogBoxOpen(false);

const [upiAddresses, setUpiAddresses] = useState<UpiId[] | undefined>([])
const [solanaAddresses, setSolanaAddresses] = useState<SolanaAddress[] | undefined>([])
const [upiAddresses, setUpiAddresses] = useState<UpiId[] | undefined>([]);
const [solanaAddresses, setSolanaAddresses] = useState<
SolanaAddress[] | undefined
>([]);

const fetchPayoutMethods = async () => {
const result = await getPayoutMethods()
if (result) {
setUpiAddresses(result.upiIds)
setSolanaAddresses(result.solanaAddresses)
}
const fetchPayoutMethods = async () => {
const result = await getPayoutMethods();
if (result) {
setUpiAddresses(result.upiIds);
setSolanaAddresses(result.solanaAddresses);
}
};

const { execute: executeDeleteUPI } = useAction(deleteUpiId, {
onSuccess: () => {
toast.success("UPI Address deleted successfully")
},
onError: () => {
toast.error("Failed to delete UPI id")
}
})
const { execute: executeDeleteUPI } = useAction(deleteUpiId, {
onSuccess: () => {
toast.success('UPI Address deleted successfully');
},
onError: () => {
toast.error('Failed to delete UPI id');
},
});

const { execute: executeDeleteSolana } = useAction(deleteSolanaAddress, {
onSuccess: () => {
toast.success("Solana Address deleted successfully")
},
onError: () => {
toast.error("Failed to delete Solana address")
}
})
const { execute: executeDeleteSolana } = useAction(deleteSolanaAddress, {
onSuccess: () => {
toast.success('Solana Address deleted successfully');
},
onError: () => {
toast.error('Failed to delete Solana address');
},
});

const handleUpiDelete = (id: number) => {
executeDeleteUPI({ id: id })
fetchPayoutMethods()
}
const handleUpiDelete = (id: number) => {
executeDeleteUPI({ id });
fetchPayoutMethods();
};

const handleSolanaDelete = (id: number) => {
executeDeleteSolana({ id: id })
fetchPayoutMethods()
}
const handleSolanaDelete = (id: number) => {
executeDeleteSolana({ id });
fetchPayoutMethods();
};

useEffect(() => {
fetchPayoutMethods()
}, [])
useEffect(() => {
fetchPayoutMethods();
}, []);

useEffect(() => {
fetchPayoutMethods()
}, [isDialogBoxOpen])
useEffect(() => {
fetchPayoutMethods();
}, [isDialogBoxOpen]);

return (
<div className="h-max pb-4 transition-colors duration-500 md:p-8">
<div className="mb-6 flex flex-col items-start justify-center sm:px-8 px-4 pt-3">
<div className="text-3xl text-black transition-colors duration-500 dark:text-white">
<h1 className="text-black dark:text-white">Payout Methods</h1>
</div>
<div className="py-8 sm:px-0 px-2">
<div>
<div className="w-[90vw] flex justify-between">
<p className="font-semibold py-2">UPI Addresses</p>
<Button
id="UPI"
size="sm"
className="light:text-black sticky rounded-md bg-black hover:bg-[#242424] p-3 text-white transition-colors duration-500 dark:bg-white dark:text-black hover:dark:bg-white"
onClick={(e) => openDialog(e)}
>
Add UPI address
</Button>
<NewPayoutDialog onClose={closeDialog} isOpen={isDialogBoxOpen} title={btnClicked} />
</div>
<div className="flex flex-col sm:w-3/6 w-[90vw]">
{
upiAddresses?.length !== 0 ? (
upiAddresses?.map((upi, index) => (
<div key={index} className="w-full flex items-center justify-between py-2">
<p className="sm:w-full w-1/2 overflow-hidden text-ellipsis whitespace-nowrap" >{upi.value}</p>
<Button className="mx-3" size="iconSM" variant={"outline"}><Trash className="w-4 h-4" onClick={() => handleUpiDelete(upi.id)} /></Button>
</div>
))
) :
<div className="flex flex-col items-start">
<p className="py-3">No addresses added yet!</p>
</div>
}
</div>
</div>
return (
<div className="h-max pb-4 transition-colors duration-500 md:p-8">
<div className="mb-6 flex flex-col items-start justify-center px-4 pt-3 sm:px-8">
<div className="text-3xl text-black transition-colors duration-500 dark:text-white">
<h1 className="text-black dark:text-white">Payout Methods</h1>
</div>
<div className="px-2 py-8 sm:px-0">
<div>
<div className="flex w-[90vw] justify-between">
<p className="py-2 font-semibold">UPI Addresses</p>
<Button
id="UPI"
size="sm"
className="light:text-black sticky rounded-md bg-black p-3 text-white transition-colors duration-500 hover:bg-[#242424] dark:bg-white dark:text-black hover:dark:bg-white"
onClick={(e) => openDialog(e)}
>
Add UPI address
</Button>
<NewPayoutDialog
onClose={closeDialog}
isOpen={isDialogBoxOpen}
title={btnClicked}
/>
</div>
<div className="flex w-[90vw] flex-col sm:w-3/6">
{upiAddresses?.length !== 0 ? (
upiAddresses?.map((upi, index) => (
<div
key={index}
className="flex w-full items-center justify-between py-2"
>
<p className="w-1/2 overflow-hidden text-ellipsis whitespace-nowrap sm:w-full">
{upi.value}
</p>
<Button className="mx-3" size="iconSM" variant={'outline'}>
<Trash
className="h-4 w-4"
onClick={() => handleUpiDelete(upi.id)}
/>
</Button>
</div>
))
) : (
<div className="flex flex-col items-start">
<p className="py-3">No addresses added yet!</p>
</div>
<div className="py-4 sm:px-0 px-2">
<div>
<div className="w-[90vw] flex justify-between">
<p className="font-semibold py-2">Solana Addresses</p>
<Button
id="Solana"
size="sm"
className="light:text-black sticky rounded-md bg-black hover:bg-[#242424] p-3 text-white transition-colors duration-500 dark:bg-white dark:text-black hover:dark:bg-white"
onClick={(e) => openDialog(e)}
>
Add SOL address
</Button>
</div>
<div className="flex flex-col sm:w-3/6 w-[90vw]">
{
solanaAddresses?.length !== 0 ? (
solanaAddresses?.map((sol, index) => (
<div key={index} className="flex items-center justify-between py-2">
<p className="sm:w-full w-1/2 overflow-hidden text-ellipsis whitespace-nowrap" >{sol.value}</p>
<Button className="mx-3" size="iconSM" variant={"outline"}><Trash className="w-4 h-4" onClick={() => handleSolanaDelete(sol.id)} /></Button>
</div>
))
) :
<div className="flex flex-col items-start">
<p className="py-3">No addresses added yet!</p>
</div>
}
</div>
</div>
)}
</div>
</div>
</div>
<div className="px-2 py-4 sm:px-0">
<div>
<div className="flex w-[90vw] justify-between">
<p className="py-2 font-semibold">Solana Addresses</p>
<Button
id="Solana"
size="sm"
className="light:text-black sticky rounded-md bg-black p-3 text-white transition-colors duration-500 hover:bg-[#242424] dark:bg-white dark:text-black hover:dark:bg-white"
onClick={(e) => openDialog(e)}
>
Add SOL address
</Button>
</div>
<div className="flex w-[90vw] flex-col sm:w-3/6">
{solanaAddresses?.length !== 0 ? (
solanaAddresses?.map((sol, index) => (
<div
key={index}
className="flex items-center justify-between py-2"
>
<p className="w-1/2 overflow-hidden text-ellipsis whitespace-nowrap sm:w-full">
{sol.value}
</p>
<Button className="mx-3" size="iconSM" variant={'outline'}>
<Trash
className="h-4 w-4"
onClick={() => handleSolanaDelete(sol.id)}
/>
</Button>
</div>
))
) : (
<div className="flex flex-col items-start">
<p className="py-3">No addresses added yet!</p>
</div>

)}
</div>
</div>
</div>
);
}
</div>
</div>
);
}
19 changes: 11 additions & 8 deletions src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,11 @@ export function Sidebar({
<Link
key={content.id}
href={navigateToContent(content.id) || '#'}
className={`flex cursor-pointer border-b p-2 hover:bg-gray-200 ${isActiveContent
? 'bg-gray-300 text-black dark:bg-gray-700 dark:text-white dark:hover:bg-gray-500'
: 'bg-gray-50 text-black dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700'
}`}
className={`flex cursor-pointer border-b p-2 hover:bg-gray-200 ${
isActiveContent
? 'bg-gray-300 text-black dark:bg-gray-700 dark:text-white dark:hover:bg-gray-500'
: 'bg-gray-50 text-black dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700'
}`}
>
<div className="flex w-full justify-between">
<div className="flex">
Expand Down Expand Up @@ -189,12 +190,14 @@ export function ToggleButton({
className={`block h-0.5 w-6 rounded-sm bg-black transition-all duration-300 ease-out dark:bg-white ${!sidebarOpen ? 'translate-y-1 rotate-45' : '-translate-y-0.5'}`}
></span>
<span
className={`my-0.5 block h-0.5 w-6 rounded-sm bg-black transition-all duration-300 ease-out dark:bg-white ${!sidebarOpen ? 'opacity-0' : 'opacity-100'
}`}
className={`my-0.5 block h-0.5 w-6 rounded-sm bg-black transition-all duration-300 ease-out dark:bg-white ${
!sidebarOpen ? 'opacity-0' : 'opacity-100'
}`}
></span>
<span
className={`block h-0.5 w-6 rounded-sm bg-black transition-all duration-300 ease-out dark:bg-white ${!sidebarOpen ? '-translate-y-1 -rotate-45' : 'translate-y-0.5'
}`}
className={`block h-0.5 w-6 rounded-sm bg-black transition-all duration-300 ease-out dark:bg-white ${
!sidebarOpen ? '-translate-y-1 -rotate-45' : 'translate-y-0.5'
}`}
></span>
</button>
);
Expand Down
Loading
Loading