mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
Add store cards
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { StoreCard } from "./StoreCard";
|
||||
import { userEvent, within } from "@storybook/test";
|
||||
|
||||
const meta = {
|
||||
title: "AGPTUI/StoreCard",
|
||||
component: StoreCard,
|
||||
parameters: {
|
||||
layout: "centered",
|
||||
},
|
||||
tags: ["autodocs"],
|
||||
argTypes: {
|
||||
agentName: { control: "text" },
|
||||
description: { control: "text" },
|
||||
runs: { control: "number" },
|
||||
rating: { control: "number", min: 0, max: 5, step: 0.1 },
|
||||
onClick: { action: "clicked" },
|
||||
},
|
||||
} satisfies Meta<typeof StoreCard>;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
agentName: "SEO Optimizer",
|
||||
description: "Optimize your website's SEO with AI-powered suggestions",
|
||||
runs: 10000,
|
||||
rating: 4.5,
|
||||
onClick: () => console.log("Default StoreCard clicked"),
|
||||
},
|
||||
};
|
||||
|
||||
export const LowRating: Story = {
|
||||
args: {
|
||||
agentName: "Data Analyzer",
|
||||
description: "Analyze complex datasets with machine learning algorithms",
|
||||
runs: 5000,
|
||||
rating: 2.7,
|
||||
onClick: () => console.log("LowRating StoreCard clicked"),
|
||||
},
|
||||
};
|
||||
|
||||
export const HighRuns: Story = {
|
||||
args: {
|
||||
agentName: "Code Assistant",
|
||||
description: "Get AI-powered coding help for various programming languages",
|
||||
runs: 1000000,
|
||||
rating: 4.8,
|
||||
onClick: () => console.log("HighRuns StoreCard clicked"),
|
||||
},
|
||||
};
|
||||
|
||||
export const WithInteraction: Story = {
|
||||
args: {
|
||||
agentName: "Task Planner",
|
||||
description: "Plan and organize your tasks efficiently with AI",
|
||||
runs: 50000,
|
||||
rating: 4.2,
|
||||
onClick: () => console.log("WithInteraction StoreCard clicked"),
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
const storeCard = canvas.getByText("Task Planner");
|
||||
|
||||
await userEvent.hover(storeCard);
|
||||
await userEvent.click(storeCard);
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,70 @@
|
||||
import * as React from "react";
|
||||
import { StarIcon, StarFilledIcon } from "@radix-ui/react-icons";
|
||||
|
||||
interface StoreCardProps {
|
||||
agentName: string;
|
||||
description: string;
|
||||
runs: number;
|
||||
rating: number;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
export const StoreCard: React.FC<StoreCardProps> = ({
|
||||
agentName,
|
||||
description,
|
||||
runs,
|
||||
rating,
|
||||
onClick,
|
||||
}) => {
|
||||
const [isHovered, setIsHovered] = React.useState(false);
|
||||
|
||||
const handleMouseEnter = () => setIsHovered(true);
|
||||
const handleMouseLeave = () => setIsHovered(false);
|
||||
|
||||
const renderStars = () => {
|
||||
const fullStars = Math.floor(rating);
|
||||
const hasHalfStar = rating % 1 !== 0;
|
||||
const stars = [];
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
if (i < fullStars) {
|
||||
stars.push(<StarFilledIcon key={i} className="text-black" />);
|
||||
} else if (i === fullStars && hasHalfStar) {
|
||||
stars.push(<StarIcon key={i} className="text-black" />);
|
||||
} else {
|
||||
stars.push(<StarIcon key={i} className="text-black" />);
|
||||
}
|
||||
}
|
||||
|
||||
return stars;
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`relative h-96 w-[440px] ${isHovered ? "shadow-lg" : ""} rounded-xl transition-shadow duration-300`}
|
||||
onClick={onClick}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
>
|
||||
<div className="absolute left-0 top-0 h-[238px] w-[440px] rounded-xl bg-[#d9d9d9]" />
|
||||
<div className="absolute left-[16px] top-[158px] h-16 w-16 rounded-full bg-[#7e7e7e]" />
|
||||
<div className="font-['PP Neue Montreal TT'] absolute left-0 top-[254px] text-xl font-bold tracking-tight text-[#272727]">
|
||||
{agentName}
|
||||
</div>
|
||||
<div className="font-['PP Neue Montreal TT'] absolute left-0 top-[284px] w-[440px] text-base font-normal leading-[21px] tracking-tight text-[#282828]">
|
||||
{description}
|
||||
</div>
|
||||
<div className="font-['PP Neue Montreal TT'] absolute left-0 top-[360px] text-base font-medium tracking-tight text-[#272727]">
|
||||
{runs.toLocaleString()}+ runs
|
||||
</div>
|
||||
<div className="absolute left-[297px] top-[360px] pb-2">
|
||||
<div className="font-['PP Neue Montreal TT'] absolute left-0 top-0 text-base font-medium tracking-tight text-[#272727]">
|
||||
{rating.toFixed(1)}
|
||||
</div>
|
||||
<div className="absolute left-[34px] top-0 inline-flex h-[19px] items-center justify-start gap-px">
|
||||
{renderStars()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user