Skip to content
Closed
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
12 changes: 3 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
FROM node:18-alpine AS builder
FROM node:20-alpine

# Set working directory inside the container
WORKDIR /app

COPY package*.json ./

# Install dependencies with legacy peer deps fix
RUN npm install --legacy-peer-deps

COPY . .
RUN npm run build

# Production Image
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app /app
# No need to run 'npm run build' for development-mode Docker
EXPOSE 3000

CMD ["npm", "run","serve"]
CMD [ "npm", "run", "dev" ]
5 changes: 2 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
version: "3.9"

services:
recodehive:
build:
Expand All @@ -8,8 +7,8 @@ services:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
- /app/node_modules # Prevents node_modules being overwritten by the mount
working_dir: /app
command: npm run start
command: npm run dev # THIS is the crucial change for hot-reload!
environment:
- NODE_ENV=development
17 changes: 9 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"dev": "docusaurus start",
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
Expand All @@ -15,14 +16,14 @@
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "^3.8.1",
"@docusaurus/plugin-content-docs": "3.8.1",
"@docusaurus/plugin-google-analytics": "^3.8.1",
"@docusaurus/plugin-ideal-image": "3.8.1",
"@docusaurus/preset-classic": "^3.8.1",
"@docusaurus/theme-classic": "^3.8.1",
"@docusaurus/theme-mermaid": "3.8.1",
"@docusaurus/theme-search-algolia": "3.8.1",
"@docusaurus/core": "^3.9.1",
"@docusaurus/plugin-content-docs": "3.9.1",
"@docusaurus/plugin-google-analytics": "^3.9.1",
"@docusaurus/plugin-ideal-image": "3.9.1",
"@docusaurus/preset-classic": "^3.9.1",
"@docusaurus/theme-classic": "^3.9.1",
"@docusaurus/theme-mermaid": "3.9.1",
"@docusaurus/theme-search-algolia": "3.9.1",
"@floating-ui/react": "^0.27.8",
"@giscus/react": "^3.1.0",
"@mdx-js/react": "^3.0.0",
Expand Down
53 changes: 11 additions & 42 deletions src/pages/podcasts/details.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React from 'react';
import Layout from '@theme/Layout';
import type { ReactElement } from 'react';
import { useLocation, useHistory } from '@docusaurus/router';
Expand Down Expand Up @@ -85,26 +85,7 @@ export default function PodcastDetails(): ReactElement {
const history = useHistory();
const state = location.state as LocationState;
const podcast = state?.podcast;

const [favorites, setFavorites] = useState<string[]>(() => {
if (typeof window !== "undefined") {
const saved = localStorage.getItem("podcast-favorites");
return saved ? JSON.parse(saved) : [];
}
return [];
});
const isFavorited = podcast ? favorites.includes(podcast.id) : false;
const toggleFavorite = () => {
if (!podcast) return;
setFavorites(prev => {
const updated = prev.includes(podcast.id)
? prev.filter(id => id !== podcast.id)
: [...prev, podcast.id];
localStorage.setItem("podcast-favorites", JSON.stringify(updated));
return updated;
});
};


// Enhanced descriptions with categories
const descriptions = {
episode: [
Expand Down Expand Up @@ -147,7 +128,7 @@ export default function PodcastDetails(): ReactElement {
history.goBack();
};

const handleShare = async (podcast?: PodcastData) => {
const handleShare = async () => {
if (navigator.share) {
try {
await navigator.share({
Expand Down Expand Up @@ -193,25 +174,13 @@ export default function PodcastDetails(): ReactElement {
<span className="nav-text">Back to Podcasts</span>
</button>
<div className="nav-actions">
<button
className="nav-action-button"
onClick={() => handleShare(podcast)}
title="Share"
>
<span className="action-icon">🔗</span>
</button>
<button
className={`nav-action-button favorite ${isFavorited ? "favorited" : ""}`}
title={isFavorited ? "Remove from favorites" : "Add to favorites"}
onClick={e => {
e.preventDefault();
e.stopPropagation();
toggleFavorite();
}}
>
<span className="action-icon">{isFavorited ? "❤️" : "🤍"}</span>
</button>
</div>
<button className="nav-action-button" onClick={handleShare} title="Share">
<span className="action-icon">🔗</span>
</button>
<button className="nav-action-button" title="Add to favorites">
<span className="action-icon">❤️</span>
</button>
</div>
</div>

{/* Main Content */}
Expand Down Expand Up @@ -278,7 +247,7 @@ export default function PodcastDetails(): ReactElement {
</span>
</div>
<div className="embed-actions">
<button className="embed-action" onClick={() => handleShare(podcast)}>
<button className="embed-action" onClick={handleShare}>
<span className="action-icon">📤</span>
Share
</button>
Expand Down
63 changes: 17 additions & 46 deletions src/pages/podcasts/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@ html[data-theme='light'] {
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
position: relative;
z-index: 1;
overflow: hidden;
animation: fadeInUp 0.6s ease-out both;
}
Expand Down Expand Up @@ -405,40 +404,12 @@ html[data-theme='light'] {
gap: 8px;
opacity: 0;
transition: opacity 0.3s ease;
position: relative;
z-index: 10;
pointer-events: auto;
}

.enhanced-podcast-card:hover .card-actions {
opacity: 1;
}

.action-btn.share {
background-color: rgba(123, 124, 128, 0.15); /* same subtle bg as unfavorited */
border: 1px solid rgba(123, 124, 128, 0.3); /* same border */
transition: all 0.3s ease;
color: inherit; /* keep the existing icon color */
border-radius: 8px;
width: 36px;
height: 36px;
cursor: pointer;
font-size: 14px;
position: relative;
z-index: 15;
user-select: none;
}

.action-btn.share:hover {
background-color: rgba(123, 124, 128, 0.25); /* slightly darker on hover */
border-color: rgba(123, 124, 128, 0.5);
transform: scale(1.1);
}

.action-btn.share:active {
transform: scale(0.95);
}

.action-btn {
width: 36px;
height: 36px;
Expand All @@ -448,35 +419,35 @@ html[data-theme='light'] {
cursor: pointer;
transition: all 0.3s ease;
font-size: 14px;
position: relative;
z-index: 15;
pointer-events: auto !important;
user-select: none;
}

.action-btn:hover {
background: var(--podcast-bg-card-hover);
transform: scale(1.1);
}
/* Enhanced favorite button styling */

.action-btn.favorite {
transition: all 0.2s ease;
border: 1px solid transparent;
position: relative;
padding: 12px; /* Increase clickable padding */
border-radius: 50%;
cursor: pointer;
transition: background-color 0.3s ease;
}

.action-btn.favorite:active {
transform: scale(0.95);
.action-btn.favorite:hover,
.action-btn.favorite.favorited {
background-color: rgba(224, 36, 94, 0.1);
}

.action-btn.favorite.unfavorited {
background-color: rgba(123, 124, 128, 0.15); /* light purple-blue tint */
color: white; /* keep the heart white */
border-color: rgba(123, 124, 128, 0.3);
.action-btn.favorite > svg,
.action-btn.favorite > img,
.action-btn.favorite > span {
pointer-events: none;
font-size: 1.5rem;
display: inline-block;
vertical-align: middle;
}

.action-btn.favorite.unfavorited:hover {
background-color: rgba(123, 124, 128, 0.15);
}

/* Podcast Title */
.podcast-title {
Expand Down Expand Up @@ -774,4 +745,4 @@ html[data-theme='light'] {
.search-input {
font-size: 14px;
}
}
}
Loading
Loading