Skip to content

Commit 8c0dfec

Browse files
authored
Merge pull request #17 from csprasad/dev
feature: new update to image & home screen; known bug fixes
2 parents 15fa9c5 + 31d32b4 commit 8c0dfec

File tree

14 files changed

+320
-89
lines changed

14 files changed

+320
-89
lines changed

data/portfolio.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@
140140
"category": "Developer Tools",
141141
"icon": "assets/images/Projects/DevLint/DevLint.png",
142142
"rating": 4.5,
143-
"screenshots": ["assets/images/Projects/DevLint/DevLint-01.png"],
143+
"screenshots": ["assets/images/Projects/DevLint/DevLint-01.png", "assets/images/Projects/DevLint/DevLint-02.png"],
144144
"description": "A lightweight macOS app for formatting, linting, and correcting Swift syntax.",
145145
"app_store_link": "https://github.com/csprasad/DevLint",
146146
"total_downloads": "10K+",
203 KB
Loading

iPhone/project-details.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,25 @@
6363

6464

6565
</div>
66+
67+
<!-- Fullscreen Image Modal -->
68+
<div id="image-modal" class="image-modal">
69+
<span class="close">&times;</span>
70+
<img class="modal-content" id="modal-img">
71+
<div id="caption"></div>
72+
<!-- Optional: Prev/Next buttons -->
73+
<button id="prev" class="nav-btn">&#10094;</button>
74+
<button id="next" class="nav-btn">&#10095;</button>
75+
</div>
6676
</div>
6777
</div>
6878
</div>
6979

80+
81+
82+
7083
<!-- Include Central JavaScript -->
7184
<script src="scripts/project-details.js"></script>
85+
<script src="scripts/image-modal-helper.js"></script>
7286
</body>
7387
</html>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// scripts/image-modal-helper.js
2+
window.initScreenshotModal = function(containerEl, images) {
3+
if (!containerEl) return;
4+
const modal = document.getElementById("image-modal");
5+
if (!modal) return;
6+
7+
const modalImg = document.getElementById("modal-img");
8+
const closeBtn = modal.querySelector(".close");
9+
const prevBtn = document.getElementById("prev");
10+
const nextBtn = document.getElementById("next");
11+
12+
const thumbs = Array.from(containerEl.querySelectorAll("img"));
13+
const sources = (images && images.length) ? images : thumbs.map(img => img.src);
14+
15+
let currentIndex = 0;
16+
17+
function openAt(i) {
18+
currentIndex = i;
19+
modal.style.display = "flex";
20+
modalImg.src = sources[currentIndex];
21+
}
22+
function showNext() {
23+
currentIndex = (currentIndex + 1) % sources.length;
24+
modalImg.src = sources[currentIndex];
25+
}
26+
function showPrev() {
27+
currentIndex = (currentIndex - 1 + sources.length) % sources.length;
28+
modalImg.src = sources[currentIndex];
29+
}
30+
function close() {
31+
modal.style.display = "none";
32+
}
33+
34+
thumbs.forEach((img, i) => {
35+
img.addEventListener("click", () => openAt(i));
36+
});
37+
38+
if (nextBtn) nextBtn.onclick = showNext;
39+
if (prevBtn) prevBtn.onclick = showPrev;
40+
if (closeBtn) closeBtn.onclick = close;
41+
42+
modal.addEventListener("click", (e) => {
43+
if (e.target === modal) close();
44+
});
45+
};

iPhone/scripts/project-details.js

Lines changed: 35 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,44 @@
1+
// project-details.js
12
document.addEventListener("DOMContentLoaded", async () => {
23
const urlParams = new URLSearchParams(window.location.search);
3-
const projectId = urlParams.get("id"); // Keep it as a string
4-
const osType = urlParams.get("os"); // Get OS type from URL
4+
const projectId = urlParams.get("id");
5+
const osType = urlParams.get("os");
56

6-
console.log("Project ID from URL:", projectId);
7-
console.log("OS Type from URL:", osType);
8-
9-
if (!projectId || !osType) {
10-
console.error("Missing project ID or OS type in URL.");
11-
document.querySelector(".app-container").innerHTML = `<p>Invalid request.</p>`;
12-
return;
13-
}
7+
// If this file is included on landing.html, quietly bail.
8+
if (!projectId || !osType) return;
149

1510
try {
16-
const response = await fetch("../data/portfolio.json");
17-
const data = await response.json();
18-
19-
console.log("🔹 Full Project Data:", data);
20-
21-
if (!data || !data.apps) {
22-
throw new Error("Invalid project data format.");
23-
}
24-
25-
// Get the correct app list based on OS type
26-
const apps = data.apps[`${osType}_apps`];
27-
28-
if (!apps || !Array.isArray(apps)) {
29-
throw new Error(`Invalid OS type: ${osType}`);
30-
}
31-
32-
console.log("List of Apps for OS:", osType, apps);
33-
34-
// Find the project by ID (convert both to strings for consistency)
35-
const project = apps.find(app => String(app.app_id) === String(projectId));
36-
37-
console.log("Found Project:", project);
38-
39-
if (!project) {
40-
throw new Error("Project not found.");
41-
}
42-
43-
// Update the UI
44-
document.getElementById("app-icon").src = project.icon;
45-
document.getElementById("app-name").textContent = project.name;
46-
document.getElementById("app-category").textContent = project.category;
47-
// document.getElementById("app-rating").textContent = `Rating: ${project.rating}/5`;
48-
document.getElementById("description").textContent = project.description;
49-
document.getElementById("action-button").href = project.app_store_link;
50-
51-
// Render screenshots
52-
const screenshotContainer = document.getElementById("screenshot-container");
53-
screenshotContainer.innerHTML = "";
54-
project.screenshots.forEach(image => {
55-
const img = document.createElement("img");
56-
img.src = image;
57-
img.alt = "Screenshot";
58-
img.classList.add("screenshot");
59-
screenshotContainer.appendChild(img);
60-
});
11+
const response = await fetch("../data/portfolio.json");
12+
const data = await response.json();
13+
const apps = data.apps[`${osType}_apps`];
14+
15+
const project = apps.find(app => String(app.app_id) === String(projectId));
16+
if (!project) throw new Error("Project not found.");
17+
18+
// Update UI
19+
document.getElementById("app-icon").src = project.icon;
20+
document.getElementById("app-name").textContent = project.name;
21+
document.getElementById("app-category").textContent = project.category;
22+
document.getElementById("description").textContent = project.description;
23+
document.getElementById("action-button").href = project.app_store_link;
24+
25+
// Render screenshots
26+
const screenshotContainer = document.getElementById("screenshot-container");
27+
screenshotContainer.innerHTML = "";
28+
project.screenshots.forEach(image => {
29+
const img = document.createElement("img");
30+
img.src = image;
31+
img.alt = "Screenshot";
32+
img.classList.add("screenshot");
33+
screenshotContainer.appendChild(img);
34+
});
35+
36+
// Hook up the modal (works here and in popup)
37+
window.initScreenshotModal(screenshotContainer, project.screenshots);
6138

6239
} catch (error) {
63-
console.error("❌ Error:", error);
64-
document.querySelector(".app-container").innerHTML = `<p>Project not found.</p>`;
40+
console.error(error);
41+
const holder = document.querySelector(".app-container");
42+
if (holder) holder.innerHTML = `<p>${error.message}</p>`;
6543
}
6644
});

iPhone/scripts/project.js

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ document.addEventListener("DOMContentLoaded", async () => {
22
const projectContainer = document.querySelector(".list-section");
33

44
const fromLanding = document.referrer.includes("landing.html") || window.location.pathname.includes("landing.html");
5+
window.fromLanding = fromLanding;
56

67
try {
78
const response = await fetch("../data/portfolio.json");
@@ -41,7 +42,7 @@ document.addEventListener("DOMContentLoaded", async () => {
4142
<span class="list-name">${app.name}</span>
4243
<span class="list-type">${app.category}</span>
4344
</div>
44-
<button class="list-button btn" onclick="viewProject('${app.platform}', '${app.app_id}')">GET</button>
45+
<button class="list-button btn" onclick="viewProject('${app.platform}', '${app.app_id}')">Details</button>
4546
`;
4647

4748
appList.appendChild(appItem);
@@ -56,7 +57,54 @@ document.addEventListener("DOMContentLoaded", async () => {
5657
}
5758
});
5859

60+
5961
// Navigate to project details
60-
function viewProject(os, projectId) {
61-
window.location.href = `project-details.html?os=${os}&id=${projectId}`;
62+
window.viewProject = async function viewProject(os, projectId) {
63+
if (window.fromLanding) {
64+
try {
65+
const response = await fetch("../data/portfolio.json");
66+
const data = await response.json();
67+
const apps = data.apps[`${os}_apps`];
68+
const project = apps.find(app => String(app.app_id) === String(projectId));
69+
if (!project) throw new Error("Project not found");
70+
renderProjectPopup(project);
71+
} catch (err) {
72+
console.error(err);
73+
}
74+
} else {
75+
window.location.href = `project-details.html?os=${os}&id=${projectId}`;
76+
}
77+
};
78+
79+
function renderProjectPopup(project) {
80+
const popup = document.getElementById("project-popup");
81+
const inner = document.getElementById("popup-inner");
82+
83+
inner.innerHTML = `
84+
<div class="app-header">
85+
<img src="iPhone/${project.icon}" alt="${project.name}" class="app-icon">
86+
<div class="app-info">
87+
<span class="app-name">${project.name}</span>
88+
<span class="app-category">${project.category}</span>
89+
<div class="Action-button-container">
90+
<a href="${project.app_store_link}" target="_blank" class="btn">OPEN</a>
91+
</div>
92+
</div>
93+
</div>
94+
<div id="screenshot-container" class="screenshot-container">
95+
${project.screenshots.map(src => `<img src="iPhone/${src}" class="screenshot">`).join("")}
96+
</div>
97+
<div class="description-container">
98+
<p>${project.description}</p>
99+
</div>
100+
`;
101+
102+
popup.classList.remove("hidden");
103+
104+
document.getElementById("popup-close").onclick = () => popup.classList.add("hidden");
105+
popup.querySelector(".popup-overlay").onclick = () => popup.classList.add("hidden");
106+
107+
// 🔗 Bind modal to the popup thumbnails
108+
const container = inner.querySelector("#screenshot-container");
109+
window.initScreenshotModal(container);
62110
}

iPhone/styles/project-details.css

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
.app-header {
1010
display: flex;
1111
margin-top: 0;
12-
/* align-items: top; */
1312
gap: 0.5rem;
1413
}
1514

@@ -26,16 +25,27 @@
2625

2726
.screenshot-container {
2827
display: flex;
29-
gap: 5px;
28+
gap: 8px;
3029
overflow-x: auto;
31-
padding: 10px 0;
30+
padding: 12px 0;
31+
scroll-snap-type: x mandatory; /* smooth carousel snapping */
32+
-webkit-overflow-scrolling: touch;
3233
}
33-
34+
3435
.screenshot-container img {
35-
width: 130px;
3636
height: 250px;
37-
border-radius: 10px;
38-
flex-shrink: 0;
37+
width: auto;
38+
max-width: 400px;
39+
border-radius: 0.8rem;
40+
flex-shrink: 0;
41+
scroll-snap-align: start;
42+
object-fit: contain;
43+
background: #f9f9f9;
44+
transition: transform 0.2s ease;
45+
}
46+
47+
.screenshot-container img:hover {
48+
transform: scale(1.02);
3949
}
4050

4151
.app-info {
@@ -74,11 +84,72 @@
7484
border: 0;
7585
outline: 0;
7686
cursor: pointer;
77-
color: white;
78-
background-color: #007aff;
87+
color: gray;
88+
background-color: rgb(0, 0, 0, 0.1);
7989
border-radius: 10px;
8090
font-size: 0.6rem;
8191
font-weight: 300;
8292
padding: 4px 8px;
8393
max-height: 28px;
94+
border: 0;
8495
}
96+
97+
.Action-button-container .btn:hover {
98+
color: white;
99+
background-color: #0066d3;
100+
text-decoration: none;
101+
}
102+
103+
104+
/*********************************
105+
Screenshot silder details
106+
**********************************/
107+
/* Fullscreen modal */
108+
.image-modal {
109+
display: none; /* Hidden by default */
110+
position: fixed;
111+
z-index: 1000;
112+
left: 0;
113+
top: 0;
114+
width: 100%;
115+
height: 100%;
116+
background-color: var(--bg-glass-dark);
117+
align-items: center;
118+
justify-content: center;
119+
}
120+
121+
/* Modal image */
122+
.image-modal .modal-content {
123+
max-width: 70%;
124+
max-height: 75%;
125+
border-radius: 15px;
126+
}
127+
128+
/* Close button */
129+
.image-modal .close {
130+
position: absolute;
131+
top: 20px;
132+
right: 30px;
133+
color: var(--text-primary);
134+
font-size: 40px;
135+
cursor: pointer;
136+
z-index: 10;
137+
}
138+
139+
/* Navigation buttons */
140+
.nav-btn {
141+
position: absolute;
142+
height: 10%;
143+
width: 5%;
144+
background: none;
145+
border: none;
146+
font-size: 2rem;
147+
color: var(--text-primary);
148+
align-content: center;
149+
padding: 2%;
150+
cursor: pointer;
151+
border-radius: 7.5%;
152+
}
153+
154+
#prev { left: 10px; }
155+
#next { right: 10px; }

iPhone/styles/project.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ body.project {
7777
outline: 0;
7878
cursor: pointer;
7979
background-color: rgb(0, 0, 0, 0.1);
80-
color: #007aff;
80+
color: var(--text-secondary);
8181
font-weight: 600;
8282
border-radius: 100px;
8383
font-size: 0.8rem;
@@ -156,7 +156,7 @@ body.landing {
156156
outline: 0;
157157
cursor: pointer;
158158
background-color: rgba(0, 0, 0, 0.1);
159-
color: var(--blue-accent);
159+
color: var(--text-secondary);
160160
font-weight: 600;
161161
border-radius: 100px;
162162
font-size: 0.8rem;

0 commit comments

Comments
 (0)