diff --git a/package-lock.json b/package-lock.json index d8b20f7c..9c67fa5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -29,6 +29,7 @@ "@tailwindcss/typography": "^0.5.10", "@tanstack/react-query": "^4.29.7", "@tanstack/react-query-devtools": "^4.32.6", + "@types/lodash": "^4.17.7", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", "astro": "^4.0.7", @@ -39,6 +40,7 @@ "clsx": "^2.0.0", "fuse.js": "^6.6.2", "hastscript": "^8.0.0", + "lodash": "^4.17.21", "lucide-react": "^0.279.0", "react": "^18.0.0", "react-dom": "^18.0.0", @@ -3025,6 +3027,11 @@ "hoist-non-react-statics": "^3.3.0" } }, + "node_modules/@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" + }, "node_modules/@types/mdast": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.2.tgz", @@ -5678,6 +5685,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "node_modules/lodash.castarray": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", diff --git a/package.json b/package.json index c7d8a260..e007b98b 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@tailwindcss/typography": "^0.5.10", "@tanstack/react-query": "^4.29.7", "@tanstack/react-query-devtools": "^4.32.6", + "@types/lodash": "^4.17.7", "@types/react": "^18.0.21", "@types/react-dom": "^18.0.6", "astro": "^4.0.7", @@ -41,6 +42,7 @@ "clsx": "^2.0.0", "fuse.js": "^6.6.2", "hastscript": "^8.0.0", + "lodash": "^4.17.21", "lucide-react": "^0.279.0", "react": "^18.0.0", "react-dom": "^18.0.0", diff --git a/src/assets/akash-logo-primary.svg b/src/assets/akash-logo-primary.svg new file mode 100644 index 00000000..5e6df930 --- /dev/null +++ b/src/assets/akash-logo-primary.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/assets/aws-logo.svg b/src/assets/aws-logo.svg new file mode 100644 index 00000000..a147f150 --- /dev/null +++ b/src/assets/aws-logo.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/assets/azure-logo.svg b/src/assets/azure-logo.svg new file mode 100644 index 00000000..55445f1d --- /dev/null +++ b/src/assets/azure-logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/cpu-brand.svg b/src/assets/cpu-brand.svg new file mode 100644 index 00000000..6fbdcb79 --- /dev/null +++ b/src/assets/cpu-brand.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/endpoint-brand.svg b/src/assets/endpoint-brand.svg new file mode 100644 index 00000000..df50e97f --- /dev/null +++ b/src/assets/endpoint-brand.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/gcp-logo.svg b/src/assets/gcp-logo.svg new file mode 100644 index 00000000..9d3ceae0 --- /dev/null +++ b/src/assets/gcp-logo.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/gpu-brand.svg b/src/assets/gpu-brand.svg new file mode 100644 index 00000000..d4f58777 --- /dev/null +++ b/src/assets/gpu-brand.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/arrow-up-right.svg b/src/assets/icons/arrow-up-right.svg new file mode 100644 index 00000000..e0fc4041 --- /dev/null +++ b/src/assets/icons/arrow-up-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/ips-brand.svg b/src/assets/ips-brand.svg new file mode 100644 index 00000000..14d45621 --- /dev/null +++ b/src/assets/ips-brand.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/memory-brand.svg b/src/assets/memory-brand.svg new file mode 100644 index 00000000..6fbdcb79 --- /dev/null +++ b/src/assets/memory-brand.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/storage-brand.svg b/src/assets/storage-brand.svg new file mode 100644 index 00000000..d4f58777 --- /dev/null +++ b/src/assets/storage-brand.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/header/hamburger-menu.tsx b/src/components/header/hamburger-menu.tsx index 3bbd1289..4a44a2b1 100644 --- a/src/components/header/hamburger-menu.tsx +++ b/src/components/header/hamburger-menu.tsx @@ -34,7 +34,7 @@ const navigation = [ { name: "Community", href: "/community/akash-insiders/" }, { name: "Blog", href: "/blog" }, { name: "Docs", href: "/docs" }, - { name: "GPU Pricing", href: "/gpus" }, + { name: "Pricing & Earnings", href: "/pricing/gpus" }, ]; export default function HamburgerMenu({ diff --git a/src/components/header/header.astro b/src/components/header/header.astro index decee8ee..e97ac840 100644 --- a/src/components/header/header.astro +++ b/src/components/header/header.astro @@ -74,7 +74,7 @@ ${disableSticky ? "" : "sticky top-0 z-[30]"} Blog Docs - GPU Pricing + Pricing & Earnings diff --git a/src/components/pricing-page/gpus/checkbox.tsx b/src/components/pricing-page/gpus/checkbox.tsx new file mode 100644 index 00000000..d6255399 --- /dev/null +++ b/src/components/pricing-page/gpus/checkbox.tsx @@ -0,0 +1,55 @@ +import clsx from "clsx"; +import React, { type InputHTMLAttributes } from "react"; + +interface InputProps extends InputHTMLAttributes { + label: string; +} + +const CheckBox = (props: InputProps) => { + const ref = React.useRef(null); + + return ( +
+ +
+ + ); +}; + +const CustomHoverCard = ({ model }: { model: Gpus["models"][0] }) => { + return ( +
+
+ {/*
*/} + Min: {price(model?.price?.min)} +
+
+
+ + +

+ + Avg: + + + {price(model?.price?.weightedAverage)} + +

+ +
+ +
+
+

+ {model?.providerAvailability?.available || 0} providers{" "} +
+ offering this model +

+
+
+

Max:

+
+ {price(model?.price?.max)}/hr +
+
+
+
+

Min:

+
+ {price(model?.price?.min)}/hr +
+
+
+
+
+

Avg:

+
+ {price(model?.price?.weightedAverage)}/hr +
+
+
+
+
+
+
+ + Rent Now + +
+
+ Max: {price(model?.price?.max)} + {/*
*/} +
+
+ ); +}; diff --git a/src/components/pricing-page/gpus/nav.tsx b/src/components/pricing-page/gpus/nav.tsx new file mode 100644 index 00000000..e64702f6 --- /dev/null +++ b/src/components/pricing-page/gpus/nav.tsx @@ -0,0 +1,44 @@ +import Tag from "./tag"; + +const Nav = ({ pathName }: any) => { + return ( + <> +
+
+ + Showcase + +
+ +
+ + Tools + +
+ +
+ + Deployed on Akash + +
+ +
+ + Akash Providers + +
+
+ + ); +}; + +export default Nav; diff --git a/src/components/pricing-page/gpus/sort.tsx b/src/components/pricing-page/gpus/sort.tsx new file mode 100644 index 00000000..465fe6c8 --- /dev/null +++ b/src/components/pricing-page/gpus/sort.tsx @@ -0,0 +1,138 @@ +import { Fragment, useEffect, useState } from "react"; +import { Listbox, Transition } from "@headlessui/react"; +import { CheckIcon, ChevronDownIcon } from "@heroicons/react/20/solid"; +import { clsx as classNames } from "clsx"; +import type { Gpus } from "./gpu-table"; +import type { Filters } from "./filter"; +const publishingOptions = [ + { title: "Availability" }, + { title: "Lowest Price" }, + { title: "Highest Price" }, +]; + +export default function Sort({ + setFilteredData, + res, + filters, +}: { + setFilteredData: React.Dispatch>; + res?: Gpus; + filters: Filters; +}) { + const [selected, setSelected] = useState(publishingOptions[0]); + + const onTop = () => { + const onTop = ["h100", "a100"]; + const filtered = res?.models + ?.filter((model) => onTop?.includes(model?.model)) + .sort((a, b) => onTop.indexOf(a?.model) - onTop.indexOf(b?.model)); + const rest = res?.models + ?.filter((model) => !onTop?.includes(model.model)) + .sort((a, b) => b?.availability?.available - a?.availability?.available); + + return [...(filtered ?? []), ...(rest ?? [])]?.filter( + (model) => model !== undefined, + ); + }; + + useEffect(() => { + const sortData = (sortType: string) => { + switch (sortType) { + case "Availability": + filters.modal.length > 0 || + filters.ram.length > 0 || + filters.interface.length > 0 + ? setFilteredData((prev) => + [...prev].sort( + (a, b) => b.availability.available - a.availability.available, + ), + ) + : setFilteredData(onTop()); + break; + case "Lowest Price": + setFilteredData((prev) => + [...prev].sort((a, b) => { + const aMed = a.price ? a.price.med : 0; + const bMed = b.price ? b.price.med : 0; + return aMed - bMed; + }), + ); + + break; + case "Highest Price": + setFilteredData((prev) => + [...prev].sort((a, b) => { + const aMed = a.price ? a.price.med : 0; + const bMed = b.price ? b.price.med : 0; + return bMed - aMed; + }), + ); + break; + default: + break; + } + }; + sortData(selected.title); + }, [selected, res?.models, setFilteredData, filters]); + + return ( + + {({ open }) => ( + <> +
+ + {selected.title} + + + + + {publishingOptions.map((option) => ( + + classNames( + active ? "bg-primary text-white" : "text-textGray", + "relative cursor-default select-none py-2 pl-8 pr-4", + ) + } + value={option} + > + {({ selected, active }) => ( + <> + + {option.title} + + + {selected ? ( + + + ) : null} + + )} + + ))} + + +
+ + )} +
+ ); +} diff --git a/src/components/pricing-page/gpus/tag.tsx b/src/components/pricing-page/gpus/tag.tsx new file mode 100644 index 00000000..4e0c4a77 --- /dev/null +++ b/src/components/pricing-page/gpus/tag.tsx @@ -0,0 +1,15 @@ +const Tag = ({ children, className, href, active }: any) => { + return ( + + {children} + + ); +}; + +export default Tag; diff --git a/src/components/pricing-page/pricing-navbar.astro b/src/components/pricing-page/pricing-navbar.astro new file mode 100644 index 00000000..3a84c469 --- /dev/null +++ b/src/components/pricing-page/pricing-navbar.astro @@ -0,0 +1,33 @@ +--- +import Tag from "../ui/pricing-tag.astro"; +const { pathName } = Astro.props; +--- + + diff --git a/src/components/pricing-page/provider/month-earning.tsx b/src/components/pricing-page/provider/month-earning.tsx new file mode 100644 index 00000000..932bbad4 --- /dev/null +++ b/src/components/pricing-page/provider/month-earning.tsx @@ -0,0 +1,17 @@ +type MonthEarning = { + size?: 20 | 24; + className?: string; + value?: string; + title?: string; +} + +const MonthEarning = ({ size, className, value, title }: MonthEarning) => { + return ( +
+

{title}

+

{value}/month

+
+ ); +}; + +export default MonthEarning; diff --git a/src/components/pricing-page/provider/pricing-unit.tsx b/src/components/pricing-page/provider/pricing-unit.tsx new file mode 100644 index 00000000..78ff0fd8 --- /dev/null +++ b/src/components/pricing-page/provider/pricing-unit.tsx @@ -0,0 +1,51 @@ +import React, { useEffect, useState } from "react"; +import ProgressBar from "./progress-bar"; + +type PricingUnitProps = { + progress: number; + setProgress: React.Dispatch>; + max: number; + title: string; + content: string; + position?: string; +} + +function PricingUnit({ title, content, position, progress, setProgress, max }: PricingUnitProps) { + + const handleInputChange = (event: React.ChangeEvent) => { + setProgress(Number(event.target.value)); + }; + + return ( +
+
+
+

+ {title} +

+

+ {content} +

+
+
+ {progress}{title === 'CPU' ? '%' : ''} +
+
+
+ + +
+
+ ); +} + +export default PricingUnit; diff --git a/src/components/pricing-page/provider/progress-bar.tsx b/src/components/pricing-page/provider/progress-bar.tsx new file mode 100644 index 00000000..6bb0c553 --- /dev/null +++ b/src/components/pricing-page/provider/progress-bar.tsx @@ -0,0 +1,17 @@ +type ProgressBarProps = { + progress: number; + max: number; +}; + +function ProgressBar({ progress, max }: ProgressBarProps) { + return ( +
+
+
+ ); +} + +export default ProgressBar; diff --git a/src/components/pricing-page/provider/provider-table.tsx b/src/components/pricing-page/provider/provider-table.tsx new file mode 100644 index 00000000..0106b48c --- /dev/null +++ b/src/components/pricing-page/provider/provider-table.tsx @@ -0,0 +1,448 @@ +import { + QueryClient, + QueryClientProvider, + useQuery, +} from "@tanstack/react-query"; +import axios from "axios"; +import React, { useEffect, useState } from "react"; +import { gpus } from "@/utils/api"; +import clsx from "clsx"; +import MonthEarning from "./month-earning"; +import _ from 'lodash' +import arrowUpRight from '../../../assets/icons/arrow-up-right.svg'; +import PricingUnit from "./pricing-unit"; +import CpuBrand from '../../../assets/cpu-brand.svg' +import MemoryBrand from '../../../assets/memory-brand.svg' +import StorageBrand from '../../../assets/storage-brand.svg' +import GpuBrand from '../../../assets/gpu-brand.svg' +import IpsBrand from '../../../assets/ips-brand.svg' +import EndpointBrand from '../../../assets/endpoint-brand.svg' + +export interface Gpus { + availability: { total: number; available: number }; + models: Array<{ + vendor: string; + model: string; + ram: string; + interface: string; + availability: { total: number; available: number }; + providerAvailability: { total: number; available: number }; + price: { + min: number; + max: number; + avg: number; + med: number; + weightedAverage: number; + }; + }>; + time?: number; +} + +const ProviderTable = ({ + initialData, + pathName, + subCom, +}: { + initialData?: any; + pathName?: any; + subCom?: boolean; +}) => { + const queryClient = new QueryClient(); + + return ( + + + + ); +}; + +export default ProviderTable; + +const Table = ({ + initialData, + pathName, + subCom, +}: { + initialData?: { + data: any; + }; + pathName?: any; + subCom?: boolean; +}) => { + const fetchInterval = 1000 * 60; + + const { + data: result, + isLoading, + isFetching, + isInitialLoading, + } = useQuery< + { + data: Gpus; + }, + Error + >({ + queryKey: ["GPU_TABLE"], + queryFn: () => axios.get(gpus), + refetchIntervalInBackground: true, + + refetchInterval: fetchInterval, + }); + + const data = result?.data; + return ( + + ); +}; + +export const Tables = ({ + data, + pathName, + subCom, + isLoading, +}: { + data?: Gpus; + pathName?: any; + subCom?: boolean; + isLoading?: boolean; +}) => { + const max = { + leasePercentInput: 100, + cpuInput: 100, + cpuPricing: 100, + memoryInput: 512, + memoryPricing: 100, + storageInput: 10240, + storagePricing: 100, + persistentStorageInput: 10240, + persistentStoragePricing: 100, + gpuInput: 100, + gpuPricing: 100, + ipInput: 100, + ipPricing: 100, + endpointInput: 100, + endpointPricing: 100, + } + + const [leasePercentInput, setLeasePercentInput] = useState(100) + const [cpuInput, setCpuInput] = useState(10) + const [cpuPricing, setCpuPricing] = useState(10) + const [memoryInput, setMemoryInput] = useState(256) + const [memoryPricing, setMemoryPricing] = useState(10) + const [storageInput, setStorageInput] = useState(1024) + const [storagePricing, setStoragePricing] = useState(10) + const [persistentStorageInput, setPersistentStorageInput] = useState(1024) + const [persistentStoragePricing, setPersistentStoragePricing] = useState(10) + const [gpuInput, setGPUInput] = useState(1) + const [gpuPricing, setGPUPricing] = useState(1) + const [ipInput, setIpInput] = useState(1) + const [ipPricing, setIpPricing] = useState(1) + const [endpointInput, setEndpointInput] = useState(1) + const [endpointPricing, setEndpointPricing] = useState(1) + + const [aktAverage, setAktAverage] = useState(true) + const [usdPrice, setUsdPrice] = useState(0) + const [monthlyAverage, setMonthlyAverage] = useState(0) + + const [usdPrices, setUsdPrices] = useState({ + cpuTotalPrice: 0, + memoryTotalPrice: 0, + storageTotalPrice: 0, + persistenStorageTotalPrice: 0, + gpuTotalPrice: 0, + ipTotalPrice: 0, + endpointTotalPrice: 0, + totalPrice: 0, + }) + + + useEffect(() => { + let currentPrice = 0.0 + let averagePrice = 0.0 + fetch('https://api.coingecko.com/api/v3/coins/akash-network/tickers') + .then((response) => response.json()) + .then((data) => { + for (let i = 0; i < data.tickers.length; i += 1) { + if (data.tickers[i].market.name === 'Coinbase Exchange') { + currentPrice = data.tickers[i].converted_last.usd + setUsdPrice(data.tickers[i].converted_last.usd) + break + } + } + }) + fetch( + 'https://api.coingecko.com/api/v3/coins/akash-network/market_chart?vs_currency=usd&days=30&interval=daily', + ) + .then((response) => response.json()) + .then((data) => { + const mean = _.meanBy(data.prices, (o: [number, number]) => { + return o[1] + }) + averagePrice = mean + if (currentPrice > averagePrice) { + setAktAverage(false) + } + setMonthlyAverage(mean) + }) + }, []) + + useEffect(() => { + const cpuTotalPrice = (cpuInput * cpuPricing) / (100 / leasePercentInput) + const memoryTotalPrice = (memoryInput * memoryPricing) / (100 / leasePercentInput) + const storageTotalPrice = (storageInput * storagePricing) / (100 / leasePercentInput) + const persistenStorageTotalPrice = (persistentStorageInput * persistentStoragePricing) / (100 / leasePercentInput) + const gpuTotalPrice = (gpuPricing * gpuInput) / (100 / leasePercentInput) + const ipTotalPrice = (ipPricing * ipInput) / (100 / leasePercentInput) + const endpointTotalPrice = (endpointInput * endpointPricing) / (100 / leasePercentInput) + + const totalPrice = + cpuTotalPrice + + memoryTotalPrice + + storageTotalPrice + + persistenStorageTotalPrice + + gpuTotalPrice + + ipTotalPrice + + endpointTotalPrice + + setUsdPrices({ + cpuTotalPrice, + memoryTotalPrice, + storageTotalPrice, + persistenStorageTotalPrice, + gpuTotalPrice, + ipTotalPrice, + endpointTotalPrice, + totalPrice, + }) + }, [cpuInput, + cpuPricing, + memoryInput, + memoryPricing, + storageInput, + storagePricing, + persistentStorageInput, + persistentStoragePricing, + gpuInput, + gpuPricing, + ipInput, + ipPricing, + endpointInput, + endpointPricing, + ]) + + const calculateAKTPrice = (usdValue: any) => { + return (aktAverage ? usdValue / monthlyAverage : usdValue / usdPrice).toFixed(2) + } + + return ( +
+
+
+

Estimated Earnings

+ +
+
+

Estimated Breakdown

+
+ + + + + + + +
+
+
+
+

Estimated Earnings

+
+
+ +
+
+

+ Resources pricing +

+

+ Usage % (Leases in your provider) +

+
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+
+
+ ); +}; diff --git a/src/components/pricing-page/usage/compare.tsx b/src/components/pricing-page/usage/compare.tsx new file mode 100644 index 00000000..182f1e04 --- /dev/null +++ b/src/components/pricing-page/usage/compare.tsx @@ -0,0 +1,50 @@ +import awsLogo from '../../../assets/aws-logo.svg' +import gcpLogo from '../../../assets/gcp-logo.svg' +import azureLogo from '../../../assets/azure-logo.svg' + + +const Compare = () => { + const mock = 25.12 + return ( +
+
+
+ akash-logo +

AWS

+
+
+

Estimated Cost:

+

+ ${mock} +

+
+
+
+
+ akash-logo +

GCP

+
+
+

Estimated Cost:

+

+ ${mock} +

+
+
+
+
+ akash-logo +

Azure

+
+
+

Estimated Cost:

+

+ ${mock} +

+
+
+
+ ); +}; + +export default Compare; diff --git a/src/components/pricing-page/usage/disclaimer.tsx b/src/components/pricing-page/usage/disclaimer.tsx new file mode 100644 index 00000000..562755ad --- /dev/null +++ b/src/components/pricing-page/usage/disclaimer.tsx @@ -0,0 +1,15 @@ +import { Info } from "lucide-react"; + +function Disclaimer() { + return ( +
+

Disclaimer

+ +
+ ); +} + +export default Disclaimer; diff --git a/src/components/pricing-page/usage/progress-bar.tsx b/src/components/pricing-page/usage/progress-bar.tsx new file mode 100644 index 00000000..51a6a361 --- /dev/null +++ b/src/components/pricing-page/usage/progress-bar.tsx @@ -0,0 +1,16 @@ +type ProgressBarProps = { + progress: number; +}; + +function ProgressBar({ progress }: ProgressBarProps) { + return ( +
+
+
+ ); +} + +export default ProgressBar; diff --git a/src/components/pricing-page/usage/usage-amount.tsx b/src/components/pricing-page/usage/usage-amount.tsx new file mode 100644 index 00000000..4989efb7 --- /dev/null +++ b/src/components/pricing-page/usage/usage-amount.tsx @@ -0,0 +1,46 @@ +import React, { useEffect, useState } from "react"; +import ProgressBar from "./progress-bar"; + +type UsageAmountProps = { + title: string; + content: string; +}; + +function UsageAmount({ title, content }: UsageAmountProps) { + + + const [progress, setProgress] = useState(60); + + const handleInputChange = (event: React.ChangeEvent) => { + setProgress(Number(event.target.value)); + }; + + + return ( +
+
+

{title}

+

{content}

+
+
+
+ + +
+
+ 240 +
+
+
+ ); +} + +export default UsageAmount; diff --git a/src/components/pricing-page/usage/usage-table.tsx b/src/components/pricing-page/usage/usage-table.tsx new file mode 100644 index 00000000..cc12fa1f --- /dev/null +++ b/src/components/pricing-page/usage/usage-table.tsx @@ -0,0 +1,203 @@ +import { + QueryClient, + QueryClientProvider, + useQuery, +} from "@tanstack/react-query"; +import axios from "axios"; +import React, { useEffect, useState } from "react"; +import { + HoverCard, + HoverCardContent, + HoverCardTrigger, +} from "@/components/ui/hover-card"; +import { Info } from "lucide-react"; +import { gpus } from "@/utils/api"; +import clsx from "clsx"; +import { Skeleton } from "../../ui/skeleton"; +import arrowUpRight from '../../../assets/icons/arrow-up-right.svg'; +import Compare from "./compare"; +import akashLogo from '../../../assets/akash-logo-primary.svg' +import ProgressBar from "./progress-bar"; +import Disclaimer from "./disclaimer"; +import UsageAmount from "./usage-amount"; +export interface Gpus { + availability: { total: number; available: number }; + models: Array<{ + vendor: string; + model: string; + ram: string; + interface: string; + availability: { total: number; available: number }; + providerAvailability: { total: number; available: number }; + price: { + min: number; + max: number; + avg: number; + med: number; + weightedAverage: number; + }; + }>; + time?: number; +} + +const UsageTable = ({ + initialData, + pathName, + subCom, +}: { + initialData?: any; + pathName?: any; + subCom?: boolean; +}) => { + const queryClient = new QueryClient(); + + return ( + +
+ + ); +}; + +export default UsageTable; + +const Table = ({ + initialData, + pathName, + subCom, +}: { + initialData?: { + data: any; + }; + pathName?: any; + subCom?: boolean; +}) => { + const fetchInterval = 1000 * 60; + + const { + data: result, + isLoading, + isFetching, + isInitialLoading, + } = useQuery< + { + data: Gpus; + }, + Error + >({ + queryKey: ["GPU_TABLE"], + queryFn: () => axios.get(gpus), + refetchIntervalInBackground: true, + + refetchInterval: fetchInterval, + }); + + const data = result?.data; + return ( + + ); +}; + +export const Tables = ({ + data, + pathName, + subCom, + isLoading, +}: { + data?: Gpus; + pathName?: any; + subCom?: boolean; + isLoading?: boolean; +}) => { + + const mock = { + cost: 5.12, + percent: - 83.55 + } + + const [progress, setProgress] = useState(60); + + const handleInputChange = (event: React.ChangeEvent) => { + setProgress(Number(event.target.value)); + }; + + return ( +
+
+
+

Price estimate

+
+
+ akash-logo +

Akash Network

+
+
+

Estimated Cost:

+

+ ${mock.cost} +

+
+
+

+ {mock.percent} +

+
+
+ +

Deploy Now

+ +
+
+
+

Price compare

+ +
+
+
+ +
+

Usage estimate

+ + + + +
+ +
+
+
+
+ ); +}; diff --git a/src/components/ui/pricing-tag.astro b/src/components/ui/pricing-tag.astro new file mode 100644 index 00000000..539cb035 --- /dev/null +++ b/src/components/ui/pricing-tag.astro @@ -0,0 +1,19 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +interface Props extends HTMLAttributes<"a"> { + className?: string; + active?: boolean; +} +const { className, active, ...props } = Astro.props; +--- + + + + diff --git a/src/pages/gpus.astro b/src/pages/gpus.astro deleted file mode 100644 index 22e7c697..00000000 --- a/src/pages/gpus.astro +++ /dev/null @@ -1,16 +0,0 @@ ---- -import Layout from "@/layouts/layout.astro"; -import GpuTable from "@/components/gpu-table/gpu-table"; -import { gpus } from "@/utils/api"; - -// const response = await fetch(gpus); -// const data = await response.json(); ---- - - - - diff --git a/src/pages/pricing/gpus/index.astro b/src/pages/pricing/gpus/index.astro new file mode 100644 index 00000000..c1436941 --- /dev/null +++ b/src/pages/pricing/gpus/index.astro @@ -0,0 +1,37 @@ +--- +import Layout from "@/layouts/layout.astro"; +import PricingNavbar from "@/components/pricing-page/pricing-navbar.astro"; +import GpuTable from "@/components/pricing-page/gpus/gpu-table"; +import { gpus } from "@/utils/api"; + +const astroUrl = Astro.url; +const pathName = astroUrl.pathname.split("/"); +// const response = await fetch(gpus); +// const data = await response.json(); +--- + + +
+

+ Explorer pricing and calculate
your costs or earnings +

+ +
+

+ GPU Models, Prices & Availabilty +

+

+ Browse the list of available GPUs along with their hourly rates. +

+
+ +
+
diff --git a/src/pages/pricing/provider/index.astro b/src/pages/pricing/provider/index.astro new file mode 100644 index 00000000..839cbe01 --- /dev/null +++ b/src/pages/pricing/provider/index.astro @@ -0,0 +1,37 @@ +--- +import Layout from "@/layouts/layout.astro"; +import PricingNavbar from "@/components/pricing-page/pricing-navbar.astro"; +import ProviderTable from "@/components/pricing-page/provider/provider-table"; +import { gpus } from "@/utils/api"; + +const astroUrl = Astro.url; +const pathName = astroUrl.pathname.split("/"); +// const response = await fetch(gpus); +// const data = await response.json(); +--- + + +
+

+ Explorer pricing and calculate
your costs or earnings +

+ +
+

+ Provider Earn Calculator +

+

+ Calculate your potential earnings by providing resources to the Akash Network. +

+
+ +
+
diff --git a/src/pages/pricing/usage/index.astro b/src/pages/pricing/usage/index.astro new file mode 100644 index 00000000..b044c025 --- /dev/null +++ b/src/pages/pricing/usage/index.astro @@ -0,0 +1,39 @@ +--- +import Layout from "@/layouts/layout.astro"; +import PricingNavbar from "@/components/pricing-page/pricing-navbar.astro"; +import UsageTable from "@/components/pricing-page/usage/usage-table"; +import { gpus } from "@/utils/api"; + +const astroUrl = Astro.url; +const pathName = astroUrl.pathname.split("/"); +// const response = await fetch(gpus); +// const data = await response.json(); +--- + + +
+

+ Explorer pricing and calculate
your costs or earnings +

+ +
+

+ Usage Pricing +

+

+ Estimate your costs by selecting the resources you need.
+ Adjust CPU, memory, storage, and other parameters to get a detailed + cost breakdown. +

+
+ +
+
diff --git a/src/styles/globals.css b/src/styles/globals.css index 5b454ab8..429bb7a7 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -15,7 +15,8 @@ --link-text: 206 6% 52%; --primary: #ff414c; --primary-foreground: 0 0% 100%; - + --background-muted: #F4F4F5; + /* secondary colors */ --secondary: 0 100% 94%; --secondary-rose: 0 100% 94%; diff --git a/tailwind.config.cjs b/tailwind.config.cjs index 99b6a671..d32335ef 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -56,6 +56,7 @@ module.exports = { colors: { background: "hsl(var(--background))", background2: "hsl(var(--background2))", + "background-muted": "hsl(var(--background-muted))", foreground: "hsl(var(--foreground))", para: "hsl(var(--para))", cardGray: "hsl(var(--card-gray))", @@ -73,6 +74,8 @@ module.exports = { DEFAULT: "var(--primary)", foreground: "hsl(var(--primary-foreground))", }, + "success-light": "#D1FAE5", + "success-dark": "#065F46", secondary: { DEFAULT: "hsl(var(--secondary))",