Skip to content
Merged
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
6 changes: 4 additions & 2 deletions apps/frontend/app/(addFunds)/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { logos } from '@/assets';
import { CopyIconButton, DividerX, Dropdown, PrimaryButton } from '@/components';
import { useNetwork, useWallet } from '@/hooks';
import { useFilter, useNetwork, useWallet } from '@/hooks';
import cn from 'clsx';
import { router } from 'expo-router';
import { useMemo, useState } from 'react';
Expand All @@ -10,8 +10,10 @@ import { SafeAreaView } from 'react-native-safe-area-context';

const Deposit = () => {
const isDark = useColorScheme() === 'dark';

const { deposit } = useWallet();
const { networkFilterItems, getNetworkById } = useNetwork();
const { getNetworkById } = useNetwork();
const { networkFilterItems } = useFilter();

const [network, setNetwork] = useState<FilterItem>(networkFilterItems[0]);

Expand Down
3 changes: 2 additions & 1 deletion apps/frontend/app/(auth)/(signup)/info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ const SignUpInfo = () => {
disabled={isLoading}
onChangeText={(value) => setPassword(value)}
/>

<InputField
label={Strings.signupInfo.CONFIRM_PASSWORD_LABEL}
secureTextEntry
Expand All @@ -120,7 +121,7 @@ const SignUpInfo = () => {
onChangeText={(value) => setConfirmPassword(value)}
/>

<View className='mt-8'>
<View className='mt-4'>
<PrimaryButton title={Strings.signupInfo.BUTTON_LABEL} isLoading={isLoading} onPress={submitForm} />
</View>
</View>
Expand Down
126 changes: 72 additions & 54 deletions apps/frontend/app/(p2p)/(advert)/(post)/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,37 @@
import { Dropdown, PrimaryButton, StepperInput, ToggleButton } from '@/components';
import { Strings } from '@/constants';
import { useAds, useCrypto, useFiat, usePriceTypes } from '@/hooks';
import { useAds, useFilter, usePriceTypes } from '@/hooks';
import { priceIndex } from '@/models';
import { capitalizeWords } from '@/utils';
import { router } from 'expo-router';
import { useCallback, useState } from 'react';
import { Text, View } from 'react-native';
import { useCallback, useEffect, useState } from 'react';
import { View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';

const PostAdvert = () => {
const { adTypeFilterItems } = useAds();
const { priceTypeFilterItems, getPriceRangeById } = usePriceTypes();
const { cryptoNameFilterItemsStrict, getCryptoNameFilterItemById } = useCrypto();
const { fiatSymbolFilterItemsStrict } = useFiat();
const [selectedFiat, setSelectedFiat] = useState<FilterItem>(fiatSymbolFilterItemsStrict[0]);

const [adType, setAdType] = useState<FilterItem>(adTypeFilterItems[0]);
const [priceType, setpriceType] = useState<FilterItem>(priceTypeFilterItems[0]);
const [selectedCrypto, setSelectedCrypto] = useState<FilterItem>();
const { newAd } = useAds();
const { getPriceRangeById } = usePriceTypes();
const {
adTypeFilterItems: adTypes,
cryptoNameFilterItemsStrict: cryptos,
fiatSymbolFilterItemsStrict: fiats,
priceTypeFilterItems: priceTypes,
getFilterItemById,
} = useFilter();

const [formData, setFormData] = useState<AdFormData>(newAd);
const [priceIndices, setPriceIndices] = useState<Record<string, number>>(priceIndex);

const adType = getFilterItemById(adTypes, formData.type) ?? adTypes[0];
const selectedCrypto = getFilterItemById(cryptos, formData.cryptoId);
const selectedFiat = getFilterItemById(fiats, formData.countryId) ?? fiats[0];
const priceType = getFilterItemById(priceTypes, formData.priceType) ?? priceTypes[0];
const currentIndex = priceIndices[priceType.id];

const updateForm = (key: keyof AdFormData, val: any) => {
setFormData((prev) => ({ ...prev, [key]: val }));
};

const handlePriceChange = useCallback(
(increment: boolean) => {
setPriceIndices((prev) => ({
Expand All @@ -33,87 +44,94 @@ const PostAdvert = () => {

const handleCreateAdvert = async () => {
if (!selectedCrypto) {
// Show error - no crypto selected
return;
}

const advertData = {
type: JSON.stringify(adType.label),
priceType: JSON.stringify(priceType.label),
selectedCrypto: JSON.stringify(selectedCrypto.id.toUpperCase()),
selectedFiat: selectedFiat ? JSON.stringify(selectedFiat.label) : undefined,
};

router.push({
pathname: '/(p2p)/(advert)/(post)/info',
params: advertData,
params: { formData: JSON.stringify(formData) },
});

try {
// we will call API to create the advert
console.log('Creating advert:', advertData);
} catch (error) {
console.error('Error creating advert:', error);
}
};

useEffect(() => {
setFormData((prev) => ({
...prev,
cryptoId: selectedCrypto?.id ?? '',
countryId: selectedFiat?.id ?? '',
type: adType.id,
priceType: priceType.id,
priceTypeValue: getPriceRangeById(priceType.id)[priceIndices[priceType.id]],
}));
}, []);

useEffect(() => {
updateForm('priceTypeValue', getPriceRangeById(priceType.id)[priceIndices[priceType.id]]);
}, [priceIndices]);

return (
<SafeAreaView className='screen-wrapper' edges={['bottom']}>
<View className='content-wrapper'>
<Text className='font-clashDisplay text-sm text-label dark:text-label-dark'>
{Strings.postAd.AD_TYPE_LABEL}
</Text>
<View className='content-wrapper form-group mt-4'>
<ToggleButton
title={Strings.postAd.AD_TYPE_LABEL}
value={adType}
items={[adTypeFilterItems[0], adTypeFilterItems[1]]}
items={[adTypes[0], adTypes[1]]}
activeButtonColors={{
[adTypeFilterItems[0].id]: 'bg-primary',
[adTypeFilterItems[1].id]: 'bg-error-500',
[adTypes[0].id]: 'bg-primary',
[adTypes[1].id]: 'bg-error-500',
}}
activeLabelColors={{
[adTypeFilterItems[0].id]: 'text-base-dark',
[adTypeFilterItems[1].id]: 'text-base-white',
[adTypes[0].id]: 'text-base-dark',
[adTypes[1].id]: 'text-base-white',
}}
wrapperStyle='w-full h-10'
onChange={(val) => setAdType(val)}
onChange={(val) => updateForm('type', val.id)}
/>

<Dropdown
title='Select Cryptocurrency'
items={cryptoNameFilterItemsStrict}
items={cryptos}
value={selectedCrypto}
onSelect={(crypto) => setSelectedCrypto(getCryptoNameFilterItemById(crypto.id)!)}
onSelect={(crypto) => updateForm('cryptoId', crypto.id)}
/>

<Dropdown
title='Select Fiat'
items={fiatSymbolFilterItemsStrict}
items={fiats}
value={selectedFiat}
onSelect={(fiat) => setSelectedFiat(fiat)}
onSelect={(fiat) => updateForm('countryId', fiat.id)}
/>
<Text className='font-clashDisplay text-sm text-label dark:text-label-dark'>
{Strings.postAd.PRICE_SETTING}
</Text>

<ToggleButton
title={Strings.postAd.PRICE_SETTING}
value={priceType}
items={[priceTypeFilterItems[0], priceTypeFilterItems[1]]}
items={[priceTypes[0], priceTypes[1]]}
activeButtonColors={{
[priceTypeFilterItems[0].id]: 'bg-card-info',
[priceTypeFilterItems[1].id]: 'bg-card-info',
[priceTypes[0].id]: 'bg-base-white dark:bg-card-info',
[priceTypes[1].id]: 'bg-base-white dark:bg-card-info',
}}
activeLabelColors={{
[priceTypeFilterItems[0].id]: 'text-base-dark',
[priceTypeFilterItems[1].id]: 'text-base-dark',
[priceTypes[0].id]: 'text-title',
[priceTypes[1].id]: 'text-title',
}}
wrapperStyle='w-full h-10'
onChange={(val) => setpriceType(val)}
onChange={(val) =>
setFormData((prev) => ({
...prev,
priceType: val.id,
priceTypeValue: getPriceRangeById(val.id)[priceIndices[val.id]],
}))
}
/>

<StepperInput
index={currentIndex}
items={getPriceRangeById(priceType.id)}
label={capitalizeWords(priceType.label)}
onIncrement={() => handlePriceChange(true)}
onDecrement={() => handlePriceChange(false)}
index={currentIndex}
items={getPriceRangeById(priceType.id)}
/>
<View className='mt-8'>

<View className='mt-4'>
<PrimaryButton title={Strings.postAd.BUTTON_NEXT_LABEL} isLoading={false} onPress={handleCreateAdvert} />
</View>
</View>
Expand Down
120 changes: 76 additions & 44 deletions apps/frontend/app/(p2p)/(advert)/(post)/info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ import {
} from '@/components';
import { AlertStrings, Strings } from '@/constants';
import { usePaymentTimeLimits, usePayMethod, usePayMethodType } from '@/hooks';
import cn from 'clsx';
import { router, useLocalSearchParams } from 'expo-router';
import { useState } from 'react';
import { useEffect, useState } from 'react';
import {
Alert,
Image,
Keyboard,
KeyboardAvoidingView,
Platform,
Expand Down Expand Up @@ -74,40 +76,54 @@ const PostAdvertInfo = () => {
setSelectedPayMethods((prev) => sortByOriginal(prev.filter((item) => item !== id)));
};

useEffect(() => {
// To Parse: JSON.parse(params.formData as string) as AdFormData

console.log(
params.formData ? JSON.stringify(JSON.parse(params.formData as string) as AdFormData, null, 2) : 'no form data',
);
}, []);

return (
<SafeAreaView className='screen-wrapper' edges={['bottom']}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
<ScrollView keyboardShouldPersistTaps='handled'>
<View className='content-wrapper pt-6'>
<SecondaryInputField
label='Total Amount'
secondarylabel={receivedCrypto}
value={totalAmount}
onChangeText={setTotalAmount}
keyboardType='numeric'
/>
<View className='mt-4 flex-row items-end gap-4'>
<View style={{ flex: 1 }}>
<SecondaryInputField
label='Order Limit'
secondarylabel={receivedFiat}
value={orderLimitFrom}
onChangeText={setOrderLimitFrom}
keyboardType='numeric'
/>
</View>
<View className='flex-1'>
<SecondaryInputField
label=''
secondarylabel={receivedFiat}
value={orderLimitTo}
onChangeText={setOrderLimitTo}
keyboardType='numeric'
/>
<View className='content-wrapper form-group mt-4'>
<View className='gap-y-4'>
<SecondaryInputField
label='Total Amount'
secondarylabel={receivedCrypto}
value={totalAmount}
onChangeText={setTotalAmount}
keyboardType='numeric'
/>

<View className='flex-row items-end gap-x-4'>
<View className='flex-1'>
<SecondaryInputField
label='Order Limit'
secondarylabel={receivedFiat}
value={orderLimitFrom}
onChangeText={setOrderLimitFrom}
keyboardType='numeric'
/>
</View>

<View className='flex-1'>
<SecondaryInputField
label=''
secondarylabel={receivedFiat}
value={orderLimitTo}
onChangeText={setOrderLimitTo}
keyboardType='numeric'
/>
</View>
</View>
</View>
<DividerX style='my-4' />

<DividerX style={cn('my-1', isDark ? 'opacity-75' : 'opacity-25')} />

<PaymentMethodChips
selectedPayMethods={selectedPayMethods.filter((id) => getPayMethodTypeById(id))}
onRemovePayMethod={deselectPayMethod}
Expand All @@ -125,24 +141,40 @@ const PostAdvertInfo = () => {
canAddMore={selectedPayMethods.length < 3 && activeUserPayMethods.length > 0}
maxSelections={3}
/>
<DividerX style='my-4' />
<View className='flex-row items-center justify-between'>
<Text className='input-label text-title dark:text-title-dark'>Payment TimeLimit</Text>
<TouchableOpacity
onPress={() => {
Keyboard.dismiss();
openPayTimeLimitBottomSheet();
}}
>
<Text className='mt-1 font-satoshi text-sm text-label dark:text-label-dark'>
{selectedPayTimeLimitData ? selectedPayTimeLimitData.label : 'Select'}

<DividerX style={cn('my-1', isDark ? 'opacity-75' : 'opacity-25')} />

<View className='gap-y-4'>
<View className='flex-row items-center justify-between'>
<Text className='field-label'>Payment Time Limit</Text>
<TouchableOpacity
onPress={() => {
Keyboard.dismiss();
openPayTimeLimitBottomSheet();
}}
>
<View className='flex-row items-end'>
<Text className='font-satoshi text-sm text-body underline dark:text-body-dark'>
{selectedPayTimeLimitData ? selectedPayTimeLimitData.label : 'Select'}
</Text>

<Image
source={isDark ? icons.dark.arrowRight : icons.light.arrowRight}
className='size-4'
resizeMode='contain'
/>
</View>
</TouchableOpacity>
</View>

<View className='rounded-lg border border-dashed border-warning-500 bg-warning-500/10 px-3 py-4 dark:border-warning-100 dark:bg-warning-100/10'>
<Text className='font-satoshi text-sm text-label dark:text-label-dark'>
Estimated Fee - 0.876 ALGO
</Text>
</TouchableOpacity>
</View>
<View className='mt-4 rounded-lg border border-dashed border-warning-500 bg-warning-500/10 px-3 py-4 dark:border-warning-100 dark:bg-warning-100/10'>
<Text className='font-satoshi text-sm text-label dark:text-label-dark'>Estimated Fee - 0.876 ALGO</Text>
</View>
</View>
<View className='mt-8'>

<View className='mt-4'>
<PrimaryButton title={Strings.postAd.PUBLISH_AD_LABEL} isLoading={false} onPress={handleCreateAdvert} />
</View>
</View>
Expand Down
Loading