Improve admin access and navigation links for superadmins
Update `App.tsx` to grant superadmin access to the admin dashboard and refactor navigation links to use `Link` component from `wouter`. Modify `DatabaseStorage` in `server/storage.ts` to update user records based on email instead of ID. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 069d4324-6c40-4355-955e-c714a50de1ea Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3df548ff-50ae-432f-9be4-25d34eccc983/069d4324-6c40-4355-955e-c714a50de1ea/bVdKIaU
This commit is contained in:
4
.replit
4
.replit
@ -14,6 +14,10 @@ run = ["npm", "run", "start"]
|
|||||||
localPort = 5000
|
localPort = 5000
|
||||||
externalPort = 80
|
externalPort = 80
|
||||||
|
|
||||||
|
[[ports]]
|
||||||
|
localPort = 43349
|
||||||
|
externalPort = 3000
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
PORT = "5000"
|
PORT = "5000"
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
attached_assets/Liverpool F.C. _1759157756392.png
Normal file
BIN
attached_assets/Liverpool F.C. _1759157756392.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
BIN
attached_assets/Manchester City F.C. _1759157730506.png
Normal file
BIN
attached_assets/Manchester City F.C. _1759157730506.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.1 KiB |
BIN
attached_assets/inter milan_1759157779359.png
Normal file
BIN
attached_assets/inter milan_1759157779359.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
BIN
attached_assets/다운로드_1759157749955.png
Normal file
BIN
attached_assets/다운로드_1759157749955.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
@ -26,7 +26,7 @@ function Router() {
|
|||||||
<Route path="/media/:slug" component={MediaOutlet} />
|
<Route path="/media/:slug" component={MediaOutlet} />
|
||||||
<Route path="/articles/:slug" component={Article} />
|
<Route path="/articles/:slug" component={Article} />
|
||||||
<Route path="/auctions" component={Auctions} />
|
<Route path="/auctions" component={Auctions} />
|
||||||
{user?.role === 'admin' && (
|
{(user?.role === 'admin' || user?.role === 'superadmin') && (
|
||||||
<Route path="/admin" component={AdminDashboard} />
|
<Route path="/admin" component={AdminDashboard} />
|
||||||
)}
|
)}
|
||||||
{user?.role === 'superadmin' && (
|
{user?.role === 'superadmin' && (
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { Link } from "wouter";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { useAuth } from "@/hooks/useAuth";
|
import { useAuth } from "@/hooks/useAuth";
|
||||||
@ -39,13 +40,13 @@ export default function Home() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav className="hidden md:flex space-x-6">
|
<nav className="hidden md:flex space-x-6">
|
||||||
<a href="/" className="text-foreground hover:text-primary transition-colors">Home</a>
|
<Link href="/" className="text-foreground hover:text-primary transition-colors">Home</Link>
|
||||||
<a href="/auctions" className="text-muted-foreground hover:text-foreground transition-colors">Auctions</a>
|
<Link href="/auctions" className="text-muted-foreground hover:text-foreground transition-colors">Auctions</Link>
|
||||||
<a href="#" className="text-muted-foreground hover:text-foreground transition-colors">Predictions</a>
|
<a href="#" className="text-muted-foreground hover:text-foreground transition-colors">Predictions</a>
|
||||||
{(user?.role === 'admin' || user?.role === 'superadmin') && (
|
{(user?.role === 'admin' || user?.role === 'superadmin') && (
|
||||||
<a href={user.role === 'admin' ? '/admin' : '/superadmin'} className="text-muted-foreground hover:text-foreground transition-colors">
|
<Link href={user.role === 'admin' ? '/admin' : '/superadmin'} className="text-muted-foreground hover:text-foreground transition-colors">
|
||||||
Dashboard
|
Dashboard
|
||||||
</a>
|
</Link>
|
||||||
)}
|
)}
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@ -87,13 +88,15 @@ export default function Home() {
|
|||||||
<Button className="bg-white text-primary hover:bg-opacity-90" data-testid="button-explore">
|
<Button className="bg-white text-primary hover:bg-opacity-90" data-testid="button-explore">
|
||||||
Explore Media Outlets
|
Explore Media Outlets
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Link href="/auctions">
|
||||||
variant="outline"
|
<Button
|
||||||
className="border-white text-white hover:bg-white hover:text-primary"
|
variant="outline"
|
||||||
data-testid="button-auctions"
|
className="border-white text-white hover:bg-white hover:text-primary"
|
||||||
>
|
data-testid="button-auctions"
|
||||||
<a href="/auctions">View Active Auctions</a>
|
>
|
||||||
</Button>
|
View Active Auctions
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -129,9 +132,11 @@ export default function Home() {
|
|||||||
<div className="mt-12">
|
<div className="mt-12">
|
||||||
<div className="flex items-center justify-between mb-6">
|
<div className="flex items-center justify-between mb-6">
|
||||||
<h2 className="text-2xl font-bold">Active Media Outlet Auctions</h2>
|
<h2 className="text-2xl font-bold">Active Media Outlet Auctions</h2>
|
||||||
<Button variant="ghost" className="text-primary hover:text-primary/80 font-semibold">
|
<Link href="/auctions">
|
||||||
<a href="/auctions">View All Auctions</a>
|
<Button variant="ghost" className="text-primary hover:text-primary/80 font-semibold">
|
||||||
</Button>
|
View All Auctions
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{auctionsLoading ? (
|
{auctionsLoading ? (
|
||||||
|
|||||||
69
replit.md
Normal file
69
replit.md
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
# Overview
|
||||||
|
|
||||||
|
SAPIENS is a comprehensive media platform that aggregates news and content from various media outlets organized into three categories: People, Topics, and Companies. The platform features a sophisticated auction system for media outlet management rights, prediction markets tied to articles, and a multi-tier admin system. Users can browse media outlets, read articles, participate in prediction markets, and bid on management rights through an eBay-style auction system.
|
||||||
|
|
||||||
|
# User Preferences
|
||||||
|
|
||||||
|
Preferred communication style: Simple, everyday language.
|
||||||
|
|
||||||
|
# System Architecture
|
||||||
|
|
||||||
|
## Frontend Architecture
|
||||||
|
- **Framework**: React with TypeScript using Vite for build tooling
|
||||||
|
- **Styling**: Tailwind CSS with shadcn/ui component library for consistent design
|
||||||
|
- **Routing**: Wouter for client-side routing
|
||||||
|
- **State Management**: TanStack Query for server state and data fetching
|
||||||
|
- **Authentication**: Integrated with Replit Auth system
|
||||||
|
|
||||||
|
## Backend Architecture
|
||||||
|
- **Framework**: Express.js with TypeScript
|
||||||
|
- **Database**: PostgreSQL with Drizzle ORM for type-safe database operations
|
||||||
|
- **Authentication**: Replit-based OAuth with session management
|
||||||
|
- **API Design**: RESTful API with structured error handling
|
||||||
|
|
||||||
|
## Database Design
|
||||||
|
The system uses a PostgreSQL database with the following core entities:
|
||||||
|
- **Users**: Supports role-based access (user, admin, superadmin)
|
||||||
|
- **Media Outlets**: Categorized entities (people, topics, companies) with slugs and metadata
|
||||||
|
- **Articles**: Content with rich text, images, and association to media outlets
|
||||||
|
- **Prediction Markets**: Betting markets linked to articles with yes/no pricing
|
||||||
|
- **Auctions**: eBay-style bidding system for media outlet management rights
|
||||||
|
- **Bids**: Individual auction bids with quality scoring
|
||||||
|
- **Comments**: User-generated content on articles
|
||||||
|
|
||||||
|
## Authentication & Authorization
|
||||||
|
- **Multi-tier Access**: Three user roles with escalating permissions
|
||||||
|
- **Session Management**: PostgreSQL-backed sessions with configurable TTL
|
||||||
|
- **Route Protection**: Middleware-based authentication checks for protected routes
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
- **Category-based Navigation**: Tabbed interface for People, Topics, Companies
|
||||||
|
- **Dual View Modes**: Grid and list views for article browsing
|
||||||
|
- **Auction System**: Real-time bidding with quality score integration
|
||||||
|
- **Prediction Markets**: Integration with external prediction market APIs
|
||||||
|
- **Admin Dashboards**: Role-specific management interfaces
|
||||||
|
- **Content Management**: Rich article creation and media outlet administration
|
||||||
|
|
||||||
|
# External Dependencies
|
||||||
|
|
||||||
|
## Database & Infrastructure
|
||||||
|
- **Neon Database**: Serverless PostgreSQL hosting
|
||||||
|
- **Drizzle ORM**: Type-safe database queries and migrations
|
||||||
|
- **Replit Auth**: OAuth authentication provider
|
||||||
|
|
||||||
|
## UI & Styling
|
||||||
|
- **shadcn/ui**: Pre-built accessible UI components
|
||||||
|
- **Radix UI**: Primitive components for complex interactions
|
||||||
|
- **Tailwind CSS**: Utility-first CSS framework
|
||||||
|
- **Lucide Icons**: Icon library for consistent iconography
|
||||||
|
|
||||||
|
## Development Tools
|
||||||
|
- **Vite**: Fast build tool with HMR for development
|
||||||
|
- **TypeScript**: Type safety across the full stack
|
||||||
|
- **TanStack Query**: Server state management and caching
|
||||||
|
- **React Hook Form**: Form handling with validation
|
||||||
|
|
||||||
|
## Third-party Integrations
|
||||||
|
- **Kalshi API**: External prediction market data (referenced in user requirements)
|
||||||
|
- **Image Services**: Unsplash for placeholder images and media content
|
||||||
|
- **Session Storage**: connect-pg-simple for PostgreSQL session management
|
||||||
@ -86,9 +86,11 @@ export class DatabaseStorage implements IStorage {
|
|||||||
.insert(users)
|
.insert(users)
|
||||||
.values(userData)
|
.values(userData)
|
||||||
.onConflictDoUpdate({
|
.onConflictDoUpdate({
|
||||||
target: users.id,
|
target: users.email,
|
||||||
set: {
|
set: {
|
||||||
...userData,
|
firstName: userData.firstName,
|
||||||
|
lastName: userData.lastName,
|
||||||
|
profileImageUrl: userData.profileImageUrl,
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user