Skip to content
Open
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
22 changes: 15 additions & 7 deletions FrontEnd/my-app/app/[locale]/profile/[address]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
'use client';

import { useParams } from 'next/navigation';
import { AppLayout } from '@/components/layout/AppLayout';
import { UserProfile } from '@/components/profile/UserProfile';
import { useProfile } from '@/lib/hooks/useProfile';

export default function ProfilePage() {
const params = useParams();
const address = params.address as string;

const { refetch, updateProfileData, follow, unfollow } = useProfile(address);
const { profileData, isLoading, refetch, updateProfileData, follow, unfollow } = useProfile(address);

return (
<UserProfile
onRefetch={refetch}
onUpdateProfile={updateProfileData}
onFollow={follow}
onUnfollow={unfollow}
/>
<AppLayout>
<div className="container mx-auto max-w-6xl py-8 px-4">
<UserProfile
address={address}
profile={profileData}
isLoading={isLoading}
onRefetch={refetch}
onUpdateProfile={updateProfileData}
onFollow={follow}
onUnfollow={unfollow}
/>
</div>
</AppLayout>
);
}
152 changes: 36 additions & 116 deletions FrontEnd/my-app/components/admin/AdminLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useState } from 'react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import type { AdminUser } from '@/lib/types/admin';
import { ThemeToggle } from '@/components/ui/ThemeToggle';

interface AdminLayoutProps {
children: React.ReactNode;
Expand All @@ -16,130 +17,49 @@ const navItems = [
{ href: '/admin/quests/new', label: 'Create Quest', icon: '➕' },
{ href: '/admin/submissions', label: 'Submissions', icon: '📬' },
{ href: '/admin/users', label: 'Users', icon: '👥' },
{ href: '/admin/settings', label: 'Settings', icon: '⚙️' },
];

export function AdminLayout({ children, user }: AdminLayoutProps) {
export default function AdminLayout({ children, user }: AdminLayoutProps) {
const pathname = usePathname();
const [sidebarOpen, setSidebarOpen] = useState(false);

return (
<div className="min-h-screen bg-zinc-100 dark:bg-zinc-950">
{/* Mobile sidebar backdrop */}
{sidebarOpen && (
<div
className="fixed inset-0 z-40 bg-black/50 lg:hidden"
onClick={() => setSidebarOpen(false)}
/>
)}

{/* Sidebar */}
<aside
className={`fixed top-0 left-0 z-50 h-full w-64 transform border-r border-zinc-200 bg-white transition-transform dark:border-zinc-800 dark:bg-zinc-900 lg:translate-x-0 ${
sidebarOpen ? 'translate-x-0' : '-translate-x-full'
}`}
>
{/* Logo */}
<div className="flex h-16 items-center justify-between border-b border-zinc-200 px-4 dark:border-zinc-800">
<Link href="/admin" className="flex items-center gap-2">
<span className="text-2xl">⭐</span>
<span className="font-bold text-zinc-900 dark:text-zinc-50">
StellarEarn
</span>
</Link>
<button
onClick={() => setSidebarOpen(false)}
className="rounded-lg p-1 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800 lg:hidden"
>
</button>
<div className="min-h-screen bg-zinc-50 dark:bg-zinc-900 text-zinc-900 dark:text-zinc-50">
<header className="flex h-16 items-center justify-between border-b border-zinc-200 bg-white px-4 dark:border-zinc-800 dark:bg-zinc-950 sm:px-6 lg:px-8">
<div className="flex items-center gap-4">
<span className="font-bold text-lg tracking-tight">StellarEarn Admin</span>
</div>
<div className="flex items-center gap-4">
<ThemeToggle />
{user && <span className="text-sm font-medium text-zinc-600 dark:text-zinc-400">{user.email}</span>}
</div>
</header>

{/* Navigation */}
<nav className="p-4 space-y-1">
{navItems.map((item) => {
const isActive =
pathname === item.href ||
(item.href !== '/admin' && pathname.startsWith(item.href));
return (
<Link
key={item.href}
href={item.href}
className={`flex items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors ${
isActive
? 'bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400'
: 'text-zinc-600 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:bg-zinc-800'
}`}
onClick={() => setSidebarOpen(false)}
>
<span>{item.icon}</span>
{item.label}
</Link>
);
})}
</nav>

{/* User Info */}
{user && (
<div className="absolute bottom-0 left-0 right-0 border-t border-zinc-200 p-4 dark:border-zinc-800">
<div className="flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-blue-100 text-blue-600 dark:bg-blue-900/30 dark:text-blue-400">
{user.username.charAt(0).toUpperCase()}
</div>
<div className="flex-1 min-w-0">
<p className="truncate font-medium text-zinc-900 dark:text-zinc-50">
{user.username}
</p>
<p className="truncate text-xs text-zinc-500 dark:text-zinc-400">
{user.role.replace('_', ' ')}
</p>
</div>
</div>
</div>
)}
</aside>

{/* Main content */}
<div className="lg:pl-64">
{/* Top bar */}
<header className="sticky top-0 z-30 flex h-16 items-center justify-between border-b border-zinc-200 bg-white px-4 dark:border-zinc-800 dark:bg-zinc-900">
<button
onClick={() => setSidebarOpen(true)}
className="rounded-lg p-2 text-zinc-500 hover:bg-zinc-100 dark:hover:bg-zinc-800 lg:hidden"
>
<svg
className="h-6 w-6"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
</button>

<div className="flex items-center gap-3">
<span className="hidden text-sm text-zinc-500 dark:text-zinc-400 sm:inline">
Admin Panel
</span>
</div>

<div className="flex items-center gap-3">
<Link
href="/dashboard"
className="rounded-lg border border-zinc-200 px-3 py-1.5 text-sm font-medium text-zinc-600 transition-colors hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-400 dark:hover:bg-zinc-800"
>
Exit Admin
</Link>
</div>
</header>
<div className="flex">
<aside className="hidden w-64 border-r border-zinc-200 bg-white p-4 dark:border-zinc-800 dark:bg-zinc-950 md:block min-h-[calc(100vh-4rem)]">
<nav className="space-y-1">
{navItems.map((item) => {
const isActive = pathname === item.href;
return (
<Link
key={item.href}
href={item.href}
className={`flex items-center gap-3 rounded-lg px-3 py-1.5 text-sm font-medium transition-colors ${
isActive
? 'bg-zinc-100 text-zinc-900 dark:bg-zinc-800 dark:text-zinc-50'
: 'text-zinc-600 hover:bg-zinc-50 dark:text-zinc-400 dark:hover:bg-zinc-900'
}`}
>
<span>{item.icon}</span>
{item.label}
</Link>
);
})}
</nav>
</aside>

{/* Page content */}
<main className="p-4 sm:p-6 lg:p-8">{children}</main>
<main className="flex-1 p-4 sm:p-6 lg:p-8">
{children}
</main>
</div>
</div>
);
Expand Down
37 changes: 9 additions & 28 deletions contracts/earn-quest/fuzz/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,45 +1,26 @@
[package]
name = "earn-quest-fuzz"
version = "0.1.0"
version = "0.0.0"
authors = ["Automated Delivery"]
edition = "2021"
publish = false

[package.metadata]
cargo-fuzz = true

[dependencies]
libfuzzer-sys = "0.4"
arbitrary = { version = "1.3", features = ["derive"] }
soroban-sdk = "21.7.4"

[dependencies.earn-quest]
path = ".."

[[bin]]
name = "quest_creation_fuzzer"
path = "fuzz_targets/quest_creation_fuzzer.rs"
test = false
doc = false

[[bin]]
name = "submission_fuzzer"
path = "fuzz_targets/submission_fuzzer.rs"
test = false
doc = false

[[bin]]
name = "validation_fuzzer"
path = "fuzz_targets/validation_fuzzer.rs"
test = false
doc = false
soroban-sdk = { version = "20.0.0", features = ["testutils"] }
earn-quest = { path = ".." }

[[bin]]
name = "input_decoding_fuzzer"
path = "fuzz_targets/input_decoding_fuzzer.rs"
name = "batch_registration_fuzzer"
path = "fuzz_targets/batch_registration_fuzzer.rs"
test = false
doc = false

[[bin]]
name = "state_transitions_fuzzer"
path = "fuzz_targets/state_transitions_fuzzer.rs"
name = "batch_approval_fuzzer"
path = "fuzz_targets/batch_approval_fuzzer.rs"
test = false
doc = false
13 changes: 13 additions & 0 deletions contracts/earn-quest/fuzz/fuzz_targets/batch_approval_fuzzer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use soroban_sdk::{Env, Vec, String};

fuzz_target!(|data: Vec<(u32, i128, u8)>| {
let env = Env::default();
let mut approvals: Vec<(String, String, i128)> = Vec::new(&env);
for item in data.iter() {
let s_id = String::from_str(&env, "sub_id");
let addr = String::from_str(&env, "addr");
approvals.push_back((s_id, addr, item.1));
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#![no_main]
use libfuzzer_sys::fuzz_target;
use soroban_sdk::{Env, Vec, String};

fuzz_target!(|data: Vec<(u32, Vec<u8>, i128)>| {
let env = Env::default();
let mut batch: Vec<(String, String, i128, String)> = Vec::new(&env);
for item in data.iter() {
if let (Ok(id_str), Ok(asset_str)) = (std::str::from_utf8(&item.1), std::str::from_utf8(&item.1)) {
let q_id = String::from_str(&env, id_str);
let r_asset = String::from_str(&env, asset_str);
let verifier = String::from_str(&env, "v1");
batch.push_back((q_id, r_asset, item.2, verifier));
}
}
});
Loading