Start Trading Today
-
+
Join thousands of traders and investors on our platform. Get started with as little as $10.
-
+
By signing up, you agree to our{" "}
-
- Terms & Conditions
+
+ Legal Notice
@@ -80,5 +82,5 @@ export default function HomePage() {
- )
+ );
}
\ No newline at end of file
diff --git a/src/app/sell/[cryptoId]/page.tsx b/src/app/sell/[cryptoId]/page.tsx
new file mode 100644
index 0000000..0683167
--- /dev/null
+++ b/src/app/sell/[cryptoId]/page.tsx
@@ -0,0 +1,39 @@
+"use client"
+
+import {OfferList} from "@/components/sub/OfferList";
+import {SellForm} from "@/components/sell-form";
+
+
+interface SellCryptoPageProps {
+ params: IParams;
+}
+
+interface IParams {
+ cryptoId: string;
+}
+
+export default function SellCryptoPage({ params }: SellCryptoPageProps) {
+ return (
+
+
+ {/* Graph demande achat/you/other */}
+
+ Graph
+
+ {/* stats */}
+
+ Stats
+
+
+
+ {/* Formulaire */}
+
+ Formulaire
+
+
+ {/* Tab Liste offfres vente existante */}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/app/wallet/page.tsx b/src/app/wallet/page.tsx
index 5c30e29..b3ee94e 100644
--- a/src/app/wallet/page.tsx
+++ b/src/app/wallet/page.tsx
@@ -14,7 +14,6 @@ export default function WalletPage() {
const [isLoading, setIsLoading] = useState
(true);
const [cryptosList, setCryptosList] = useState([]);
const userContext = useContext(UserDataContext);
- //FIX the loop
useEffect(() => {
console.log(userContext?.userData);
diff --git a/src/components/auth-form.tsx b/src/components/auth-form.tsx
index 5ceac58..982e56c 100644
--- a/src/components/auth-form.tsx
+++ b/src/components/auth-form.tsx
@@ -64,6 +64,9 @@ const registerSchema = z.object({
.regex(/[0-9]/, "Password must contain at least one number.")
.regex(/[^a-zA-Z0-9]/, "Password must contain at least one special character.")
.describe("Your account password."),
+
+ promoCode: z
+ .string().max(255, "Your promotional code is too long.").optional(),
});
export function AuthForms() {
diff --git a/src/components/auto-form/utils.ts b/src/components/auto-form/utils.ts
index 4e72616..eaf3af2 100644
--- a/src/components/auto-form/utils.ts
+++ b/src/components/auto-form/utils.ts
@@ -3,7 +3,6 @@ import type { DefaultValues } from "react-hook-form";
import type { z } from "zod";
import type { FieldConfig } from "./types";
-// TODO: This should support recursive ZodEffects but TypeScript doesn't allow circular type definitions.
export type ZodObjectOrWrapped =
| z.ZodObject
| z.ZodEffects>;
diff --git a/src/components/cryptos/sell-modal.tsx b/src/components/cryptos/sell-modal.tsx
new file mode 100644
index 0000000..33dc998
--- /dev/null
+++ b/src/components/cryptos/sell-modal.tsx
@@ -0,0 +1,10 @@
+import type {Row} from "@tanstack/react-table";
+import type {ICryptoInUserWalletInfo} from "@/interfaces/crypto.interface";
+
+
+interface SellModalProps {
+ row: Row
+}
+export function SellModal({ row }: SellModalProps) {
+
+}
\ No newline at end of file
diff --git a/src/components/data-tables/wallet-table.tsx b/src/components/data-tables/wallet-table.tsx
index 931b200..6efbb8c 100644
--- a/src/components/data-tables/wallet-table.tsx
+++ b/src/components/data-tables/wallet-table.tsx
@@ -10,15 +10,11 @@ import { ViewModal } from "@/components/cryptos/view-modal";
import { Button } from "@/components/ui/button";
import { DataTable } from "@/components/ui/data-table";
import type { IUserWallet } from "@/interfaces/userdata.interface";
-import {
- type ColumnDef,
- flexRender,
- getCoreRowModel,
- useReactTable,
+import type {
+ ColumnDef,
} from "@tanstack/react-table";
import { ArrowUpDown, MoreHorizontal } from "lucide-react";
import { useRouter } from "next/navigation";
-import { useState } from "react";
interface DataTableProps {
columns: ColumnDef[];
diff --git a/src/components/header.tsx b/src/components/header.tsx
index 4da4885..e589ebe 100644
--- a/src/components/header.tsx
+++ b/src/components/header.tsx
@@ -14,8 +14,8 @@ export function Header({
"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"
}
>
-
-
+
+
{title || "Neptune"}
diff --git a/src/components/sell-form.tsx b/src/components/sell-form.tsx
new file mode 100644
index 0000000..fcd1c44
--- /dev/null
+++ b/src/components/sell-form.tsx
@@ -0,0 +1,187 @@
+"use client";
+import * as z from "zod";
+import ApiRequest from "@/services/apiRequest";
+import { toast } from "@/components/ui/use-toast";
+import * as React from "react";
+import { useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
+import { Button } from "@/components/ui/button";
+import { useEffect, useState } from "react";
+import type { IUserWalletCryptos } from "@/interfaces/crypto.interface";
+import type { IApiUserAssetsRes } from "@/interfaces/api.interface";
+import { Slider } from "@/components/ui/slider";
+import { DollarSign, Equal, X } from "lucide-react";
+import { Card } from "@/components/ui/card";
+
+export function SellForm() {
+ const [currentWallet, setCurrentWallet] = useState();
+ const [sliderValue, setSliderValue] = useState(0);
+ const [quantity, setQuantity] = useState(0);
+ const [selectedCrypto, setSelectedCrypto] = useState();
+
+ useEffect(() => {
+ async function fetchAssets() {
+ const res = await ApiRequest.authenticated.get.json("user/my-assets");
+ setCurrentWallet(res.data.UserHasCrypto);
+ }
+ fetchAssets();
+ }, []);
+
+ function getMaxSharesForCrypto(cryptoId: string) {
+ return currentWallet?.find((crypto) => crypto.Crypto.id === cryptoId)?.amount || 0;
+ }
+
+ function getCryptoValue(cryptoId: string) {
+ return currentWallet?.find((crypto) => crypto.Crypto.id === cryptoId)?.Crypto.value || 0;
+ }
+
+ function getCryptoName(cryptoId: string) {
+ return currentWallet?.find((crypto) => crypto.Crypto.id === cryptoId)?.Crypto.name || "";
+ }
+
+ const sellToUserSchema = z.object({
+ cryptoId: z.string({ required_error: "You should select a crypto from your wallet." }).uuid(),
+ amount: z.number({
+ required_error: "You should select an amount of the assets that you want to sell.",
+ }).max(sliderValue),
+ });
+
+ async function onSellToUserSubmit(data: z.infer) {
+ const res = await ApiRequest.authenticated.post.json("offer/create", {
+ id_crypto: data.cryptoId,
+ amount: data.amount,
+ });
+
+ if (res.status !== 201) {
+ toast({
+ title: "An error occurred!",
+ description: (
+
+ {JSON.stringify(res.statusText, null, 2)}
+
+ ),
+ });
+ return;
+ }
+
+ console.log(res);
+ toast({
+ title: "Transaction accepted.",
+ description: The page is going to reload.
,
+ });
+ setTimeout(() => location.reload(), 1_500);
+
+ toast({
+ title: "You submitted the following values:",
+ description: (
+
+ {JSON.stringify(data, null, 2)}
+
+ ),
+ });
+ }
+
+ const sellToUserForm = useForm>({
+ resolver: zodResolver(sellToUserSchema),
+ });
+
+ if (!currentWallet) {
+ return (
+
+
+
+ );
+ }
+
+ return (
+
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/sub/GraphSellOffer.tsx b/src/components/sub/GraphSellOffer.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/sub/OfferList.tsx b/src/components/sub/OfferList.tsx
new file mode 100644
index 0000000..72a7a66
--- /dev/null
+++ b/src/components/sub/OfferList.tsx
@@ -0,0 +1,50 @@
+import {Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
+import {ScrollArea} from "@/components/ui/scroll-area";
+import type {IAllTrades} from "@/interfaces/crypto.interface";
+import {cn} from "@/lib/utils";
+
+interface OfferListProps {
+ className?: string;
+ trades: IAllTrades;
+}
+
+interface RenderRowsProps {
+ data?: IAllTrades;
+}
+
+function RenderRows({ data }: RenderRowsProps) {
+ if (!data || data?.length === 0) return (
+ {" "}
+ {" "}
+ {"No history..."}
+ {" "}
+ );
+
+ return data.map((item, index) => (
+
+ {item.Giver.pseudo}
+ {item.Receiver.pseudo}
+ {item.Crypto.quantity}
+ ${item.Crypto.value}
+
+ ));
+}
+
+export function OfferList({ className, trades}: OfferListProps) {
+ return (
+
+ A list of recent sell offers.
+
+
+ Seller
+ Buyer
+ Crypto share amount
+ $
+
+
+
+
+
+
+
)
+}
\ No newline at end of file
diff --git a/src/interfaces/userdata.interface.ts b/src/interfaces/userdata.interface.ts
index 1575221..3d5c643 100644
--- a/src/interfaces/userdata.interface.ts
+++ b/src/interfaces/userdata.interface.ts
@@ -15,7 +15,6 @@ export interface IUserData {
dollarAvailables: number;
created_at: string;
updated_at: string;
- //TODO get on register
wallet: IUserWallet;
}