1+ 'use client' ;
2+
3+ import { useState } from 'react' ;
4+ import NextImage from 'next/image' ;
5+ import Link from 'next/link' ;
6+ import { useParams } from 'next/navigation' ;
7+ import Button from '@/app/components/ui/Button' ;
8+ import { Skeleton } from '@/app/components/ui/Skeleton' ;
9+ import {
10+ MapPin ,
11+ Star ,
12+ ShieldCheck ,
13+ Briefcase ,
14+ MessageSquare ,
15+ Image as ImageIcon ,
16+ Mail ,
17+ Users ,
18+ } from 'lucide-react' ;
19+
20+ type TabKey = 'portfolio' | 'teams' | 'services' | 'reviews' ;
21+
22+ export default function AgencyProfilePage ( ) {
23+ const params = useParams ( ) ;
24+ const agencyId = params . id as string ;
25+ const [ activeTab , setActiveTab ] = useState < TabKey > ( 'portfolio' ) ;
26+
27+ // Mock data for demonstration
28+ const agency = {
29+ id : agencyId ,
30+ name : 'Creative Minds Agency' ,
31+ tagline : 'A team of talented designers and developers' ,
32+ verified : true ,
33+ rating : 4.8 ,
34+ reviewCount : 24 ,
35+ walletAddress : 'GABC...123' ,
36+ bio : 'We are a full-service creative agency specializing in design, development, and digital marketing. Our team of 15+ professionals delivers high-quality work for clients worldwide.' ,
37+ avatar : '' ,
38+ coverImage : '' ,
39+ teams : [
40+ {
41+ id : 'team-1' ,
42+ name : 'Design Team' ,
43+ description : 'UI/UX and graphic design specialists' ,
44+ members : [
45+ { id : 'u1' , name : 'Sarah Johnson' , role : 'Lead Designer' , avatar : '' , rating : 4.9 } ,
46+ { id : 'u2' , name : 'Mike Chen' , role : 'UI Designer' , avatar : '' , rating : 4.7 } ,
47+ { id : 'u3' , name : 'Emma Wilson' , role : 'Illustrator' , avatar : '' , rating : 4.8 } ,
48+ ] ,
49+ } ,
50+ {
51+ id : 'team-2' ,
52+ name : 'Development Team' ,
53+ description : 'Full-stack developers and engineers' ,
54+ members : [
55+ { id : 'u4' , name : 'David Lee' , role : 'Tech Lead' , avatar : '' , rating : 4.9 } ,
56+ { id : 'u5' , name : 'Lisa Wang' , role : 'Frontend Developer' , avatar : '' , rating : 4.6 } ,
57+ ] ,
58+ } ,
59+ ] ,
60+ portfoliosByTeam : {
61+ 'team-1' : [
62+ { id : 'p1' , title : 'Brand Identity Package' , coverImage : '' , items : 12 , description : 'Complete brand redesign for a tech startup' , teamName : 'Design Team' } ,
63+ { id : 'p2' , title : 'Mobile App UI Design' , coverImage : '' , items : 8 , description : 'UI/UX design for fitness tracking app' , teamName : 'Design Team' } ,
64+ ] ,
65+ 'team-2' : [
66+ { id : 'p3' , title : 'E-commerce Platform' , coverImage : '' , items : 15 , description : 'Full-stack e-commerce solution' , teamName : 'Development Team' } ,
67+ ] ,
68+ } ,
69+ totalEarnings : 125000 ,
70+ teamEarnings : {
71+ 'team-1' : 75000 ,
72+ 'team-2' : 50000 ,
73+ } ,
74+ } ;
75+
76+ if ( ! agency ) {
77+ return (
78+ < div className = "min-h-screen flex items-center justify-center bg-neutral-50 dark:bg-neutral-950" >
79+ < div className = "text-center" >
80+ < div className = "w-20 h-20 bg-neutral-200 dark:bg-neutral-800 rounded-full flex items-center justify-center mx-auto mb-4" >
81+ < ImageIcon className = "w-10 h-10 text-neutral-400" />
82+ </ div >
83+ < h1 className = "text-2xl font-bold text-neutral-900 dark:text-white mb-2" >
84+ Agency Not Found
85+ </ h1 >
86+ < p className = "text-neutral-500 dark:text-neutral-400" >
87+ We couldn't find the agency you're looking for.
88+ </ p >
89+ </ div >
90+ </ div >
91+ ) ;
92+ }
93+
94+ const tabs : { key : TabKey ; label : string ; icon : React . ReactNode } [ ] = [
95+ { key : 'portfolio' , label : 'Portfolio' , icon : < Briefcase className = "w-4 h-4" /> } ,
96+ { key : 'teams' , label : 'Teams' , icon : < Users className = "w-4 h-4" /> } ,
97+ { key : 'services' , label : 'Services' , icon : < ImageIcon className = "w-4 h-4" /> } ,
98+ { key : 'reviews' , label : 'Reviews' , icon : < MessageSquare className = "w-4 h-4" /> } ,
99+ ] ;
100+
101+ const allPortfolios = Object . values ( agency . portfoliosByTeam ) . flat ( ) ;
102+
103+ return (
104+ < div className = "min-h-screen bg-neutral-50 dark:bg-neutral-950" >
105+ { /* Cover Image */ }
106+ < div className = "relative h-56 sm:h-72 bg-gradient-to-r from-primary-600 via-primary-700 to-secondary-600" >
107+ { agency . coverImage && (
108+ < img
109+ src = { agency . coverImage }
110+ alt = { `${ agency . name } cover` }
111+ className = "w-full h-full object-cover"
112+ />
113+ ) }
114+ < div className = "absolute inset-0 bg-gradient-to-t from-black/40 to-transparent" />
115+ </ div >
116+
117+ < div className = "max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 -mt-20 relative z-10" >
118+ { /* Profile Header */ }
119+ < div className = "flex flex-col sm:flex-row sm:items-end gap-4 sm:gap-6" >
120+ { /* Avatar */ }
121+ < div className = "relative w-32 h-32 sm:w-36 sm:h-36 rounded-full border-4 border-white dark:border-neutral-900 overflow-hidden bg-neutral-200 dark:bg-neutral-700 shadow-lg flex-shrink-0" >
122+ { agency . avatar ? (
123+ < NextImage
124+ src = { agency . avatar }
125+ alt = { agency . name }
126+ fill
127+ className = "object-cover"
128+ sizes = "144px"
129+ />
130+ ) : (
131+ < div className = "w-full h-full flex items-center justify-center text-neutral-400" >
132+ < Building2 className = "w-12 h-12" />
133+ </ div >
134+ ) }
135+ </ div >
136+
137+ { /* Name & Info */ }
138+ < div className = "flex-1 pb-2" >
139+ < div className = "flex items-center gap-3 flex-wrap" >
140+ < h1 className = "text-2xl sm:text-3xl font-bold text-neutral-900 dark:text-white" >
141+ { agency . name }
142+ < span className = "ml-2 text-sm px-2 py-0.5 bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 rounded-full" >
143+ Agency
144+ </ span >
145+ </ h1 >
146+ { agency . verified && (
147+ < span className = "inline-flex items-center gap-1 px-2 py-0.5 bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-400 text-xs font-medium rounded-full" >
148+ < ShieldCheck className = "w-3.5 h-3.5" />
149+ Verified
150+ </ span >
151+ ) }
152+ </ div >
153+ { agency . tagline && (
154+ < p className = "text-neutral-600 dark:text-neutral-400 mt-1 text-lg" >
155+ { agency . tagline }
156+ </ p >
157+ ) }
158+ < div className = "flex items-center gap-4 mt-2 flex-wrap" >
159+ < div className = "flex items-center gap-1 text-amber-500" >
160+ < Star className = "w-4 h-4 fill-current" />
161+ < span className = "text-sm font-medium text-neutral-700 dark:text-neutral-300" >
162+ { agency . rating ?. toFixed ( 1 ) || '—' }
163+ </ span >
164+ < span className = "text-sm text-neutral-400" >
165+ ({ agency . reviewCount || 0 } reviews)
166+ </ span >
167+ </ div >
168+ < span className = "text-sm text-neutral-400 flex items-center gap-1" >
169+ < Users className = "w-3.5 h-3.5" />
170+ { agency . teams . reduce ( ( acc , team ) => acc + team . members . length , 0 ) } team members
171+ </ span >
172+ { agency . walletAddress && (
173+ < span className = "text-sm text-neutral-400 flex items-center gap-1" >
174+ < MapPin className = "w-3.5 h-3.5" />
175+ Stellar Wallet Connected
176+ </ span >
177+ ) }
178+ </ div >
179+ </ div >
180+
181+ { /* CTA Buttons */ }
182+ < div className = "flex gap-2 sm:pb-2 mt-3 sm:mt-0" >
183+ < Button variant = "primary" size = "md" >
184+ < Mail className = "w-4 h-4 mr-2" />
185+ Contact Agency
186+ </ Button >
187+ < Link
188+ href = { `/commissions/new?agencyId=${ agency . id } &agencyName=${ encodeURIComponent ( agency . name ) } ` }
189+ className = "inline-flex items-center justify-center rounded-xl border-2 border-primary-700 px-4 py-2 text-sm font-medium text-primary-700 transition-colors hover:bg-primary-50 dark:hover:bg-primary-900/20"
190+ >
191+ Start a Project
192+ </ Link >
193+ </ div >
194+ </ div >
195+
196+ { /* Teams Count Badge */ }
197+ < div className = "flex flex-wrap gap-2 mt-5" >
198+ < span className = "px-3 py-1 bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-400 text-xs font-medium rounded-full" >
199+ { agency . teams . length } teams
200+ </ span >
201+ { agency . teams . map ( ( team ) => (
202+ < span
203+ key = { team . id }
204+ className = "px-3 py-1 bg-neutral-100 dark:bg-neutral-800 text-neutral-600 dark:text-neutral-300 text-xs font-medium rounded-full"
205+ >
206+ { team . name } : { team . members . length } members
207+ </ span >
208+ ) ) }
209+ </ div >
210+
211+ { /* Bio */ }
212+ { agency . bio && (
213+ < p className = "mt-4 text-neutral-600 dark:text-neutral-400 leading-relaxed max-w-3xl" >
214+ { agency . bio }
215+ </ p >
216+ ) }
217+
218+ { /* Tabs Navigation */ }
219+ < div className = "mt-8 border-b border-neutral-200 dark:border-neutral-800" >
220+ < nav className = "flex gap-0 -mb-px" role = "tablist" >
221+ { tabs . map ( ( tab ) => (
222+ < button
223+ key = { tab . key }
224+ role = "tab"
225+ aria-selected = { activeTab === tab . key }
226+ onClick = { ( ) => setActiveTab ( tab . key ) }
227+ className = { `inline-flex items-center gap-2 px-5 py-3 text-sm font-medium border-b-2 transition-colors ${ activeTab === tab . key
228+ ? 'border-primary-600 text-primary-600 dark:text-primary-400'
229+ : 'border-transparent text-neutral-500 hover:text-neutral-700 dark:hover:text-neutral-300 hover:border-neutral-300 dark:hover:border-neutral-600'
230+ } `}
231+ >
232+ { tab . icon }
233+ { tab . label }
234+ </ button >
235+ ) ) }
236+ </ nav >
237+ </ div >
238+
239+ { /* Tab Content */ }
240+ < div className = "py-8" >
241+ { activeTab === 'portfolio' && (
242+ < PortfolioTab portfoliosByTeam = { agency . portfoliosByTeam } />
243+ ) }
244+ { activeTab === 'teams' && (
245+ < TeamsTab teams = { agency . teams } teamEarnings = { agency . teamEarnings } />
246+ ) }
247+ { activeTab === 'services' && (
248+ < div className = "text-center py-16" >
249+ < FolderOpen className = "w-16 h-16 text-neutral-400 mx-auto mb-4" />
250+ < h3 className = "text-lg font-semibold text-neutral-700 dark:text-neutral-300 mb-1" >
251+ Services coming soon
252+ </ h3 >
253+ </ div >
254+ ) }
255+ { activeTab === 'reviews' && (
256+ < div className = "text-center py-16" >
257+ < MessageSquare className = "w-16 h-16 text-neutral-400 mx-auto mb-4" />
258+ < h3 className = "text-lg font-semibold text-neutral-700 dark:text-neutral-300 mb-1" >
259+ Reviews & Ratings
260+ </ h3 >
261+ < p className = "text-neutral-500" > Team ratings and client reviews will appear here</ p >
262+ </ div >
263+ ) }
264+ </ div >
265+ </ div >
266+ </ div >
267+ ) ;
268+ }
269+
270+ function PortfolioTab ( { portfoliosByTeam } : { portfoliosByTeam : any } ) {
271+ return (
272+ < div className = "space-y-12" >
273+ { Object . entries ( portfoliosByTeam ) . map ( ( [ teamId , portfolios ] : [ string , any [ ] ] ) => (
274+ < div key = { teamId } className = "border-b border-neutral-200 dark:border-neutral-800 pb-10 last:border-0" >
275+ < h3 className = "text-xl font-bold text-neutral-900 dark:text-white mb-6 flex items-center gap-2" >
276+ < Briefcase className = "w-5 h-5 text-primary-500" />
277+ { portfolios [ 0 ] ?. teamName || 'Team' } Portfolio
278+ </ h3 >
279+ < div className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6" >
280+ { portfolios . map ( ( portfolio : any ) => (
281+ < Link
282+ key = { portfolio . id }
283+ href = { `/portfolios/${ portfolio . id } ` }
284+ className = "group bg-white dark:bg-neutral-900 rounded-2xl overflow-hidden border border-neutral-200 dark:border-neutral-800 hover:border-primary-300 dark:hover:border-primary-700 hover:shadow-lg transition-all duration-300"
285+ >
286+ < div className = "relative h-48 bg-neutral-100 dark:bg-neutral-800 overflow-hidden" >
287+ { portfolio . coverImage ? (
288+ < img
289+ src = { portfolio . coverImage }
290+ alt = { portfolio . title }
291+ className = "w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
292+ />
293+ ) : (
294+ < div className = "w-full h-full flex items-center justify-center" >
295+ < Image className = "w-12 h-12 text-neutral-300 dark:text-neutral-600" />
296+ </ div >
297+ ) }
298+ < div className = "absolute top-3 right-3" >
299+ < span className = "px-2.5 py-1 bg-white/90 dark:bg-neutral-900/90 backdrop-blur-sm text-xs font-medium text-neutral-600 dark:text-neutral-300 rounded-full" >
300+ { portfolio . items ?. length || 0 } items
301+ </ span >
302+ </ div >
303+ </ div >
304+ < div className = "p-4" >
305+ < h3 className = "font-semibold text-neutral-900 dark:text-white group-hover:text-primary-600 dark:group-hover:text-primary-400 transition-colors line-clamp-1" >
306+ { portfolio . title }
307+ </ h3 >
308+ < p className = "text-sm text-neutral-500 dark:text-neutral-400 mt-1 line-clamp-2" >
309+ { portfolio . description }
310+ </ p >
311+ </ div >
312+ </ Link >
313+ ) ) }
314+ </ div >
315+ </ div >
316+ ) ) }
317+ </ div >
318+ ) ;
319+ }
320+
321+ function TeamsTab ( { teams, teamEarnings } : { teams : any [ ] , teamEarnings : any } ) {
322+ return (
323+ < div className = "space-y-8" >
324+ { teams . map ( ( team ) => (
325+ < div key = { team . id } className = "bg-white dark:bg-neutral-900 rounded-2xl p-6 border border-neutral-200 dark:border-neutral-800" >
326+ < div className = "flex items-start justify-between mb-6" >
327+ < div >
328+ < h3 className = "text-xl font-bold text-neutral-900 dark:text-white" > { team . name } </ h3 >
329+ < p className = "text-neutral-500 dark:text-neutral-400 mt-1" > { team . description } </ p >
330+ </ div >
331+ < div className = "text-right" >
332+ < p className = "text-sm text-neutral-500 dark:text-neutral-400" > Team Earnings</ p >
333+ < p className = "text-2xl font-bold text-emerald-600" > ${ teamEarnings [ team . id ] ?. toLocaleString ( ) || 0 } </ p >
334+ </ div >
335+ </ div >
336+
337+ < h4 className = "text-sm font-semibold text-neutral-700 dark:text-neutral-300 mb-4" > Team Members ({ team . members . length } )</ h4 >
338+ < div className = "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4" >
339+ { team . members . map ( ( member : any ) => (
340+ < Link
341+ key = { member . id }
342+ href = { `/artists/${ member . id } ` }
343+ className = "flex items-center gap-4 p-4 bg-neutral-50 dark:bg-neutral-800 rounded-xl hover:bg-neutral-100 dark:hover:bg-neutral-750 transition-colors"
344+ >
345+ < div className = "w-12 h-12 rounded-full bg-neutral-200 dark:bg-neutral-700 overflow-hidden flex-shrink-0" >
346+ { member . avatar ? (
347+ < img src = { member . avatar } alt = { member . name } className = "w-full h-full object-cover" />
348+ ) : (
349+ < div className = "w-full h-full flex items-center justify-center" >
350+ < User className = "w-6 h-6 text-neutral-400" />
351+ </ div >
352+ ) }
353+ </ div >
354+ < div className = "min-w-0" >
355+ < p className = "font-medium text-neutral-900 dark:text-white truncate" > { member . name } </ p >
356+ < p className = "text-sm text-neutral-500 dark:text-neutral-400 truncate" > { member . role } </ p >
357+ < div className = "flex items-center gap-1 mt-1" >
358+ < Star className = "w-3 h-3 fill-current text-amber-500" />
359+ < span className = "text-xs text-neutral-600 dark:text-neutral-400" > { member . rating } </ span >
360+ </ div >
361+ </ div >
362+ </ Link >
363+ ) ) }
364+ </ div >
365+ </ div >
366+ ) ) }
367+ </ div >
368+ ) ;
369+ }
0 commit comments