Add defaultCryptoId prop to SellForm and enhance usability

Introduced a new defaultCryptoId prop for the SellForm component to pre-select a cryptocurrency on mount. Adjusted responsive layout and usability for various components including headers, modals, and navigation links. Ensured better user feedback and message clarity for login and registration processes.
This commit is contained in:
Mathis H (Avnyr) 2024-11-24 23:50:12 +01:00
parent e3aa219389
commit b6f50dc944
Signed by: Mathis
GPG Key ID: DD9E0666A747D126
8 changed files with 76 additions and 75 deletions

View File

@ -27,18 +27,18 @@ export default function RootLayout({
<body className={"w-full min-h-screen flex flex-col items-center justify-between"}> <body className={"w-full min-h-screen flex flex-col items-center justify-between"}>
<Providers> <Providers>
<Header> <Header>
<div className={"flex flex-row flex-wrap md:flex-nowrap gap-2"}> <nav className="flex flex-row flex-wrap md:flex-nowrap gap-2">
<Button asChild variant={"light"}> <Button asChild variant="light">
<Link href={"/wallet"}><p className={"lg:text-lg"}>Wallet</p></Link> <Link href="/wallet" title={"Go to your wallet"}><p className="lg:text-lg">Wallet</p></Link>
</Button> </Button>
<Button asChild variant={"light"}> <Button asChild variant="light">
<Link href={"/dashboard"}><p className={"lg:text-lg"}>Explore cryptos</p></Link> <Link href="/dashboard" title={"Go to the crypto explorer"}><p className="lg:text-lg">Explore cryptos</p></Link>
</Button> </Button>
</div> </nav>
</Header> </Header>
{children} {children}
<Toaster /> <Toaster/>
<Footer /> <Footer/>
</Providers> </Providers>
</body> </body>
</html> </html>

View File

@ -23,6 +23,9 @@ export default function HomePage() {
<Button>Get Started</Button> <Button>Get Started</Button>
<Button variant="outline">Learn More</Button> <Button variant="outline">Learn More</Button>
</div> </div>
<p className="mx-auto max-w-[700px] text-destructive/50 md:text-lg">
This website is fictional and for demonstration purposes only.
</p>
</div> </div>
</div> </div>
</section> </section>

View File

@ -13,26 +13,11 @@ interface IParams {
} }
export default function SellCryptoPage({ params }: SellCryptoPageProps) { export default function SellCryptoPage({ params }: SellCryptoPageProps) {
console.log(params);
return ( return (
<main className="flex flex-col sm:flex-row items-center justify-center w-full h-full gap-4 sm:p-4"> <main className="flex flex-col sm:flex-row items-center justify-center w-full h-full gap-4 p-2 sm:p-4">
<section className={"w-full sm:w-1/3 h-full p-0.5 sm:p-2 flex flex-col items-center justify-center gap-4"}> <section className={"w-full lg:w-1/3 h-full p-0.5 sm:p-2 flex flex-col items-center justify-center gap-4"}>
{/* Graph demande achat/you/other */} <SellForm defaultCryptoId={params.cryptoId}/>
<div className={"w-full h-1/3 rounded bg-card text-card-foreground"}>
Graph
</div>
{/* stats */}
<div className={"w-full h-2/3 rounded bg-card text-card-foreground"}>
Stats
</div>
</section>
<section className={"w-full sm:w-2/3 h-full p-0.5 sm:p-2 flex flex-col items-center justify-center gap-4"}>
{/* Formulaire */}
<div className={"w-full h-2/3 rounded bg-card text-card-foreground p-2"}>
Formulaire
<SellForm defaultCryptoId={params.cryptoId}/>
</div>
{/* Tab Liste offfres vente existante */}
<OfferList className={"w-full h-1/3"} trades={[]}/>
</section> </section>
</main> </main>
); );

View File

@ -179,7 +179,7 @@ export function AuthForms() {
} }
//toast.custom(<ToastBox message={"Login successful ! \n You will be redirected."} type={toastType.success}/>) //toast.custom(<ToastBox message={"Login successful ! \n You will be redirected."} type={toastType.success}/>)
toast({ toast({
description: "Login successful ! \n You will be redirected.", description: "Login successful ! \n You will be redirected to the home page.",
}); });
setTimeout(() => { setTimeout(() => {
setIsLoading(false); setIsLoading(false);
@ -248,9 +248,9 @@ export function AuthForms() {
<p>Register</p> <p>Register</p>
</AutoFormSubmit> </AutoFormSubmit>
<p className="text-gray-500 text-sm"> <p className="text-gray-500 text-sm">
By submitting this form, you agree to our{" "} By submitting this form, you agree to the{" "}
<Link href="#" className="text-primary underline"> <Link title={"Go to legal page"} href="/legal" className="text-primary underline">
terms and conditions GDPR Compliance Policy & Usage Policy
</Link> </Link>
. .
</p> </p>

View File

@ -4,29 +4,27 @@ import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
import { import {
Form, Form,
FormControl, FormControl,
FormDescription,
FormField, FormField,
FormItem, FormItem,
FormLabel, FormLabel,
FormMessage, FormMessage,
} from "@/components/ui/form"; } from "@/components/ui/form";
import { import {
Select, Select,
SelectContent, SelectTrigger,
SelectItem, SelectValue,
SelectTrigger, SelectContent,
SelectValue, SelectItem,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { toast } from "@/components/ui/use-toast"; import { toast } from "@/components/ui/use-toast";
import type { IApiAllOffersRes, IApiDoTradeReq } from "@/interfaces/api.interface"; import type { IApiAllOffersRes } from "@/interfaces/api.interface";
import type { ICryptoInWalletInfo } from "@/interfaces/crypto.interface"; import type { ICryptoInWalletInfo } from "@/interfaces/crypto.interface";
import ApiRequest from "@/services/apiRequest"; import ApiRequest from "@/services/apiRequest";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
import { Ban, DollarSign, RefreshCw } from "lucide-react"; import { Ban, DollarSign, RefreshCw } from "lucide-react";
import Link from "next/link";
import * as React from "react"; import * as React from "react";
import { Dispatch, SetStateAction, useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import * as z from "zod"; import * as z from "zod";
type Props = { type Props = {
@ -43,6 +41,7 @@ export function BuyModal(props: Props) {
ApiRequest.authenticated.get ApiRequest.authenticated.get
.json<IApiAllOffersRes[]>(`offer/crypto/${props.cryptoData.id}`) .json<IApiAllOffersRes[]>(`offer/crypto/${props.cryptoData.id}`)
.then((response) => { .then((response) => {
console.debug(response)
if (response.data) {setOffersList(response.data)} if (response.data) {setOffersList(response.data)}
console.log(`Crypto ${props.cryptoData.name} -> ${response.data.length}`); console.log(`Crypto ${props.cryptoData.name} -> ${response.data.length}`);
setIsLoaded(true); setIsLoaded(true);
@ -157,7 +156,10 @@ export function BuyModal(props: Props) {
{offersList.length} {offersList.length}
</p> </p>
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="server">Buy from server</TabsTrigger> <TabsTrigger value="server">Buy from server{" "}<p
className={" ml-1 px-1 bg-primary text-primary-foreground rounded"}>
{props.cryptoData.quantity}
</p></TabsTrigger>
</TabsList> </TabsList>
<TabsContent <TabsContent
value="user" value="user"
@ -171,30 +173,28 @@ export function BuyModal(props: Props) {
<FormField <FormField
control={buyFromUserForm.control} control={buyFromUserForm.control}
name="offerId" name="offerId"
render={({ field }) => ( render={({ field }) => (
<FormItem> <FormItem>
<FormLabel>Select an offer</FormLabel> <FormLabel>Select an offer</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}> <Select defaultValue={offersList[0]?.id} onValueChange={(val) => {
<FormControl> console.log(val);
<SelectTrigger> field.onChange(val);
<SelectValue placeholder="Select an offer to purchase." /> }}>
</SelectTrigger> <SelectTrigger>
</FormControl> <SelectValue placeholder="Select an offer to purchase."/>
<SelectContent> </SelectTrigger>
{offersList.map((offer) => { <SelectContent>
if (!offer) return; {offersList.map((offer) => (
return ( <SelectItem
<SelectItem value={offer.id}
value={offer.id} key={offer.id}
key={offer.id} >{`${offer.amount}x ${offer.Crypto.name}`}</SelectItem>
>{`${offer.amount}x ${offer.Crypto.name} - ${offer.User.pseudo}`}</SelectItem> ))}
); </SelectContent>
})} </Select>
</SelectContent> <FormMessage />
</Select> </FormItem>
<FormMessage /> )}
</FormItem>
)}
/> />
<Button type="submit">Submit</Button> <Button type="submit">Submit</Button>
</form> </form>

View File

@ -13,8 +13,9 @@ import type { IUserWallet } from "@/interfaces/userdata.interface";
import type { import type {
ColumnDef, ColumnDef,
} from "@tanstack/react-table"; } from "@tanstack/react-table";
import { ArrowUpDown, MoreHorizontal } from "lucide-react"; import { ArrowUpDown, MoreHorizontal, Receipt } from "lucide-react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import Link from "next/link";
interface DataTableProps<TData, TValue> { interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[]; columns: ColumnDef<TData, TValue>[];
@ -68,8 +69,8 @@ export function WalletTable(props: Props) {
const payment = row.original; const payment = row.original;
return ( return (
<div className={"flex gap-2"}> <div>
<p className={"font-light italic text-xs"}>Soon here : Sell, History</p> <Link href={`/sell/${row.original.id}`} className={"flex w-fit gap-2 p-2 justify-center items-center rounded hover:bg-card"}><Receipt /> <p className={"hidden sm:block"}>Sell for USD</p></Link>
</div> </div>
); );
}, },

View File

@ -11,7 +11,7 @@ export function Header({
return ( return (
<header <header
className={ className={
"flex flex-col md:flex-row justify-between items-center w-full p-1 md:px-3 md:py-2 pb-2 border-b-2" "flex flex-col md:flex-row justify-between items-center w-full p-1 md:px-3 gap-2 md:py-2 pb-2 border-b-2"
} }
> >
<Link title={"Return to home page"} href={"/"} className={"flex flex-row justify-center md:justify-start items-center w-fit gap-2"}> <Link title={"Return to home page"} href={"/"} className={"flex flex-row justify-center md:justify-start items-center w-fit gap-2"}>

View File

@ -15,7 +15,11 @@ import { Slider } from "@/components/ui/slider";
import { DollarSign, Equal, X } from "lucide-react"; import { DollarSign, Equal, X } from "lucide-react";
import { Card } from "@/components/ui/card"; import { Card } from "@/components/ui/card";
export function SellForm() { interface SellFormProps {
defaultCryptoId?: string;
}
export function SellForm({ defaultCryptoId }: SellFormProps) {
const [currentWallet, setCurrentWallet] = useState<IUserWalletCryptos[]>(); const [currentWallet, setCurrentWallet] = useState<IUserWalletCryptos[]>();
const [sliderValue, setSliderValue] = useState(0); const [sliderValue, setSliderValue] = useState(0);
const [quantity, setQuantity] = useState(0); const [quantity, setQuantity] = useState(0);
@ -29,6 +33,15 @@ export function SellForm() {
fetchAssets(); fetchAssets();
}, []); }, []);
useEffect(() => {
if (defaultCryptoId) {
const maxShares = getMaxSharesForCrypto(defaultCryptoId);
setSliderValue(maxShares);
setSelectedCrypto(defaultCryptoId);
setQuantity(1);
}
}, []);
function getMaxSharesForCrypto(cryptoId: string) { function getMaxSharesForCrypto(cryptoId: string) {
return currentWallet?.find((crypto) => crypto.Crypto.id === cryptoId)?.amount || 0; return currentWallet?.find((crypto) => crypto.Crypto.id === cryptoId)?.amount || 0;
} }
@ -116,6 +129,7 @@ export function SellForm() {
> >
<FormLabel>Sell shares of your wallet</FormLabel> <FormLabel>Sell shares of your wallet</FormLabel>
<Select <Select
defaultValue={defaultCryptoId}
onValueChange={(val) => { onValueChange={(val) => {
const maxShares = getMaxSharesForCrypto(val); const maxShares = getMaxSharesForCrypto(val);
setSliderValue(maxShares); setSliderValue(maxShares);
@ -130,11 +144,9 @@ export function SellForm() {
</SelectTrigger> </SelectTrigger>
</FormControl> </FormControl>
<SelectContent> <SelectContent>
{currentWallet?.map((crypto) => ( {currentWallet?.map((crypto) => (<SelectItem value={crypto.Crypto.id} key={crypto.Crypto.id}>
<SelectItem value={crypto.Crypto.id} key={crypto.Crypto.id}> {`${crypto.amount}x ${crypto.Crypto.name} - ${Math.round(crypto.Crypto.value)}$/u`}
{`${crypto.amount}x ${crypto.Crypto.name} - ${crypto.Crypto.value}$/u`} </SelectItem>))}
</SelectItem>
))}
</SelectContent> </SelectContent>
</Select> </Select>
<FormMessage /> <FormMessage />