Skip to content

Commit

Permalink
group page rework / modal fixes (#127)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Felix C. Morency <[email protected]>
  • Loading branch information
chalabi2 and fmorency authored Dec 9, 2024
1 parent 32d6952 commit 9f73765
Show file tree
Hide file tree
Showing 28 changed files with 1,722 additions and 1,027 deletions.
263 changes: 147 additions & 116 deletions components/admins/modals/validatorModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { Formik, Form, Field, ErrorMessage, FieldProps } from 'formik';
import * as Yup from 'yup';
import { calculateIsUnsafe } from '@/utils/maths';
import { TextInput } from '@/components/react';
import { createPortal } from 'react-dom';

const PowerUpdateSchema = Yup.object().shape({
power: Yup.number()
Expand Down Expand Up @@ -121,151 +122,181 @@ export function ValidatorDetailsModal({
(document.getElementById(modalId) as HTMLDialogElement)?.close();
};

return (
const modalContent = (
<dialog
id={modalId}
className={`modal ${openValidatorModal ? 'modal-open' : ''}`}
onClose={handleClose}
style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 9999,
backgroundColor: 'transparent',
padding: 0,
margin: 0,
height: '100vh',
width: '100vw',
display: openValidatorModal ? 'flex' : 'none',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Formik
initialValues={{ power: power, totalvp, validatorVPArray }}
validationSchema={PowerUpdateSchema}
onSubmit={() => {}}
enableReinitialize
>
{({ isValid, errors, touched }) => {
return (
<div className="modal-box relative max-w-4xl min-h-96 flex flex-col md:flex-row md:ml-20 -mt-12 rounded-[24px] shadow-lg dark:bg-[#1D192D] bg-[#FFFFFF] transition-all duration-300">
<button
className="btn btn-sm btn-circle text-black dark:text-white btn-ghost absolute right-2 top-2"
onClick={handleClose}
type="button"
>
</button>
<div className="flex flex-col flex-grow w-full p-6 space-y-6">
<h3 className="text-2xl font-bold text-black dark:text-white">Validator Details</h3>
<div className="flex flex-col justify-start items-start gap-4">
<span className="text-sm text-gray-500 dark:text-gray-400">VALIDATOR</span>
<div className="flex flex-row justify-start items-center gap-4">
{validator?.logo_url !== '' ? (
<img className="h-16 w-16 rounded-full" src={validator.logo_url} alt="" />
) : (
<ProfileAvatar walletAddress={validator?.operator_address} size={64} />
)}
<span className="text-2xl font-bold text-black dark:text-white">
{validator?.description.moniker}
</span>
</div>
{({ isValid, errors, touched }) => (
<div className="modal-box relative max-w-4xl min-h-96 flex flex-col md:flex-row md:ml-20 -mt-12 rounded-[24px] shadow-lg dark:bg-[#1D192D] bg-[#FFFFFF] transition-all duration-300">
<button
className="btn btn-sm btn-circle text-black dark:text-white btn-ghost absolute right-2 top-2"
onClick={handleClose}
type="button"
>
</button>
<div className="flex flex-col flex-grow w-full p-6 space-y-6">
<h3 className="text-2xl font-bold text-black dark:text-white">Validator Details</h3>
<div className="flex flex-col justify-start items-start gap-4">
<span className="text-sm text-gray-500 dark:text-gray-400">VALIDATOR</span>
<div className="flex flex-row justify-start items-center gap-4">
{validator?.logo_url !== '' ? (
<img className="h-16 w-16 rounded-full" src={validator.logo_url} alt="" />
) : (
<ProfileAvatar walletAddress={validator?.operator_address} size={64} />
)}
<span className="text-2xl font-bold text-black dark:text-white">
{validator?.description.moniker}
</span>
</div>
</div>

<div className="space-y-6">
<div className="dark:bg-[#FFFFFF0F] bg-[#0000000A] rounded-[12px] p-4">
<span className="text-sm text-gray-500 dark:text-gray-400">
SECURITY CONTACT
</span>
<p className="text-md text-black dark:text-white mt-2">
{isEmail(validator?.description.security_contact)
? validator?.description.security_contact
: 'No Security Contact'}
</p>
</div>
<div className="dark:bg-[#FFFFFF0F] bg-[#0000000A] rounded-[12px] p-4">
<span className="text-sm text-gray-500 dark:text-gray-400">POWER</span>
<div className="flex flex-col gap-2 mt-2">
<div className="flex flex-row gap-2 justify-between items-center">
<div className="relative w-2/3">
<Field name="power">
{({ field, meta }: FieldProps) => (
<div className="relative">
<TextInput
showError={false}
{...field}
type="number"
placeholder={validator?.consensus_power?.toString() ?? 'Inactive'}
className={`input input-bordered w-full ${
meta.touched && meta.error ? 'input-error' : ''
}`}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
field.onChange(e);
setPowerInput(e.target.value);
}}
/>
{meta.touched && meta.error && (
<div
className="tooltip tooltip-bottom tooltip-open tooltip-error bottom-0 absolute left-1/2 transform -translate-x-1/2 translate-y-full mt-1 z-50 text-white text-xs"
data-tip={meta.error}
>
<div className="w-0 h-0"></div>
</div>
)}
</div>
)}
</Field>
</div>
<button
type="submit"
className="btn btn-gradient w-1/3"
disabled={!isValid || isSigning}
onClick={() => {
handleUpdate({ power: power });
}}
>
{isSigning ? (
<span className="loading loading-dots loading-sm"></span>
) : (
'Update'
<div className="space-y-6">
<div className="dark:bg-[#FFFFFF0F] bg-[#0000000A] rounded-[12px] p-4">
<span className="text-sm text-gray-500 dark:text-gray-400">SECURITY CONTACT</span>
<p className="text-md text-black dark:text-white mt-2">
{isEmail(validator?.description.security_contact)
? validator?.description.security_contact
: 'No Security Contact'}
</p>
</div>
<div className="dark:bg-[#FFFFFF0F] bg-[#0000000A] rounded-[12px] p-4">
<span className="text-sm text-gray-500 dark:text-gray-400">POWER</span>
<div className="flex flex-col gap-2 mt-2">
<div className="flex flex-row gap-2 justify-between items-center">
<div className="relative w-2/3">
<Field name="power">
{({ field, meta }: FieldProps) => (
<div className="relative">
<TextInput
showError={false}
{...field}
type="number"
placeholder={validator?.consensus_power?.toString() ?? 'Inactive'}
className={`input input-bordered w-full ${
meta.touched && meta.error ? 'input-error' : ''
}`}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
field.onChange(e);
setPowerInput(e.target.value);
}}
/>
{meta.touched && meta.error && (
<div
className="tooltip tooltip-bottom tooltip-open tooltip-error bottom-0 absolute left-1/2 transform -translate-x-1/2 translate-y-full mt-1 z-50 text-white text-xs"
data-tip={meta.error}
>
<div className="w-0 h-0"></div>
</div>
)}
</div>
)}
</button>
</Field>
</div>
{isUnsafe && Number(power) > 0 && (
<div className="text-warning text-xs">
Warning: This power update may be unsafe
</div>
)}
<button
type="submit"
className="btn btn-gradient w-1/3"
disabled={!isValid || isSigning}
onClick={() => {
handleUpdate({ power: power });
}}
>
{isSigning ? (
<span className="loading loading-dots loading-sm"></span>
) : (
'Update'
)}
</button>
</div>
{isUnsafe && Number(power) > 0 && (
<div className="text-warning text-xs">
Warning: This power update may be unsafe
</div>
)}
</div>
<div className="dark:bg-[#FFFFFF0F] bg-[#0000000A] rounded-[12px] p-4">
<span className="text-sm text-gray-500 dark:text-gray-400">
OPERATOR ADDRESS
</span>
<div className="text-md mt-2">
<TruncatedAddressWithCopy address={validator?.operator_address} slice={42} />
</div>
</div>
<div className="dark:bg-[#FFFFFF0F] bg-[#0000000A] rounded-[12px] p-4">
<span className="text-sm text-gray-500 dark:text-gray-400">OPERATOR ADDRESS</span>
<div className="text-md mt-2">
<TruncatedAddressWithCopy address={validator?.operator_address} slice={42} />
</div>
<div className="dark:bg-[#FFFFFF0F] bg-[#0000000A] rounded-[12px] p-4">
<div className="flex flex-row justify-between items-center relative">
<span className="text-sm text-gray-500 dark:text-gray-400">DETAILS</span>
{validator?.description.details.length > 50 && (
<button
className="btn btn-sm btn-ghost hover:bg-transparent absolute -right-2 -top-2"
onClick={handleDescription}
>
<BsThreeDots />
</button>
)}
</div>
<p className="text-md mt-2 text-black dark:text-white" aria-label="details">
{validator?.description.details
? validator.description.details.substring(0, 50) +
(validator.description.details.length > 50 ? '...' : '')
: 'No Details'}
</p>
</div>
<div className="dark:bg-[#FFFFFF0F] bg-[#0000000A] rounded-[12px] p-4">
<div className="flex flex-row justify-between items-center relative">
<span className="text-sm text-gray-500 dark:text-gray-400">DETAILS</span>
{validator?.description.details.length > 50 && (
<button
className="btn btn-sm btn-ghost hover:bg-transparent absolute -right-2 -top-2"
onClick={handleDescription}
>
<BsThreeDots />
</button>
)}
</div>
<p className="text-md mt-2 text-black dark:text-white" aria-label="details">
{validator?.description.details
? validator.description.details.substring(0, 50) +
(validator.description.details.length > 50 ? '...' : '')
: 'No Details'}
</p>
</div>
</div>
</div>
);
}}
</div>
)}
</Formik>
<DescriptionModal
type="validator"
modalId="validator-description-modal"
details={validator?.description.details ?? 'No Details'}
/>
<form method="dialog" className="modal-backdrop">
<button onClick={handleClose}>close</button>
<form
method="dialog"
className="modal-backdrop"
style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: -1,
backgroundColor: 'rgba(0, 0, 0, 0.3)',
}}
onSubmit={handleClose}
>
<button>close</button>
</form>
</dialog>
);

// Only render if we're in the browser
if (typeof document !== 'undefined') {
return createPortal(modalContent, document.body);
}

return null;
}
47 changes: 42 additions & 5 deletions components/admins/modals/warningModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import { cosmos, strangelove_ventures } from '@liftedinit/manifestjs';
import { Any } from '@liftedinit/manifestjs/dist/codegen/google/protobuf/any';
import { MsgRemoveValidator } from '@liftedinit/manifestjs/dist/codegen/strangelove_ventures/poa/v1/tx';
import { useChain } from '@cosmos-kit/react';
import React, { useEffect, useState } from 'react';
import React, { useEffect } from 'react';
import { PiWarning } from 'react-icons/pi';
import { createPortal } from 'react-dom';

interface WarningModalProps {
admin: string;
Expand Down Expand Up @@ -90,11 +91,27 @@ export function WarningModal({
(document.getElementById(modalId) as HTMLDialogElement)?.close();
};

return (
const modalContent = (
<dialog
id={modalId}
className={`modal ${openWarningModal ? 'modal-open' : ''}`}
onClose={handleClose}
style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: 9999,
backgroundColor: 'transparent',
padding: 0,
margin: 0,
height: '100vh',
width: '100vw',
display: openWarningModal ? 'flex' : 'none',
alignItems: 'center',
justifyContent: 'center',
}}
>
<form
method="dialog"
Expand All @@ -106,7 +123,7 @@ export function WarningModal({
>
</button>
<div className="p-4 ">
<div className="p-4">
<div className="flex flex-col gap-2 items-center mb-6">
<PiWarning className="text-yellow-200 text-6xl" />
</div>
Expand Down Expand Up @@ -136,9 +153,29 @@ export function WarningModal({
</button>
</div>
</form>
<form method="dialog" className="modal-backdrop">
<button onClick={handleClose}>close</button>
<form
method="dialog"
className="modal-backdrop"
style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
bottom: 0,
zIndex: -1,
backgroundColor: 'rgba(0, 0, 0, 0.3)',
}}
onSubmit={handleClose}
>
<button>close</button>
</form>
</dialog>
);

// Only render if we're in the browser
if (typeof document !== 'undefined') {
return createPortal(modalContent, document.body);
}

return null;
}
Loading

0 comments on commit 9f73765

Please sign in to comment.