Skip to content

Commit

Permalink
Merge pull request #34 from GeneralMagicio/feat/header_responsiveness
Browse files Browse the repository at this point in the history
Fix: ranking page UI update & lock/unlock logic
  • Loading branch information
mmahdigh authored Oct 23, 2024
2 parents 6d3ec5f + 43e1011 commit 175d6fd
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 48 deletions.
21 changes: 15 additions & 6 deletions app/allocation/[category]/components/RankingRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ const RankingRow: FC<IRankingRowProps> = ({
};

return (
<tr className="flex w-full items-center justify-around border-b border-gray-200 bg-gray-50">
<tr
className={`flex w-full items-center justify-around rounded-lg border border-gray-200 ${
locked && 'bg-gray-100'
}`}
>
<td className="pb-8 pl-4 pt-4">
<Checkbox
checked={selected}
Expand Down Expand Up @@ -64,7 +68,11 @@ const RankingRow: FC<IRankingRowProps> = ({
</div>
</td>
<td className="pb-8 pl-4 pt-4">
<div className="flex items-center justify-center rounded-md border border-gray-200 bg-gray-50 px-4 py-2">
<div
className={`flex items-center justify-center rounded-md border border-gray-200 px-4 py-2 ${
locked && 'bg-gray-100'
}`}
>
<p className="text-gray-700">{index + 1}</p>
</div>
</td>
Expand All @@ -79,9 +87,12 @@ const RankingRow: FC<IRankingRowProps> = ({
values?.floatValue ? values.floatValue / 100 : 0
);
}}
className="w-24 rounded-md border border-gray-200 bg-gray-50 px-4 py-2 text-center focus:outline-none focus:ring-1"
className={`w-24 rounded-md border border-gray-200 px-4 py-2 text-center focus:outline-none focus:ring-1 ${
locked && 'bg-gray-100'
}`}
placeholder="0.00%"
isAllowed={values => handleAllowdValue(values)}
disabled={locked}
/>
<span className="absolute bottom-2 right-7 text-xs text-gray-400">
{formatBudget(budget)}
Expand All @@ -91,9 +102,7 @@ const RankingRow: FC<IRankingRowProps> = ({
<button
className={`flex items-center justify-center rounded-md border p-2
${
locked
? 'rounded-md border-[#232634] bg-[#232634]'
: 'border-gray-50'
locked ? 'rounded-md border-[#232634] bg-[#232634]' : 'border-gray-50'
}`}
onClick={() => onLock(project.projectId)}
>
Expand Down
96 changes: 90 additions & 6 deletions app/allocation/[category]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '../../comparison/utils/helpers';
import { Checkbox } from '@/app/utils/Checkbox';
import { LockIcon } from '@/public/assets/icon-components/Lock';
import { UnlockIcon } from '@/public/assets/icon-components/Unlock';
import NotFoundComponent from '@/app/components/404';
import {
useProjectsRankingByCategoryId,
Expand Down Expand Up @@ -51,6 +52,8 @@ const RankingPage = () => {
const [rankingArray, setRankingArray] = useState<IProjectRankingObj[]>([]);
const [totalShareError, setTotalShareError] = useState<string | null>(null);
const [lockedItems, setLockedItems] = useState<number[]>([]);
const [isLocked, setIsLocked] = useState(false);
const [isUnlocked, setIsUnlocked] = useState(false);

const { data: categoryRankings } = useCategoryRankings();
const { data: ranking, isLoading } = useProjectsRankingByCategoryId(category);
Expand Down Expand Up @@ -89,6 +92,30 @@ const RankingPage = () => {
}
};

const lockSelection = () => {
if (!projects) return;

const lockedProjects = checkedItems.filter(
checkedId => !lockedItems.includes(checkedId)
);

setLockedItems([...lockedItems, ...lockedProjects]);
setCheckedItems([]);
};

const unlockSelection = () => {
if (!projects) return;

const unlockedProjects = checkedItems.filter(checkedId =>
lockedItems.includes(checkedId)
);

setLockedItems(
lockedItems.filter(lockedId => !unlockedProjects.includes(lockedId))
);
setCheckedItems([]);
};

const selectItem = (id: number) => {
if (checkedItems.includes(id)) {
setCheckedItems(checkedItems.filter(checkedId => checkedId !== id));
Expand Down Expand Up @@ -134,6 +161,40 @@ const RankingPage = () => {
updateProjectRanking();
};

useEffect(() => {
if (!projects || projects.length === 0) {
setIsLocked(false);
setIsUnlocked(true);
return;
}

const allLocked = lockedItems.length === projects.length;
const noneLocked = lockedItems.length === 0;
const checkedLocked = checkedItems.every(id => lockedItems.includes(id));
const checkedUnlocked = checkedItems.every(
id => !lockedItems.includes(id)
);
const someLocked = checkedItems.some(id => lockedItems.includes(id));
const someUnlocked = checkedItems.some(id => !lockedItems.includes(id));

if (allLocked || checkedLocked) {
setIsLocked(true);
setIsUnlocked(false);
}
else if (noneLocked || checkedUnlocked) {
setIsLocked(false);
setIsUnlocked(true);
}
else if (someLocked || someUnlocked) {
setIsLocked(true);
setIsUnlocked(true);
}
else {
setIsLocked(false);
setIsUnlocked(false);
}
}, [projects, lockedItems, checkedItems]);

useEffect(() => {
if (ranking) setProjects(ranking?.ranking);
}, [ranking]);
Expand Down Expand Up @@ -184,15 +245,38 @@ const RankingPage = () => {
items selected
</p>
</div>
<div className="h-6 border-r border-gray-200"></div>
<button className="flex items-center justify-center gap-2">
<LockIcon />
<p className="text-sm text-gray-600">Lock allocation</p>
</button>
{projects?.length && checkedItems.length > 0 && (
<>
<div className="h-6 border-r border-gray-200" />
{isLocked && (
<button
className="flex items-center justify-center gap-2"
onClick={unlockSelection}
>
<UnlockIcon />
<p className="text-sm text-gray-600">Unlock selection</p>
</button>
)}
{isLocked && isUnlocked && (
<div className="h-6 border-r border-gray-200" />
)}
{isUnlocked && (
<button
className="flex items-center justify-center gap-2"
onClick={lockSelection}
>
<LockIcon />
<p className="text-sm text-gray-600">Lock selection</p>
</button>
)}
</>
)}
</div>
<div className="flex gap-4">
<p className="text-sm font-medium text-gray-400">
0 items locked
{lockedItems.length}
{' '}
items locked
</p>
</div>
</div>
Expand Down
2 changes: 2 additions & 0 deletions app/allocation/components/EOA/EmailLoginModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ const EmailLoginModal = ({ closeModal, selectedCategoryId }: TEmailLoginModalPro
setOAuthData={setOAuthData}
sendOTP={sendOTP}
setStep={setStep}
closeModal={closeModal}
/>
)
: (
Expand All @@ -186,6 +187,7 @@ const EmailLoginModal = ({ closeModal, selectedCategoryId }: TEmailLoginModalPro
setEoaWallet={setEoaWallet}
setStep={setStep}
resendOTP={sendOTP}
closeModal={closeModal}
/>
)}
</div>
Expand Down
44 changes: 30 additions & 14 deletions app/allocation/components/EOA/MethodSelection.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import React, { FC, FormEvent } from 'react';
import Image from 'next/image';
import { Wallet } from 'thirdweb/wallets';
import { useConnect } from 'thirdweb/react';
import {
createSmartWalletFromEOA,
createSocialEoa,
Strategy,
} from '@/app/lib/third-web/methods';
import { TOTPData, TOAuthData, Step } from './EmailLoginModal';
import { InfoIcon } from '@/public/assets/icon-components/Info';
import StorageLabel from '@/app/lib/localStorage';

interface IMethodSelectionProps {
pickedMethod: Strategy | 'email' | null
Expand All @@ -19,6 +21,7 @@ interface IMethodSelectionProps {
setOtpData: (data: TOTPData) => void
sendOTP: () => void
setStep: (step: Step) => void
closeModal: () => void
}

export const MethodSelection: FC<IMethodSelectionProps> = ({
Expand All @@ -31,7 +34,10 @@ export const MethodSelection: FC<IMethodSelectionProps> = ({
setOtpData,
sendOTP,
setStep,
closeModal,
}) => {
const { connect } = useConnect();

const handleOAuthConnect = (strategy: Strategy) => async () => {
try {
setPickedMethod(strategy);
Expand All @@ -42,20 +48,30 @@ export const MethodSelection: FC<IMethodSelectionProps> = ({
if (!account) throw new Error(`Unable to create a ${strategy} EOA`);

const smartWallet = await createSmartWalletFromEOA(account);
console.log('Connected EOA wallet ==> ', smartWallet);
setEoaWallet(smartWallet);
setOAuthData({ ...oAuthData, loading: false });
setStep(Step.CONNECT_EOA);
setPickedMethod(null);

const personalWalletId = localStorage.getItem(
StorageLabel.LAST_CONNECT_PERSONAL_WALLET_ID
);

if (!personalWalletId) {
setStep(Step.CONNECT_EOA);
setPickedMethod(null);
}
else {
console.log('Connecting to smart wallet');
connect(smartWallet);
closeModal();
}
}
catch (error: any) {
if (error.message === 'User closed login window') dismissOAuthError();
else
setOAuthData({
...oAuthData,
loading: true,
error: 'There was a problem connecting to your Google account',
});
console.error(error);
setOAuthData({
...oAuthData,
loading: true,
error: 'There was a problem connecting to your Google account',
});
}
};

Expand Down Expand Up @@ -137,7 +153,7 @@ export const MethodSelection: FC<IMethodSelectionProps> = ({
)
: (
<button
className="my-4 flex w-full items-center justify-center gap-2 rounded-lg border border-gray-200 px-4 py-2 font-semibold text-gray-600"
className="my-4 flex w-full items-center justify-center gap-2 rounded-lg border border-gray-200 px-4 py-2 font-semibold text-gray-600 shadow-sm"
onClick={handleOAuthConnect(Strategy.Google)}
>
<Image
Expand Down Expand Up @@ -173,7 +189,7 @@ export const MethodSelection: FC<IMethodSelectionProps> = ({
onChange={handleEmailChange}
onBlur={handleEmailBlur}
placeholder="Enter your email"
className={`w-full rounded-lg border px-4 py-2 placeholder:text-gray-400
className={`w-full rounded-lg border px-4 py-2 placeholder:text-gray-500
${otpData.emailError ? 'border-red-500' : 'border-gray-200'}
focus:outline-none ${
otpData.email && otpData.emailError
Expand All @@ -195,9 +211,9 @@ export const MethodSelection: FC<IMethodSelectionProps> = ({
)}
</div>
<button
className={`w-full rounded-lg border px-4 py-2 font-semibold ${
className={`w-full rounded-lg border px-4 py-2 text-sm font-semibold shadow-sm ${
!otpData.email || otpData.emailError
? 'bg-gray-300 text-gray-500'
? 'text-gray-500'
: 'bg-primary text-white'
} transition duration-300`}
onClick={sendOTP}
Expand Down
Loading

0 comments on commit 175d6fd

Please sign in to comment.