Skip to content

Commit 4e2796c

Browse files
authored
Merge branch 'recodehive:main' into main
2 parents 8a6d664 + 10a3af9 commit 4e2796c

File tree

9 files changed

+268
-72
lines changed

9 files changed

+268
-72
lines changed

.github/CODEOWNERS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# Assign @octocat as the owner for all files
2-
* @sanjay-kv @iitzIrFan
2+
* @sanjay-kv @iitzIrFan @Adez017

.github/workflows/pr-issue-sync.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
id: extract
1818
uses: actions/github-script@v7
1919
with:
20-
github-token: ${{ secrets.GITHUB_TOKEN }}
20+
github-token: ${{ secrets.GITHUB_TOKEN }}
2121
script: |
2222
const body = context.payload.pull_request.body || "";
2323
const issuePattern = /#(\d+)/g;
@@ -32,6 +32,7 @@ jobs:
3232
if: steps.extract.outputs.issues && steps.extract.outputs.issues != '[]'
3333
uses: actions/github-script@v7
3434
with:
35+
github-token: ${{ secrets.GITHUB_TOKEN }}
3536
script: |
3637
const issues = JSON.parse(`${{ steps.extract.outputs.issues }}`);
3738
const prNumber = context.payload.pull_request.number;
@@ -77,7 +78,6 @@ jobs:
7778
const existingComment = comments.data.find(c => c.body.includes("### Synced data from Linked Issues"));
7879
7980
if (existingComment) {
80-
// Update existing comment
8181
await github.rest.issues.updateComment({
8282
...context.repo,
8383
comment_id: existingComment.id,

src/components/header/header.css

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -104,24 +104,14 @@ html.theme-dark .chh__header-content p {
104104
gap: 1rem;
105105
}
106106

107-
.chh__header-content__input--link {
107+
.chh__header-content__input--button {
108108
text-decoration: none;
109109
font-size: 20px;
110110
line-height: 28px;
111111
font-weight: 600;
112112
color: black;
113-
}
114-
115-
.chh__header-content__input--link:hover {
116-
text-decoration: none;
117-
color:#121212;
118-
}
119-
120-
.chh__header-content__input button {
121-
flex: 1;
113+
width: 100%;
122114
min-height: 56px;
123-
font-weight: 600;
124-
font-size: 18px;
125115
border: none;
126116
cursor: pointer;
127117
outline: none;
@@ -131,9 +121,12 @@ html.theme-dark .chh__header-content p {
131121
position: relative;
132122
overflow: hidden;
133123
z-index: 1;
124+
display: flex;
125+
align-items: center;
126+
justify-content: center;
134127
}
135128

136-
.chh__header-content__input button::after {
129+
.chh__header-content__input--button::after {
137130
content: "";
138131
position: absolute;
139132
top: 0;
@@ -151,53 +144,62 @@ html.theme-dark .chh__header-content p {
151144
pointer-events: none;
152145
}
153146

154-
.chh__header-content__input button:hover::after {
147+
.chh__header-content__input--button:hover::after {
155148
left: 100%;
156149
}
157150

158-
.chh__header-content__input button:hover {
151+
.chh__header-content__input--button:hover {
159152
transform: scale(1.03); /* very subtle lift */
153+
text-decoration: none;
160154
}
161155

162-
.chh__header-content__input button:first-child {
156+
.chh__header-content__input div:first-child .chh__header-content__input--button {
163157
background: linear-gradient(135deg, #fda085 0%, #f6d365 100%);
164158
}
165159

166-
.chh__header-content__input button:first-child:hover {
160+
.chh__header-content__input div:first-child .chh__header-content__input--button:hover {
167161
background: linear-gradient(135deg, #f76b1c 0%, #fca65f 100%);
168162
transform: translateY(-2px);
169163
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
164+
text-decoration: none;
165+
color: black;
170166
}
171167

172-
[data-theme='dark'] .chh__header-content__input button:first-child {
168+
[data-theme='dark'] .chh__header-content__input div:first-child .chh__header-content__input--button {
173169
background: linear-gradient(135deg, #9b4d89 0%, #6b3a9c 100%);
174170
}
175171

176-
[data-theme='dark'] .chh__header-content__input button:first-child:hover {
172+
[data-theme='dark'] .chh__header-content__input div:first-child .chh__header-content__input--button:hover {
177173
background: linear-gradient(135deg, #b45ea5 0%, #8050c4 100%);
178174
transform: translateY(-2px) scale(1.02);
179175
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
176+
text-decoration: none;
177+
color: white;
180178
}
181179

182-
.chh__header-content__input button:last-child {
180+
.chh__header-content__input div:last-child .chh__header-content__input--button {
183181
background: linear-gradient(135deg, #a18cd1 0%, #fbc2eb 100%);
184182
}
185183

186-
.chh__header-content__input button:last-child:hover {
184+
.chh__header-content__input div:last-child .chh__header-content__input--button:hover {
187185
background: linear-gradient(135deg, #ae8dca 0%, #b3a7cb 100%);
188186
transform: translateY(-2px);
189187
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
188+
text-decoration: none;
189+
color: black;
190190
}
191191

192-
[data-theme='dark'] .chh__header-content__input button:last-child {
192+
[data-theme='dark'] .chh__header-content__input div:last-child .chh__header-content__input--button {
193193
background: linear-gradient(135deg, #2c2c36 0%, #3d3d4f 100%);
194194
color: #e0e0e0;
195195
}
196196

197-
[data-theme='dark'] .chh__header-content__input button:last-child:hover {
197+
[data-theme='dark'] .chh__header-content__input div:last-child .chh__header-content__input--button:hover {
198198
background: linear-gradient(135deg, #3d3d4f 0%, #50506b 100%);
199199
transform: translateY(-2px) scale(1.02);
200200
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
201+
text-decoration: none;
202+
color: #e0e0e0;
201203
}
202204

203205
.chh__header-image {

src/components/header/header.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const HeaderContent = () => {
4141
</motion.p>
4242

4343
<div className="chh__header-content__input">
44-
<motion.button
44+
<motion.div
4545
initial={{ opacity: 0, x: -10 }}
4646
whileInView={{ opacity: 1, x: 0 }}
4747
viewport={{ once: true }}
@@ -51,14 +51,14 @@ const HeaderContent = () => {
5151
stiffness: 100,
5252
delay: 0.3,
5353
}}
54-
type="button"
54+
style={{ flex: 1 }}
5555
>
56-
<Link to="/get-started/" className="chh__header-content__input--link">
56+
<Link to="/get-started/" className="chh__header-content__input--button">
5757
Get Started
5858
</Link>
59-
</motion.button>
59+
</motion.div>
6060

61-
<motion.button
61+
<motion.div
6262
initial={{ opacity: 0, x: 10 }}
6363
whileInView={{ opacity: 1, x: 0 }}
6464
viewport={{ once: true }}
@@ -68,12 +68,12 @@ const HeaderContent = () => {
6868
stiffness: 100,
6969
delay: 0.2,
7070
}}
71-
type="button"
71+
style={{ flex: 1 }}
7272
>
73-
<Link to="/courses" className="chh__header-content__input--link">
73+
<Link to="/courses" className="chh__header-content__input--button">
7474
Courses
7575
</Link>
76-
</motion.button>
76+
</motion.div>
7777
</div>
7878
</div>
7979
);

src/lib/statsProvider.tsx

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ interface PRDetails {
4848
mergedAt: string;
4949
repoName: string;
5050
number: number;
51+
points: number;
5152
}
5253

5354
interface Contributor {
@@ -75,6 +76,7 @@ interface PullRequestItem {
7576
title?: string;
7677
html_url?: string;
7778
number?: number;
79+
labels?: Array<{ name: string }>;
7880
}
7981

8082
// Enhanced contributor type for internal processing (stores all PRs)
@@ -96,6 +98,33 @@ const MAX_CONCURRENT_REQUESTS = 8;
9698
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes cache
9799
const MAX_PAGES_PER_REPO = 20;
98100

101+
// Function to calculate points based on PR labels
102+
const calculatePointsForPR = (labels?: Array<{ name: string }>): number => {
103+
if (!labels || labels.length === 0) {
104+
return 0; // No points if no labels
105+
}
106+
107+
const labelNames = labels.map(label => label.name.toLowerCase());
108+
109+
// Check if PR has the "recode" label
110+
if (!labelNames.includes('recode')) {
111+
return 0; // No points if "recode" label is missing
112+
}
113+
114+
// Check for level labels and assign points accordingly with new point system
115+
const levelPointsMap: { [key: string]: number } = {
116+
'level 1': 10,
117+
'level 2': 30,
118+
'level 3': 50,
119+
};
120+
const matchedLevel = labelNames.find(label => levelPointsMap.hasOwnProperty(label));
121+
if (matchedLevel) {
122+
return levelPointsMap[matchedLevel];
123+
}
124+
125+
return 0; // No points if no level label
126+
};
127+
99128
// Time filter utility functions
100129
const getTimeFilterDate = (filter: TimeFilter): Date | null => {
101130
const now = new Date();
@@ -163,11 +192,14 @@ export function CommunityStatsProvider({ children }: CommunityStatsProviderProps
163192
isPRInTimeRange(pr.mergedAt, currentTimeFilter)
164193
);
165194

195+
// Calculate total points from all filtered PRs
196+
const totalPoints = filteredPRs.reduce((sum, pr) => sum + pr.points, 0);
197+
166198
return {
167199
username: contributor.username,
168200
avatar: contributor.avatar,
169201
profile: contributor.profile,
170-
points: filteredPRs.length * POINTS_PER_PR,
202+
points: totalPoints,
171203
prs: filteredPRs.length,
172204
prDetails: filteredPRs, // For backward compatibility, though we'll use the new function
173205
};
@@ -319,6 +351,9 @@ export function CommunityStatsProvider({ children }: CommunityStatsProviderProps
319351
}
320352
const contributor = contributorMap.get(username)!;
321353

354+
// Calculate points for this PR based on labels
355+
const prPoints = calculatePointsForPR(pr.labels);
356+
322357
// Add detailed PR information to the full list
323358
if (pr.title && pr.html_url && pr.merged_at && pr.number) {
324359
contributor.allPRDetails.push({
@@ -327,6 +362,7 @@ export function CommunityStatsProvider({ children }: CommunityStatsProviderProps
327362
mergedAt: pr.merged_at,
328363
repoName,
329364
number: pr.number,
365+
points: prPoints,
330366
});
331367
}
332368
});

src/pages/podcasts/details.css

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,15 @@ html[data-theme='light'] {
206206
justify-content: center;
207207
}
208208

209+
.nav-action-button:active {
210+
box-shadow: 0 1px 8px rgba(40,50,70,0.06);
211+
}
212+
213+
.nav-action-button.favorite.favorited {
214+
color: #ff4d4d; /* red heart */
215+
background: #fff0f0; /* soft pink background when liked */
216+
}
217+
209218
.nav-action-button:hover {
210219
background: var(--details-bg-card-hover);
211220
color: var(--details-text-primary);

src/pages/podcasts/details.tsx

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import Layout from '@theme/Layout';
33
import type { ReactElement } from 'react';
44
import { useLocation, useHistory } from '@docusaurus/router';
@@ -85,7 +85,26 @@ export default function PodcastDetails(): ReactElement {
8585
const history = useHistory();
8686
const state = location.state as LocationState;
8787
const podcast = state?.podcast;
88-
88+
89+
const [favorites, setFavorites] = useState<string[]>(() => {
90+
if (typeof window !== "undefined") {
91+
const saved = localStorage.getItem("podcast-favorites");
92+
return saved ? JSON.parse(saved) : [];
93+
}
94+
return [];
95+
});
96+
const isFavorited = podcast ? favorites.includes(podcast.id) : false;
97+
const toggleFavorite = () => {
98+
if (!podcast) return;
99+
setFavorites(prev => {
100+
const updated = prev.includes(podcast.id)
101+
? prev.filter(id => id !== podcast.id)
102+
: [...prev, podcast.id];
103+
localStorage.setItem("podcast-favorites", JSON.stringify(updated));
104+
return updated;
105+
});
106+
};
107+
89108
// Enhanced descriptions with categories
90109
const descriptions = {
91110
episode: [
@@ -128,7 +147,7 @@ export default function PodcastDetails(): ReactElement {
128147
history.goBack();
129148
};
130149

131-
const handleShare = async () => {
150+
const handleShare = async (podcast?: PodcastData) => {
132151
if (navigator.share) {
133152
try {
134153
await navigator.share({
@@ -174,13 +193,25 @@ export default function PodcastDetails(): ReactElement {
174193
<span className="nav-text">Back to Podcasts</span>
175194
</button>
176195
<div className="nav-actions">
177-
<button className="nav-action-button" onClick={handleShare} title="Share">
178-
<span className="action-icon">🔗</span>
179-
</button>
180-
<button className="nav-action-button" title="Add to favorites">
181-
<span className="action-icon">❤️</span>
182-
</button>
183-
</div>
196+
<button
197+
className="nav-action-button"
198+
onClick={() => handleShare(podcast)}
199+
title="Share"
200+
>
201+
<span className="action-icon">🔗</span>
202+
</button>
203+
<button
204+
className={`nav-action-button favorite ${isFavorited ? "favorited" : ""}`}
205+
title={isFavorited ? "Remove from favorites" : "Add to favorites"}
206+
onClick={e => {
207+
e.preventDefault();
208+
e.stopPropagation();
209+
toggleFavorite();
210+
}}
211+
>
212+
<span className="action-icon">{isFavorited ? "❤️" : "🤍"}</span>
213+
</button>
214+
</div>
184215
</div>
185216

186217
{/* Main Content */}
@@ -247,7 +278,7 @@ export default function PodcastDetails(): ReactElement {
247278
</span>
248279
</div>
249280
<div className="embed-actions">
250-
<button className="embed-action" onClick={handleShare}>
281+
<button className="embed-action" onClick={() => handleShare(podcast)}>
251282
<span className="action-icon">📤</span>
252283
Share
253284
</button>

0 commit comments

Comments
 (0)