Skip to content

Fix/issues #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Nov 3, 2024
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
24 changes: 18 additions & 6 deletions src/app/admin/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ export default function AdminPanel() {
const [roleFilter, setRoleFilter] = useState<UserRole | "All">("All");
const [isAdmin, setIsAdmin] = useState<boolean>(false);
const [editingProfile, setEditingProfile] = useState<{
[key: string]: { assigned_agent_address: string; account_index: string };
[key: string]: {
assigned_agent_address: string;
account_index: string;
role: UserRole;
};
}>({});
const [sortOrder, setSortOrder] = useState<SortOrder>(null);

Expand Down Expand Up @@ -89,9 +93,10 @@ export default function AdminPanel() {
acc[profile.id] = {
assigned_agent_address: profile.assigned_agent_address || "",
account_index: profile.account_index?.toString() || "",
role: profile.role,
};
return acc;
}, {} as { [key: string]: { assigned_agent_address: string; account_index: string } });
}, {} as { [key: string]: { assigned_agent_address: string; account_index: string; role: UserRole } });
setEditingProfile(initialEditingState);
}
} catch (error) {
Expand All @@ -117,6 +122,7 @@ export default function AdminPanel() {
editingProfile[userId].account_index === ""
? 0
: parseInt(editingProfile[userId].account_index, 10),
role: editingProfile[userId].role,
};
const { error } = await supabase
.from("profiles")
Expand All @@ -133,7 +139,7 @@ export default function AdminPanel() {

const handleInputChange = (
userId: string,
field: "assigned_agent_address" | "account_index",
field: "assigned_agent_address" | "account_index" | "role",
value: string
) => {
setEditingProfile((prev) => ({
Expand Down Expand Up @@ -269,7 +275,7 @@ export default function AdminPanel() {
({getSortText()})
</span>
</th>
<th className="px-4 py-2 text-left">Stack Address</th>
<th className="px-4 py-2 text-left">Stacks Addresses</th>
<th className="px-4 py-2 text-left">Role</th>
<th className="px-4 py-2 text-left">Agent Address</th>
<th className="px-4 py-2 text-left">Actions</th>
Expand Down Expand Up @@ -298,8 +304,14 @@ export default function AdminPanel() {
<td className="px-4 py-2">
<select
className="w-full p-2 border rounded-md"
value={profile.role}
onChange={() => updateProfile(profile.id)}
value={editingProfile[profile.id]?.role || profile.role}
onChange={(e) =>
handleInputChange(
profile.id,
"role",
e.target.value as UserRole
)
}
>
<option value="Normal">Normal</option>
<option value="Admin">Admin</option>
Expand Down
5 changes: 4 additions & 1 deletion src/app/crew/[id]/manage/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ export default function CrewDetails() {

return (
<div className="space-y-8">
<h1 className="text-3xl font-bold pt-4">Crew: {crew.name}</h1>
<h1 className="text-primary text-3xl font-bold pt-4">
Crew: {crew.name}
</h1>
<p className="text-ghost">{crew.description}</p>
<div className="space-y-8">
<Card>
<CardContent>
Expand Down
90 changes: 84 additions & 6 deletions src/app/leaderboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React, { useState } from "react";
import { Loader2, Search, Trophy } from "lucide-react";
import React, { useState, useMemo } from "react";
import { Loader2, Search, Trophy, User } from "lucide-react";
import { Alert, AlertDescription } from "@/components/ui/alert";
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
import {
Expand All @@ -15,18 +15,46 @@ import {
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { useLeaderboardData } from "@/hooks/useLeaderBoardData";
import { useUserData } from "@/hooks/useUserData";

export default function LeaderBoard() {
const { data: profiles, isLoading, error } = useLeaderboardData();
const { data: userData } = useUserData();
const [searchTerm, setSearchTerm] = useState<string>("");

const filteredProfiles = React.useMemo(() => {
const sortedProfiles = useMemo(() => {
if (!profiles) return [];
return profiles.filter((profile) => {
return [...profiles].sort((a, b) => {
const balanceA = a.agentBalance || 0;
const balanceB = b.agentBalance || 0;
return balanceB - balanceA;
});
}, [profiles]);

const filteredProfiles = useMemo(() => {
return sortedProfiles.filter((profile) => {
const stacksAddress = profile.email.split("@")[0].toLowerCase();
return stacksAddress.includes(searchTerm.toLowerCase());
});
}, [searchTerm, profiles]);
}, [searchTerm, sortedProfiles]);

const authenticatedUserProfile = useMemo(() => {
if (!sortedProfiles || !userData) return null;
return sortedProfiles.find(
(profile) =>
profile.email.split("@")[0].toLowerCase() ===
userData.stxAddress.toLowerCase()
);
}, [sortedProfiles, userData]);

const authenticatedUserRank = useMemo(() => {
if (!authenticatedUserProfile) return null;
return (
sortedProfiles.findIndex(
(profile) => profile.email === authenticatedUserProfile.email
) + 1
);
}, [sortedProfiles, authenticatedUserProfile]);

if (isLoading) {
return (
Expand Down Expand Up @@ -64,6 +92,49 @@ export default function LeaderBoard() {
</div>
</CardHeader>
<CardContent>
{authenticatedUserProfile && (
<Card className="mb-6 bg-primary/10">
<CardContent className="p-4">
<div className="flex items-center justify-between mb-2">
<div className="flex items-center gap-2">
<User className="h-5 w-5" />
<span className="font-bold">Your Position</span>
</div>
<Badge variant="secondary">Rank: {authenticatedUserRank}</Badge>
</div>
<Table>
<TableHeader>
<TableRow>
<TableHead>Participant</TableHead>
<TableHead>Agent Address</TableHead>
<TableHead className="text-right">Agent Balance</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="font-mono">
{authenticatedUserProfile.email
.split("@")[0]
.toUpperCase()}
</TableCell>
<TableCell className="font-mono text-sm">
{authenticatedUserProfile.assigned_agent_address || (
<Badge variant="outline">No agent assigned</Badge>
)}
</TableCell>
<TableCell className="text-right font-bold">
{authenticatedUserProfile.agentBalance !== undefined
? `${authenticatedUserProfile.agentBalance.toFixed(
2
)} STX`
: "-"}
</TableCell>
</TableRow>
</TableBody>
</Table>
</CardContent>
</Card>
)}
<Table>
<TableHeader>
<TableRow>
Expand All @@ -75,7 +146,14 @@ export default function LeaderBoard() {
</TableHeader>
<TableBody>
{filteredProfiles.map((profile, index) => (
<TableRow key={profile.email}>
<TableRow
key={profile.email}
className={
profile.email === authenticatedUserProfile?.email
? "bg-primary/10"
: undefined
}
>
<TableCell className="font-medium">
{index < 3 ? (
<Trophy
Expand Down
82 changes: 42 additions & 40 deletions src/components/crews/CloneTradingAnalyzer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,44 +16,44 @@ const getDefaultAgents = async (): Promise<CloneAgent[]> => {
const webSearchTools = await getToolsByCategory("web_search");

return [
{
name: "Research agent for ALEX",
role: "Market Researcher",
goal: "Analyze and provide insights on market trends using ALEX data",
backstory:
"Specialized in processing and analyzing ALEX market data to identify trading opportunities and market patterns",
agent_tools: [
...alexTools.map((t) => t.id),
...webSearchTools.map((t) => t.id),
],
},
{
name: "Research agent for bitflow",
role: "Bitflow Analyst",
goal: "Monitor and analyze Bitflow trading signals and market data",
backstory:
"Expert in interpreting Bitflow signals and correlating them with market movements",
agent_tools: [
...bitflowTools.map((t) => t.id),
...webSearchTools.map((t) => t.id),
],
},
{
name: "Research agent for lunarcrush",
role: "Social Sentiment Analyst",
goal: "Track and analyze social sentiment data from LunarCrush",
backstory:
"Specialized in social media sentiment analysis and its correlation with crypto markets",
agent_tools: [...lunarcrushTools.map((t) => t.id)],
},
{
name: "Trade executor for bitflow",
role: "Trade Executor",
goal: "Execute trades based on analyzed signals and market conditions",
backstory:
"Experienced in implementing trading strategies and managing trade execution",
agent_tools: [...bitflowTools.map((t) => t.id)],
},
{
name: "Research agent for ALEX",
role: "Market Researcher",
goal: "Analyze and provide insights on market trends using ALEX data",
backstory:
"Specialized in processing and analyzing ALEX market data to identify trading opportunities and market patterns",
agent_tools: [
...alexTools.map((t) => t.id),
...webSearchTools.map((t) => t.id),
],
},
{
name: "Research agent for bitflow",
role: "Bitflow Analyst",
goal: "Monitor and analyze Bitflow trading signals and market data",
backstory:
"Expert in interpreting Bitflow signals and correlating them with market movements",
agent_tools: [
...bitflowTools.map((t) => t.id),
...webSearchTools.map((t) => t.id),
],
},
{
name: "Research agent for lunarcrush",
role: "Social Sentiment Analyst",
goal: "Track and analyze social sentiment data from LunarCrush",
backstory:
"Specialized in social media sentiment analysis and its correlation with crypto markets",
agent_tools: [...lunarcrushTools.map((t) => t.id)],
},
{
name: "Trade executor for bitflow",
role: "Trade Executor",
goal: "Execute trades based on analyzed signals and market conditions",
backstory:
"Experienced in implementing trading strategies and managing trade execution",
agent_tools: [...bitflowTools.map((t) => t.id)],
},
];
};

Expand Down Expand Up @@ -95,10 +95,12 @@ const createTaskForAgent = (agent: CloneAgent): CloneTask => {

interface CloneTradingAnalyzerProps {
onCloneComplete: () => void;
disabled: boolean;
}

export function CloneTradingAnalyzer({
export function CloneTradingAnalyzer({
onCloneComplete,
disabled,
}: CloneTradingAnalyzerProps) {
const [isCloning, setIsCloning] = useState(false);
const [error, setError] = useState<string | null>(null);
Expand Down Expand Up @@ -226,7 +228,7 @@ export function CloneTradingAnalyzer({
)}
<Button
onClick={createTradingAnalyzer}
disabled={isCloning || hasCloned}
disabled={isCloning || hasCloned || disabled}
variant="outline"
className="w-full"
>
Expand Down
25 changes: 18 additions & 7 deletions src/components/crews/CrewForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { toast } from "@/hooks/use-toast";
import { CrewFormProps } from "@/types/supabase";
import { CrewFormProps, Crew } from "@/types/supabase";

export default function CrewForm({ onCrewCreated, onClose }: CrewFormProps) {
const [crewName, setCrewName] = useState("");
Expand All @@ -29,18 +29,29 @@ export default function CrewForm({ onCrewCreated, onClose }: CrewFormProps) {
throw new Error("No authenticated user found");
}

const { error } = await supabase.from("crews").insert({
name: crewName,
description: crewDescription,
profile_id: user.id,
});
const { data, error } = await supabase
.from("crews")
.insert({
name: crewName,
description: crewDescription,
profile_id: user.id,
})
.select()
.single();

if (error) throw error;

const newCrew: Crew = {
id: data.id,
name: data.name,
description: data.description,
created_at: data.created_at,
};

setCrewName("");
setCrewDescription("");
onClose();
onCrewCreated();
onCrewCreated(newCrew);
toast({
title: "Crew created",
description: "The new crew has been successfully created.",
Expand Down
Loading
Loading