Skip to content
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
2 changes: 1 addition & 1 deletion app/frontend/app/dao/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { WrongNetworkAlert } from '@/components/wallet/WrongNetworkAlert';

const ProposalDetailPage: React.FC = () => {
const params = useParams();
const id = params.id as string;
const id = typeof params?.id === 'string' ? params.id : '';
const [proposal, setProposal] = useState<Proposal | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
Expand Down
4 changes: 2 additions & 2 deletions app/frontend/app/demo/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";

import React, { useState } from 'react';
import MultiSourceDataAggregator from '../components/MultiSourceDataAggregator';
import SessionTimeoutManager from '../components/SessionTimeoutManager';
import MultiSourceDataAggregator from '../../components/MultiSourceDataAggregator';
import SessionTimeoutManager from '../../components/SessionTimeoutManager';

// Demo page for testing both components
const ComponentDemoPage: React.FC = () => {
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/app/events/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type EventDetailPayload = Event & {

export default function EventDetailPage() {
const params = useParams();
const eventId = params.id as string;
const eventId = typeof params?.id === 'string' ? params.id : '';

const [event, setEvent] = useState<EventDetailPayload | null>(null);
const [loading, setLoading] = useState(true);
Expand Down
4 changes: 2 additions & 2 deletions app/frontend/app/events/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export default function EventsPage() {
) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{events.map((event) => {
const status = getEventStatus(event.startDate, event.endDate);
const status = getEventStatus(event.startDate, event.endDate ?? null);
return (
<Link
key={event.id}
Expand Down Expand Up @@ -201,7 +201,7 @@ export default function EventsPage() {
<div className="space-y-2 mb-4">
<div className="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400">
<Calendar className="w-4 h-4" />
<span>{formatDateRange(event.startDate, event.endDate)}</span>
<span>{formatDateRange(event.startDate, event.endDate ?? null)}</span>
</div>
{event.registeredCount > 0 && (
<div className="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400">
Expand Down
11 changes: 8 additions & 3 deletions app/frontend/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Geist, Geist_Mono } from "next/font/google";
import "./globals.css";
import { WalletProvider } from "@/components/wallet/WalletProvider";
import { OfflineProvider } from "@/lib/offline/OfflineContext";
import { FloatingActionButton } from "@/components/navigation/FloatingActionButton";
import { RoleProvider } from "@/components/dao/RoleContext";

const geistSans = Geist({
variable: "--font-geist-sans",
Expand Down Expand Up @@ -41,9 +43,12 @@ export default function RootLayout({
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
<body className="antialiased">
<OfflineProvider>
<WalletProvider>
{children}
</WalletProvider>
<RoleProvider>
<WalletProvider>
{children}
<FloatingActionButton />
</WalletProvider>
</RoleProvider>
</OfflineProvider>
</body>
</html>
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/components/DataTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { useState } from "react";
import { motion, AnimatePresence } from "motion/react";
import { motion, AnimatePresence } from "framer-motion";

// Example data
const initialData = [
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/components/MultiSourceDataAggregator.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React, { useState, useEffect, useCallback } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { motion, AnimatePresence } from 'framer-motion';
import { AlertCircle, RefreshCw, CheckCircle, XCircle, Loader2 } from 'lucide-react';

// Types for the component
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/components/ReusableTable.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React, { useState } from "react";
import { motion, AnimatePresence } from "motion/react";
import { motion, AnimatePresence } from "framer-motion";

interface TableColumn {
key: string;
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/components/SessionTimeoutHandler.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React, { useState, useEffect, useCallback, useRef } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { motion, AnimatePresence } from 'framer-motion';
import { AlertCircle, Clock, LogOut, RefreshCcw, ShieldAlert } from 'lucide-react';

interface SessionTimeoutHandlerProps {
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/components/SessionTimeoutManager.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React, { useState, useEffect, useCallback, useRef } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { motion, AnimatePresence } from 'framer-motion';
import { AlertTriangle, Clock, LogOut, RefreshCw, X } from 'lucide-react';

// Types for the component
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/components/auth/RouteGuard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ function GenericSkeleton() {
);
}

const SKELETONS: Record<SkeletonVariant, () => JSX.Element> = {
const SKELETONS: Record<SkeletonVariant, () => React.JSX.Element> = {
dashboard: DashboardSkeleton,
event: EventSkeleton,
profile: ProfileSkeleton,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect, useRef, useState } from 'react';
import DynamicVideoGrid from '../video/DynamicVideoGrid';
import { DynamicVideoGrid } from '../video/DynamicVideoGrid';

// Section config type
type SectionType = 'trending' | 'forYou' | 'newReleases';
Expand Down
14 changes: 14 additions & 0 deletions app/frontend/components/common/VideoPlayerCaptions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use client';

interface VideoPlayerCaptionsProps {
videoSrc: string;
}

export default function VideoPlayerCaptions({ videoSrc }: VideoPlayerCaptionsProps) {
return (
<div className="rounded-lg border border-gray-200 bg-white p-3 text-sm text-gray-600 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300">
Captions are not available for this source yet.
<span className="sr-only">{videoSrc}</span>
</div>
);
}
14 changes: 14 additions & 0 deletions app/frontend/components/common/VideoPlayerComments.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use client';

interface VideoPlayerCommentsProps {
videoSrc: string;
}

export default function VideoPlayerComments({ videoSrc }: VideoPlayerCommentsProps) {
return (
<div className="mt-3 rounded-lg border border-gray-200 bg-white p-3 text-sm text-gray-600 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300">
Comments are currently unavailable.
<span className="sr-only">{videoSrc}</span>
</div>
);
}
2 changes: 1 addition & 1 deletion app/frontend/components/common/VideoPlayerLazy.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Suspense, useState } from 'react';
import dynamic from 'next/dynamic';
import VideoPlayerSync from '../video/VideoPlayerSync';
import { VideoPlayerSync } from '../video/VideoPlayerSync';

// Dynamically import non-critical UI components
const Captions = dynamic(() => import('./VideoPlayerCaptions'), { ssr: false, loading: () => <div className="player-ui-loading">Loading captions...</div> });
Expand Down
14 changes: 14 additions & 0 deletions app/frontend/components/common/VideoPlayerStats.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
'use client';

interface VideoPlayerStatsProps {
videoSrc: string;
}

export default function VideoPlayerStats({ videoSrc }: VideoPlayerStatsProps) {
return (
<div className="mt-3 rounded-lg border border-gray-200 bg-white p-3 text-sm text-gray-600 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-300">
Playback stats are loading.
<span className="sr-only">{videoSrc}</span>
</div>
);
}
2 changes: 2 additions & 0 deletions app/frontend/components/dao/RoleContext.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"use client";

import React, { createContext, useContext, useState, useEffect } from 'react';

export type UserRole = 'creator' | 'contributor' | 'admin' | null;
Expand Down
7 changes: 2 additions & 5 deletions app/frontend/components/dashboard/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,6 @@ export function Chart({
name={s.name || s.dataKey}
fill={s.color || colors[index % colors.length]}
radius={[4, 4, 0, 0]}
onClick={(data, index) => handleClick(data, index)}
cursor={onDataPointClick ? 'pointer' : 'default'}
{...animationProps}
/>
Expand Down Expand Up @@ -260,7 +259,6 @@ export function Chart({
strokeWidth={s.strokeWidth || 2}
dot={{ fill: s.color || colors[index % colors.length], r: 4 }}
activeDot={{ r: 6, strokeWidth: 0 }}
onClick={(data, index) => handleClick(data, index)}
cursor={onDataPointClick ? 'pointer' : 'default'}
{...animationProps}
/>
Expand Down Expand Up @@ -297,7 +295,6 @@ export function Chart({
stroke={s.color || colors[index % colors.length]}
fill={s.color || colors[index % colors.length]}
fillOpacity={s.fillOpacity || 0.2}
onClick={(data, index) => handleClick(data, index)}
cursor={onDataPointClick ? 'pointer' : 'default'}
{...animationProps}
/>
Expand All @@ -318,7 +315,7 @@ export function Chart({
outerRadius={outerRadius}
dataKey={chartSeries[0]?.dataKey || 'value'}
nameKey={xAxisKey}
onClick={(data, index) => handleClick(data as unknown as ChartDataPoint, index)}
onClick={(data: unknown, index: number) => handleClick(data as ChartDataPoint, index)}
cursor={onDataPointClick ? 'pointer' : 'default'}
{...animationProps}
>
Expand All @@ -335,7 +332,7 @@ export function Chart({
);

default:
return null;
return <></>;
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import Link from 'next/link';
import { Calendar, ChevronLeft, ChevronRight, MapPin, Star, Users } from 'lucide-react';
import type { Event } from '@/lib/api/events';

function formatDateShort(dateString: string) {
const date = new Date(dateString);
function formatDateShort(dateInput: string | Date) {
const date = dateInput instanceof Date ? dateInput : new Date(dateInput);
return date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
Expand All @@ -26,7 +26,7 @@ function formatDateRangeShort(start: string, end?: string | null) {
return formatDateShort(start);
}
if (endDate) {
return `${formatDateShort(start)} – ${formatDateShort(end)}`;
return `${formatDateShort(start)} – ${formatDateShort(endDate)}`;
}
return formatDateShort(start);
}
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/components/events/ScheduleBuilder.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React, { useState, useCallback, useMemo } from 'react';
import { motion, Reorder, AnimatePresence } from 'motion/react';
import { motion, Reorder, AnimatePresence } from 'framer-motion';
import { GripVertical, Clock, MapPin, Plus, Trash2, Edit3, Save, RotateCcw } from 'lucide-react';

interface Session {
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/components/events/VirtualizedEventList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import React, { useState, useEffect, useRef, useCallback, useMemo } from 'react';
import { motion, AnimatePresence } from 'motion/react';
import { motion, AnimatePresence } from 'framer-motion';
import { Calendar, MapPin, Users, Info, ChevronRight } from 'lucide-react';

interface Event {
Expand Down
13 changes: 6 additions & 7 deletions app/frontend/components/forms/CreateEventForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const TAG_SUGGESTIONS = [
'Technology',
];

const EVENT_CATEGORIES = ['conference', 'workshop', 'concert', 'hackathon', 'meetup'] as const;

// ─── Schema ───────────────────────────────────────────────────────────────────
const createEventSchema = z.object({
title: z
Expand All @@ -42,6 +44,10 @@ const createEventSchema = z.object({
maxAttendees: z
.string()
.refine(v => !isNaN(Number(v)) && Number(v) >= 1 && Number.isInteger(Number(v)), 'Must be a whole number ≥ 1'),
category: z
.string()
.refine((value) => EVENT_CATEGORIES.includes(value as (typeof EVENT_CATEGORIES)[number]), {
message: 'Please select a category',
category: z.enum(['conference', 'workshop', 'concert', 'hackathon', 'meetup', ''], {
errorMap: () => ({ message: 'Please select a category' }),
}).refine(v => v !== '', { message: 'Please select a category' }),
Expand Down Expand Up @@ -174,7 +180,6 @@ export default function CreateEventForm() {
{/* Title */}
<FormInput
label="Event Title"
name="title"
type="text"
placeholder="e.g. Stellar Dev Hackathon 2025"
required
Expand All @@ -188,7 +193,6 @@ export default function CreateEventForm() {
{/* Description */}
<FormInput
label="Description"
name="description"
as="textarea"
rows={3}
placeholder="Tell attendees what this event is about..."
Expand All @@ -202,7 +206,6 @@ export default function CreateEventForm() {
{/* Category */}
<FormInput
label="Category"
name="category"
as="select"
required
error={errors.category}
Expand Down Expand Up @@ -238,7 +241,6 @@ export default function CreateEventForm() {
<div className="grid grid-cols-2 gap-4">
<FormInput
label="Ticket Price (XLM)"
name="ticketPrice"
type="number"
min="0"
step="0.01"
Expand All @@ -251,7 +253,6 @@ export default function CreateEventForm() {
/>
<FormInput
label="Max Attendees"
name="maxAttendees"
type="number"
min="1"
step="1"
Expand All @@ -267,7 +268,6 @@ export default function CreateEventForm() {
{/* Contract Address */}
<FormInput
label="Contract Address"
name="contractAddress"
type="text"
placeholder="GABC…"
icon={<CodeIcon />}
Expand All @@ -280,7 +280,6 @@ export default function CreateEventForm() {
{/* Website URL */}
<FormInput
label="Website URL"
name="websiteUrl"
type="url"
placeholder="https://gatheraa.xyz/event"
icon={<GlobeIcon />}
Expand Down
2 changes: 1 addition & 1 deletion app/frontend/components/forms/DynamicFormBuilder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface ValidationRule {
value?: string | number;
message: string;
regex?: string;
customValidator?: (value: any) => boolean | string;
customValidator?: (value: any, allValues?: Record<string, any>) => boolean | string;
}

export interface FieldOption {
Expand Down
Loading
Loading