Skip to content

Commit

Permalink
manage dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
vidvidvid committed Oct 28, 2024
1 parent 3eb50ef commit d7ba5a0
Show file tree
Hide file tree
Showing 23 changed files with 717 additions and 310 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ import MaxDeposit from './MaxDeposit';
import SwapTo from './SwapTo';
import { SlippageDropdown } from '../SlippageDropdown';

import { collateralSwapAbi } from '@ionicprotocol/sdk';
import { collateralSwapAbi } from '@ionicprotocol/sdk/src';

createConfig({
integrator: 'ionic',
Expand Down
37 changes: 37 additions & 0 deletions packages/ui/app/_components/veion/DelegateView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { useState } from 'react';

import { InfoIcon } from 'lucide-react';
import { isAddress } from 'viem';

import { Button } from '@ui/components/ui/button';
import { Input } from '@ui/components/ui/input';

export function DelegateView() {
const [delegateAddress, setDelegateAddress] = useState('');
const isValidAddress = delegateAddress ? isAddress(delegateAddress) : false;

return (
<div className="flex flex-col gap-y-2 py-2 px-3">
<p>Delegate Address</p>
<Input
placeholder="0x..."
onChange={(e) => setDelegateAddress(e.target.value)}
className={!isValidAddress && delegateAddress ? 'border-red-500' : ''}
/>
<div className="border border-yellow-200 text-yellow-200 text-xs flex items-center gap-3 rounded-md py-2.5 px-4 mt-2">
<InfoIcon className="h-5 w-5 flex-shrink-0" />
<span>
You may delegate your voting power to any user, without transferring
the tokens. You may revoke it, but the user will still be able to vote
until the end of the current voting period.
</span>
</div>
<Button
className="w-full bg-accent text-black mt-4"
disabled={!isValidAddress}
>
Delegate veION
</Button>
</div>
);
}
155 changes: 155 additions & 0 deletions packages/ui/app/_components/veion/ExtendView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { useState, useEffect, useMemo } from 'react';

import { format, addDays } from 'date-fns';
import { Calendar as CalendarIcon } from 'lucide-react';

import { Button } from '@ui/components/ui/button';
import { Calendar } from '@ui/components/ui/calendar';
import {
Popover,
PopoverContent,
PopoverTrigger
} from '@ui/components/ui/popover';
import { Separator } from '@ui/components/ui/separator';
import { Slider } from '@ui/components/ui/slider';

import AutoLock from './AutoLock';
import CustomTooltip from '../CustomTooltip';

export function ExtendView() {
const [autoLock, setAutoLock] = useState(false);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [lockDuration, setLockDuration] = useState<string>('180');
const [lockDate, setLockDate] = useState<Date>(() =>
addDays(new Date(), 180)
);
const [selectedDuration, setSelectedDuration] = useState<number>(180);
const [isCalendarOpen, setIsCalendarOpen] = useState(false);

// Calculate the valid date range for the calendar
const dateRange = useMemo(() => {
const today = new Date();
return {
minDate: addDays(today, 180), // Minimum 180 days from today
maxDate: addDays(today, 730) // Maximum 730 days from today
};
}, []);

const durationLabels = {
180: '180d',
365: '1y',
547: '1.5y',
730: '2y'
};

useEffect(() => {
const newDate = addDays(new Date(), selectedDuration);
setLockDate(newDate);
setLockDuration(selectedDuration.toString());
}, [selectedDuration]);

const handleDurationChange = (val: number[]) => {
const duration = val[0];
setSelectedDuration(duration);
};

const handleDateSelect = (date: Date | undefined) => {
if (date) {
setLockDate(date);
// Calculate duration in days
const durationInDays = Math.round(
(date.getTime() - new Date().getTime()) / (1000 * 60 * 60 * 24)
);

// Clamp the duration between 180 and 730 days
const clampedDuration = Math.max(180, Math.min(730, durationInDays));
setSelectedDuration(clampedDuration);
setLockDuration(clampedDuration.toString());
setIsCalendarOpen(false);
}
};

return (
<div className="flex flex-col gap-y-2 py-2 px-3">
<div className="space-y-2">
<div className="flex items-center gap-2 text-xs text-white/60 tracking-wider mb-2">
<p>LOCK UNTIL</p>
<CustomTooltip content="A longer lock period gives you more veION for the same amount of LPs, which means a higher voting power." />
</div>
<div className="flex items-center justify-between">
<div className="text-sm text-white/60">
{format(lockDate, 'dd. MM. yyyy')}
</div>
<Popover
open={isCalendarOpen}
onOpenChange={setIsCalendarOpen}
>
<PopoverTrigger asChild>
<Button
variant="ghost"
className="p-0 hover:bg-transparent"
>
<CalendarIcon className="h-4 w-4 text-white/60" />
</Button>
</PopoverTrigger>
<PopoverContent
className="w-auto p-0 bg-grayUnselect border-white/10"
sideOffset={5}
>
<Calendar
mode="single"
selected={lockDate}
onSelect={handleDateSelect}
disabled={{
before: dateRange.minDate,
after: dateRange.maxDate
}}
defaultMonth={dateRange.minDate}
/>
</PopoverContent>
</Popover>
</div>
<Slider
value={[selectedDuration]}
onValueChange={handleDurationChange}
max={730}
min={180}
step={1}
className="[&_[role=slider]]:bg-accent [&_[role=slider]]:border-0"
/>
<div className="w-full flex justify-between text-xs text-white/60">
{Object.entries(durationLabels).map(([days, label]) => (
<span
key={days}
className={selectedDuration >= Number(days) ? 'text-accent' : ''}
>
{label}
</span>
))}
</div>
</div>

<AutoLock
autoLock={autoLock}
setAutoLock={setAutoLock}
/>

<Separator className="bg-white/10 my-4" />

<div className="flex w-full items-center justify-between text-xs text-white/50">
<div className="flex items-center gap-2">
VOTING POWER
<CustomTooltip content="Your voting power diminishes each day closer to the end of the token lock period." />
</div>
<p>0.00 veIon</p>
</div>

<div className="flex w-full items-center justify-between text-xs text-white/50">
LOCKED Until
<p>28 Aug 2023 → {format(lockDate, 'dd MMM yyyy')}</p>
</div>

<Button className="w-full bg-accent text-black mt-4">Extend Lock</Button>
</div>
);
}
89 changes: 89 additions & 0 deletions packages/ui/app/_components/veion/IncreaseView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { useState, useEffect } from 'react';

import { Button } from '@ui/components/ui/button';
import { Separator } from '@ui/components/ui/separator';
import { Slider } from '@ui/components/ui/slider';
import { getToken } from '@ui/utils/getStakingTokens';

import CustomTooltip from '../CustomTooltip';
import MaxDeposit from '../stake/MaxDeposit';

type IncreaseViewProps = {
chain: string;
};

export function IncreaseView({ chain }: IncreaseViewProps) {
const utilizationMarks = [0, 25, 50, 75, 100];
const [veionAmount, setVeIonAmount] = useState(0);
const [sliderValue, setSliderValue] = useState(0);
const maxtoken = '1000';

useEffect(() => {
const newSliderValue = (veionAmount / Number(maxtoken)) * 100;
setSliderValue(newSliderValue);
}, [veionAmount, maxtoken]);

const handleInputChange = (val?: string) => {
if (val !== undefined) {
setVeIonAmount(Number(val));
}
};

const handleSliderChange = (val: number[]) => {
const newVal = val[0];
setSliderValue(newVal);
const veionval = (newVal / 100) * Number(maxtoken);
setVeIonAmount(veionval);
};

return (
<div className="flex flex-col gap-y-2 py-2 px-3">
<MaxDeposit
headerText={'Lock Amount'}
max={maxtoken}
amount={String(veionAmount)}
tokenName={'ion/eth LP'}
token={getToken(+chain)}
handleInput={handleInputChange}
chain={+chain}
/>
<div className="w-full mx-auto mt-3 mb-5">
<div className="w-full mb-2 text-xs flex justify-between text-white/25">
{utilizationMarks.map((mark) => (
<span
key={mark}
className={sliderValue >= mark ? 'text-accent' : ''}
>
{mark}%
</span>
))}
</div>
<Slider
value={[sliderValue]}
onValueChange={handleSliderChange}
max={100}
step={1}
className="[&_[role=slider]]:bg-accent [&_[role=slider]]:border-0"
/>
</div>
<Separator className="bg-white/10 my-4" />

<div className="flex w-full items-center justify-between text-xs text-white/50">
<div className="flex items-center gap-2">
VOTING POWER
<CustomTooltip content="Your voting power diminishes each day closer to the end of the token lock period." />
</div>
<p>0.00 veIon</p>
</div>
<div className="flex w-full items-center justify-between text-xs text-white/50">
<div className="flex items-center gap-2">
LP <CustomTooltip content="Info regarding the locked BLP." />
</div>
<p>67.90 veIon</p>
</div>
<Button className="w-full bg-accent text-black mt-4">
Increase Locked Amount
</Button>
</div>
);
}
32 changes: 32 additions & 0 deletions packages/ui/app/_components/veion/InfoBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Image from 'next/image';

import type { InfoBlock } from '@ui/constants/mock';

import CustomTooltip from '../CustomTooltip';

interface InfoBlockProps {
block: InfoBlock;
}

const InfoBlockComponent: React.FC<InfoBlockProps> = ({ block }) => (
<div className="flex flex-col gap-1 mt-3">
<div className="text-white/60 text-xs flex items-center">
{block.label}
<CustomTooltip content={block.infoContent} />
</div>
<div className="text-white/60 text-xs flex items-center">
{block.icon && (
<Image
alt={`${block.label} icon`}
className="w-6 h-6 inline-block"
src={block.icon}
width={24}
height={24}
/>
)}
<span className="text-white text-sm ml-1">{block.value}</span>
</div>
</div>
);

export default InfoBlockComponent;
3 changes: 1 addition & 2 deletions packages/ui/app/_components/veion/LockDuration.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
'use client';
import { useState } from 'react';

import { format } from 'date-fns'; // to format dates
import formatDistanceToNowStrict from 'date-fns/formatDistanceToNowStrict';
import { format, formatDistanceToNowStrict } from 'date-fns';

interface Iprops {
setLockDuration: React.Dispatch<React.SetStateAction<string>>;
Expand Down
Loading

0 comments on commit d7ba5a0

Please sign in to comment.