Skip to content

Commit eb73368

Browse files
chore: profile UI completed
1 parent a862cb5 commit eb73368

File tree

1 file changed

+141
-77
lines changed

1 file changed

+141
-77
lines changed

src/lib/ui.py

Lines changed: 141 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,102 @@ def create_recent_activity(recent_submissions):
1919
box=box.ROUNDED,
2020
border_style="cyan",
2121
pad_edge=False,
22-
show_edge=True
22+
show_edge=True,
23+
width=65
2324
)
24-
2525
table.add_column("Time", style="dim", width=16)
2626
table.add_column("Problem", style="cyan")
27-
table.add_column("Status", justify="center", width=8)
2827

2928
for sub in recent_submissions['recentAcSubmissionList'][:5]:
3029
table.add_row(
3130
format_timestamp(int(sub['timestamp'])),
3231
sub['title'],
33-
"[green]✓"
3432
)
33+
return table
34+
35+
def create_progress_panel(data):
36+
if not data.get('progress'):
37+
return None
38+
39+
progress = data['progress']
40+
all_count = progress['allQuestionsCount']
41+
submit_stats = progress['matchedUser']['submitStats']
42+
table = Table.grid(padding=(0, 1))
43+
table.add_column(justify="left")
44+
45+
for diff in ['Easy', 'Medium', 'Hard']:
46+
total = next((q['count'] for q in all_count if q['difficulty'] == diff), 0)
47+
solved = next((s['count'] for s in submit_stats['acSubmissionNum'] if s['difficulty'] == diff), 0)
48+
table.add_row(f"[dim]{diff}:[/dim] {solved}/{total}")
49+
50+
return Panel(table, title="[bold green]Progress[/bold green]", border_style="green")
51+
52+
def create_social_links(user, websites=None):
53+
links = []
54+
if user['githubUrl']:
55+
links.append(f"[blue]GitHub[/blue]: {user['githubUrl']}")
56+
if user['linkedinUrl']:
57+
links.append(f"[blue]LinkedIn[/blue]: {user['linkedinUrl']}")
58+
if user['twitterUrl']:
59+
links.append(f"[blue]Twitter[/blue]: {user['twitterUrl']}")
60+
61+
if websites:
62+
for site in websites:
63+
url = f"https://{site}" if not site.startswith(('http://', 'https://')) else site
64+
links.append(f"[blue]Website[/blue]: {url}")
65+
66+
return "\n".join(links) if links else "No social links"
67+
68+
def create_language_stats(data):
69+
if not data or 'matchedUser' not in data:
70+
return None
71+
72+
lang_stats = data['matchedUser']['languageProblemCount']
73+
table = Table.grid(padding=(0, 1))
74+
table.add_column(justify="left")
75+
rows = []
76+
sorted_stats = sorted(lang_stats, key=lambda x: x['problemsSolved'], reverse=True)
77+
78+
for lang in sorted_stats[:5]:
79+
rows.append(f"[dim]{lang['languageName']}:[/dim] {lang['problemsSolved']}")
80+
81+
table.add_row("\n".join(rows))
82+
return Panel(table, title="[bold blue]Languages[/bold blue]", border_style="blue", width=35, padding=(0, 1))
83+
84+
def create_contest_stats(contest_info):
85+
stats = []
86+
rating = contest_info.get('userContestRanking', {}).get('rating', 0)
87+
attended = contest_info.get('userContestRanking', {}).get('attendedContestsCount', 0)
88+
stats.append(f"[dim]Rating:[/dim] {rating:.1f}")
89+
stats.append(f"[dim]Contests:[/dim] {attended}")
90+
return "\n".join(stats)
91+
92+
def create_skill_stats(data):
93+
if not data.get('skillStats'):
94+
return None
95+
96+
skills = data['skillStats']['matchedUser']['tagProblemCounts']
97+
table = Table(
98+
title="[bold magenta]Skills[/bold magenta]",
99+
box=box.ROUNDED,
100+
border_style="magenta",
101+
width=65,
102+
pad_edge=False
103+
)
104+
table.add_column("Level", style="magenta")
105+
table.add_column("Tag", style="cyan")
106+
table.add_column("Solved", justify="right")
107+
108+
for level in ['advanced', 'intermediate', 'fundamental']:
109+
for skill in skills[level][:2]:
110+
table.add_row(level.capitalize(), skill['tagName'], str(skill['problemsSolved']))
35111

36112
return table
37113

38114
def display_user_stats(data):
39115
console.clear()
40-
width = min(console.width - 4, 150) # Limit max width
41-
first_width = width // 3 - 2
42-
second_width = (width * 2) // 3 - 2
116+
width = min(console.width - 4, 180)
117+
profile_width, stats_width, progress_width = 65, 35, 30
43118

44119
if not data.get('userProfile'):
45120
console.print(Panel("Could not fetch user profile", border_style="red"))
@@ -48,88 +123,77 @@ def display_user_stats(data):
48123
user = data['userProfile']['matchedUser']
49124
profile = user['profile']
50125

51-
# Create main profile info
52126
profile_table = Table.grid(padding=(0, 1))
53127
profile_table.add_column(justify="left")
54128
profile_info = [
55-
f"[bold cyan]{user['username']}[/bold cyan]",
56-
f"[dim]Ranking:[/dim] {profile['ranking']}",
57-
f"[dim]Company:[/dim] {profile['company'] or 'Not specified'}",
58-
f"[dim]Location:[/dim] {profile['countryName'] or 'Not specified'}"
129+
f"[bold cyan]{user.get('username', 'N/A')}[/bold cyan]",
130+
f"[dim]Name:[/dim] {profile.get('realName') or 'Not specified'}",
131+
f"[dim]Ranking:[/dim] {profile.get('ranking', 'N/A')}",
59132
]
60-
if profile['skillTags']:
61-
skills = ", ".join(profile['skillTags'])
62-
profile_info.append(f"[dim]Skills:[/dim] {skills}")
63-
profile_table.add_row("\n".join(profile_info))
64133

65-
# Create contest stats if available
66-
contest_panel = None
67-
if data.get('contestInfo') and data['contestInfo'].get('userContestRanking'):
68-
contest = data['contestInfo']['userContestRanking']
69-
contest_table = Table.grid(padding=(0, 1))
70-
contest_table.add_column(justify="left")
71-
contest_table.add_row(
72-
f"[yellow]Rating: {contest['rating']}[/yellow]\n"
73-
f"Global Rank: {contest['globalRanking']}\n"
74-
f"Top: {contest['topPercentage']}%\n"
75-
f"Contests: {contest['attendedContestsCount']}"
76-
)
77-
contest_panel = Panel(
78-
contest_table,
79-
title="[bold yellow]Contest Stats[/bold yellow]",
80-
border_style="yellow",
81-
width=second_width
82-
)
134+
for label, field in [('Company', 'company'), ('Job Title', 'jobTitle'),
135+
('School', 'school'), ('Location', 'countryName')]:
136+
if field in profile and profile[field]:
137+
profile_info.append(f"[dim]{label}:[/dim] {profile[field]}")
83138

84-
# Create top row grid
85-
top_grid = Table.grid(padding=(0, 2))
86-
top_grid.add_column(width=first_width)
87-
top_grid.add_column(width=second_width)
88-
top_grid.add_row(
89-
Panel(profile_table, title="[bold cyan]Profile Info[/bold cyan]", border_style="cyan"),
90-
contest_panel or ""
91-
)
92-
console.print("\n")
93-
console.print(top_grid)
94-
console.print("\n")
139+
if profile.get('skillTags'):
140+
profile_info.append(f"[dim]Skills:[/dim] {', '.join(profile['skillTags'])}")
95141

96-
# Create bottom row grid
97-
bottom_grid = Table.grid(padding=(0, 2))
98-
bottom_grid.add_column(width=first_width)
99-
bottom_grid.add_column(width=second_width)
142+
social_links = create_social_links(user, profile.get('websites', []))
143+
if social_links != "No social links":
144+
profile_info.append("\n" + social_links)
145+
146+
profile_table.add_row("\n".join(profile_info))
147+
profile_panel = Panel(profile_table, title="[bold cyan]Profile Info[/bold cyan]",
148+
border_style="cyan", width=profile_width, padding=(0, 1))
149+
150+
stats_table = Table.grid(padding=(0, 1))
151+
stats_table.add_column(justify="left")
152+
stats = [
153+
f"[dim]Solutions:[/dim] {profile.get('solutionCount', 0)} ({profile.get('solutionCountDiff', 0):+d})",
154+
f"[dim]Reputation:[/dim] {profile.get('reputation', 0)} ({profile.get('reputationDiff', 0):+d})",
155+
f"[dim]Views:[/dim] {profile.get('postViewCount', 0)} ({profile.get('postViewCountDiff', 0):+d})",
156+
]
157+
if 'categoryDiscussCount' in profile:
158+
stats.append(f"[dim]Discussions:[/dim] {profile['categoryDiscussCount']} ({profile.get('categoryDiscussCountDiff', 0):+d})")
159+
stats_table.add_row("\n".join(stats))
160+
161+
progress = create_progress_panel(data)
162+
if progress:
163+
progress.width = progress_width
100164

101-
# Language stats
102-
lang_panel = None
165+
middle_column = Table.grid(padding=(0, 1))
103166
if data.get('languageStats'):
104-
lang_stats = data['languageStats']['matchedUser']['languageProblemCount']
105-
lang_table = Table(
106-
title="[bold cyan]Languages[/bold cyan]",
107-
box=box.ROUNDED,
108-
border_style="cyan",
109-
padding=(0, 1),
110-
width=first_width
111-
)
112-
lang_table.add_column("Language", style="cyan")
113-
lang_table.add_column("Solved", justify="right")
114-
115-
for lang in sorted(lang_stats, key=lambda x: x['problemsSolved'], reverse=True)[:5]:
116-
lang_table.add_row(
117-
lang['languageName'],
118-
str(lang['problemsSolved'])
119-
)
120-
lang_panel = lang_table
121-
122-
# Recent submissions
123-
recent_panel = None
124-
if data.get('recentAcSubmissions'):
125-
recent_table = create_recent_activity(data['recentAcSubmissions'])
126-
if recent_table:
127-
recent_panel = recent_table
167+
middle_column.add_row(create_language_stats(data['languageStats']))
168+
middle_column.add_row("")
169+
if data.get('contestInfo'):
170+
contest_panel = Panel(create_contest_stats(data['contestInfo']),
171+
title="[bold yellow]Contest Stats[/bold yellow]",
172+
border_style="yellow", width=stats_width, padding=(0, 1))
173+
middle_column.add_row(contest_panel)
174+
175+
right_column = Table.grid()
176+
if progress:
177+
right_column.add_row(progress)
178+
right_column.add_row("")
179+
stats_panel = Panel(stats_table, title="[bold blue]Activity Stats[/bold blue]",
180+
border_style="blue", width=progress_width, padding=(0, 1))
181+
right_column.add_row(stats_panel)
182+
183+
top_grid = Table.grid(padding=(0, 2))
184+
top_grid.add_row(profile_panel, middle_column, right_column)
128185

186+
bottom_grid = Table.grid(padding=(0, 2))
187+
bottom_grid.add_column(width=65)
188+
bottom_grid.add_column(width=65)
129189
bottom_grid.add_row(
130-
lang_panel or "",
131-
recent_panel or ""
190+
create_skill_stats(data) if data.get('skillStats') else "",
191+
create_recent_activity(data['recentAcSubmissions']) if data.get('recentAcSubmissions') else ""
132192
)
193+
194+
console.print("\n")
195+
console.print(top_grid)
196+
console.print("\n")
133197
console.print(bottom_grid)
134198
console.print("\n")
135199

0 commit comments

Comments
 (0)