Skip to content

Commit a8a456e

Browse files
committed
UX change: Instead of form submit, now using fetch to enhance experience of waiting for data to load.
1 parent 0609236 commit a8a456e

File tree

3 files changed

+116
-76
lines changed

3 files changed

+116
-76
lines changed

cmd/handlers.go

+21-6
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,29 @@ func render(ctx *gin.Context, status int, template templ.Component) error {
2121
return template.Render(ctx.Request.Context(), ctx.Writer)
2222
}
2323

24+
func handleMainPage(ctx *gin.Context) {
25+
if strings.TrimSpace(ctx.Query("username")) == "" {
26+
getIndexHandler(ctx)
27+
} else {
28+
getUserHandler(ctx)
29+
}
30+
}
31+
32+
func getIndexHandler(ctx *gin.Context) {
33+
_, cancel := context.WithTimeout(context.Background(), appTimeout)
34+
35+
defer cancel()
36+
37+
emptyUser := &views.GitHubUser{}
38+
39+
render(ctx, http.StatusOK, views.Index(emptyUser))
40+
}
41+
2442
func getUserHandler(ctx *gin.Context) {
2543
_, cancel := context.WithTimeout(context.Background(), appTimeout)
2644
username := ctx.Query("username")
2745
username = strings.TrimSpace(username)
2846

29-
if username == "" {
30-
username = "rajatasusual"
31-
}
32-
3347
defer cancel()
3448

3549
user, err := service.FetchEntryFromXata(username)
@@ -41,7 +55,7 @@ func getUserHandler(ctx *gin.Context) {
4155
user = &views.GitHubUser{
4256
Name: "User not found",
4357
}
44-
render(ctx, http.StatusOK, views.Index(user))
58+
ctx.JSON(http.StatusNotFound, user)
4559
return
4660
}
4761
_, err := service.CreateNewEntry(user)
@@ -50,5 +64,6 @@ func getUserHandler(ctx *gin.Context) {
5064
}
5165
}
5266

53-
render(ctx, http.StatusOK, views.Index(user))
67+
//serve user as JSON
68+
ctx.JSON(http.StatusOK, user)
5469
}

cmd/routes.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cmd
22

33
import (
4+
"net/http"
5+
46
"github.com/gin-gonic/gin"
57
)
68

@@ -10,5 +12,15 @@ type Config struct {
1012

1113
func (app *Config) Routes() {
1214
//views
13-
app.Router.GET("/", getUserHandler)
15+
app.Router.GET("/", handleMainPage)
16+
17+
app.Router.GET("/health", func(ctx *gin.Context) {
18+
ctx.JSON(200, gin.H{
19+
"status": "ok",
20+
})
21+
})
22+
23+
app.Router.NoRoute(func(ctx *gin.Context) {
24+
ctx.Status(http.StatusNotFound)
25+
})
1426
}

views/index.templ

+82-69
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package views
22

33
import (
4-
"fmt"
54
"go-github/views/components"
6-
"strings"
75
)
86

97
// GitHubUser represents a GitHub user with extended details
@@ -36,7 +34,7 @@ templ Index(user *GitHubUser) {
3634
</nav>
3735
<div class="mt-6 w-full flex justify-center items-center flex-col">
3836
<!-- Search Form -->
39-
<form method="get" class="w-96">
37+
<form method="get" id="searchForm" class="w-96">
4038
<input
4139
type="text"
4240
name="username"
@@ -54,85 +52,100 @@ templ Index(user *GitHubUser) {
5452
<br />
5553

5654
<!-- Main Content Container -->
57-
<div class="flex flex-col lg:flex-row w-full max-w-6xl mx-auto mt-6 gap-8">
55+
<div class="flex flex-col lg:flex-row w-full max-w-6xl mx-auto mt-6 gap-8" style="display: none;" id="profileContent">
5856
<!-- Profile Information -->
59-
<div class="w-full lg:w-1/2 flex justify-center items-center flex-col p-4 border border-gray-300 rounded-lg">
60-
<img class="w-24 h-24 rounded-full" src={ user.AvatarURL } />
61-
<h1 class="text-3xl font-bold mt-4">{ user.Name }</h1>
62-
<p class="text-center mb-2"><em>{ user.Bio }</em></p>
63-
64-
<!-- Additional Information -->
65-
<div class="w-full px-4 items-center flex flex-col justify-center">
66-
<p><strong>Username:</strong> { user.Login }</p>
67-
<p><strong>Company:</strong> { user.Company }</p>
68-
<p><strong>Blog:</strong> <a href={ templ.URL(user.Blog) }>{ user.Blog }</a></p>
69-
<p><strong>Location:</strong> { user.Location }</p>
70-
<p><strong>Email:</strong> { user.Email }</p>
71-
<p><strong>Public Repos:</strong> { fmt.Sprintf("%d", user.PublicRepos) }</p>
72-
<p><strong>Followers:</strong> { fmt.Sprintf("%d", user.Followers) }</p>
73-
<p><strong>Following:</strong> { fmt.Sprintf("%d", user.Following) }</p>
74-
<p><strong>Joined:</strong> { user.CreatedAt }</p>
75-
</div>
57+
<div id="profileInfo" class="w-full lg:w-1/2 flex justify-center items-center flex-col p-4 border border-gray-300 rounded-lg">
58+
<!-- Dynamic user info will be inserted here -->
7659
</div>
7760

7861
<!-- Commit History Scatterplot -->
79-
<div class="w-full lg:w-1/2 flex flex-col items-center p-4 border border-gray-300 rounded-lg">
80-
<h2 class="text-xl font-bold mb-4">Commit History Scatterplot</h2>
81-
<div class="w-full">
82-
<canvas id="commitHistoryChart" data-chart={ strings.Join(user.CommitHistory, ",") } class="w-full h-64"></canvas>
83-
</div>
62+
<div id="commitHistory" class="w-full lg:w-1/2 flex flex-col items-center p-4 border border-gray-300 rounded-lg">
63+
<!-- Dynamic commit history chart will be inserted here -->
8464
</div>
8565
</div>
8666
</div>
8767
</main>
8868
</body>
8969
<script>
90-
window.onload = function() {
91-
// Retrieve commit history data from Go
92-
const commitData = document.getElementById('commitHistoryChart').getAttribute('data-chart');
93-
94-
const listToChartData = commitData => {
95-
const lines = commitData.trim().split(',');
96-
return lines.map(line => {
97-
const [date, commits] = line.split(':');
98-
return {
99-
x: date,
100-
y: commits
101-
}
102-
});
103-
};
104-
105-
console.log(listToChartData(commitData));
106-
107-
// Configure Chart.js for a scatterplot
108-
const ctx = document.getElementById('commitHistoryChart').getContext('2d');
109-
const config = {
110-
type: 'line',
111-
data: {
112-
labels: [],
113-
datasets: [{
114-
data: listToChartData(commitData),
115-
label: "Commits",
116-
borderColor: "#3e95cd",
117-
fill: false
118-
}]
119-
},
120-
options: {
121-
scales: {
122-
xAxes: [{
123-
type: 'time',
124-
distribution: 'linear',
125-
}],
126-
title: {
127-
display: false,
70+
document.getElementById('searchForm').addEventListener('submit', async function(event) {
71+
event.preventDefault(); // Prevent page reload
72+
73+
const username = document.getElementById('username').value;
74+
document.getElementById('profileContent').style.display = 'flex';
75+
76+
try {
77+
// Show a loading state if needed
78+
document.getElementById('profileInfo').innerHTML = "<p>Loading...</p>";
79+
document.getElementById('commitHistory').innerHTML = "<p>Loading chart...</p>";
80+
81+
// Fetch user profile and commit history
82+
const response = await fetch(`http://localhost:8080/?username=${encodeURIComponent(username)}`);
83+
const user = await response.json();
84+
85+
// Populate Profile Info
86+
const profileHTML = `
87+
<img class="w-24 h-24 rounded-full" src="${user.AvatarURL}" />
88+
<h1 class="text-3xl font-bold mt-4">${user.Name}</h1>
89+
<p class="text-center mb-2"><em>${user.Bio}</em></p>
90+
<div class="w-full px-4 items-center flex flex-col justify-center">
91+
<p><strong>Username:</strong> ${user.Login}</p>
92+
<p><strong>Company:</strong> ${user.Company}</p>
93+
<p><strong>Blog:</strong> <a href="${user.Blog}" target="_blank">${user.Blog}</a></p>
94+
<p><strong>Location:</strong> ${user.Location}</p>
95+
<p><strong>Email:</strong> ${user.Email}</p>
96+
<p><strong>Public Repos:</strong> ${user.PublicRepos}</p>
97+
<p><strong>Followers:</strong> ${user.Followers}</p>
98+
<p><strong>Following:</strong> ${user.Following}</p>
99+
<p><strong>Joined:</strong> ${user.CreatedAt}</p>
100+
</div>
101+
`;
102+
document.getElementById('profileInfo').innerHTML = profileHTML;
103+
104+
// Inject the canvas for the commit history chart
105+
document.getElementById('commitHistory').innerHTML = `
106+
<h2 class="text-xl font-bold mb-4">Commit History Scatterplot</h2>
107+
<canvas id="commitHistoryChart" class="w-full h-64"></canvas>
108+
`;
109+
110+
const listToChartData = commitData => {
111+
return commitData.map(datapoint => {
112+
const [date, commits] = datapoint.split(':');
113+
return {
114+
x: date,
115+
y: commits
116+
}
117+
});
118+
};
119+
const ctx = document.getElementById('commitHistoryChart').getContext('2d');
120+
new Chart(ctx, {
121+
type: 'line',
122+
data: {
123+
datasets: [{
124+
label: "Commits",
125+
data: listToChartData(user.CommitHistory || []),
126+
backgroundColor: "#3e95cd",
127+
borderColor: "#3e95cd",
128+
fill: false
129+
}]
130+
},
131+
options: {
132+
scales: {
133+
xAxes: [{
134+
type: 'time',
135+
time: {
136+
unit: 'day'
137+
}
138+
}]
128139
}
129140
}
130-
}
131-
};
141+
});
132142

133-
new Chart(ctx, config);
134-
135-
}
143+
} catch (error) {
144+
console.error('Error fetching data:', error);
145+
document.getElementById('profileInfo').innerHTML = "<p>Error loading profile information.</p>";
146+
document.getElementById('commitHistory').innerHTML = "<p>Error loading commit history.</p>";
147+
}
148+
});
136149
</script>
137150
@components.Footer()
138151
</html>

0 commit comments

Comments
 (0)