Skip to content

Commit

Permalink
add ability to hide job postings
Browse files Browse the repository at this point in the history
  • Loading branch information
m1yon committed May 3, 2024
1 parent f3a3b6f commit f031f76
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 140 deletions.
22 changes: 4 additions & 18 deletions cmd/jobsummoner/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,15 @@
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/[email protected]"
integrity="sha384-ujb1lZYygJmzgSwoxRggbCHcjc0rB2XoQrxeTUQyRjrOnlCoYta87iKBWq3EsdM2"
crossorigin="anonymous"></script>
</head>

<body>
<div class="max-w-3xl m-auto mb-12">
<h1 class="mt-12 mb-6 text-2xl font-semibold">Job Summoner</h1>
{{range .JobPostings}}
<a class="p-4 bg-gray-100 mb-2 flex justify-between items-center" href="{{.JobPostingUrl}}">
<div class="flex items-center">
{{if .CompanyAvatar.String}}
<img class="size-10 rounded-lg mr-4" src="{{.CompanyAvatar.String}}" alt="">
{{else}}
<div class="size-10 rounded-lg mr-4 bg-gray-300 flex items-center justify-center">
<p class="text-lg text-gray-600">?</p>
</div>
{{end}}
<div>
<p class="font-bold">{{.Position}}</p>
<p>{{.CompanyName}}</p>
</div>
</div>
<p class="text-sm text-gray-500">Posted {{.TimeAgo}}</p>
</a>
{{end}}
{{template "user_job_postings" .}}
</div>
</body>

Expand Down
88 changes: 7 additions & 81 deletions cmd/jobsummoner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,14 @@ package main
import (
"context"
"database/sql"
"fmt"
"log/slog"
"net/http"
"text/template"
"time"

"github.com/joho/godotenv"
"github.com/lmittmann/tint"
"github.com/m1yon/jobsummoner/internal/database"
"github.com/m1yon/jobsummoner/internal/handlers"
"github.com/m1yon/jobsummoner/internal/linkedincrawler"
"github.com/m1yon/jobsummoner/internal/logger"
"github.com/prometheus/client_golang/prometheus/promhttp"
_ "modernc.org/sqlite"
)

Expand All @@ -31,9 +27,7 @@ func main() {
slog.Error("problem initializing handler mux", err)
return
}
go linkedincrawler.ScrapeLoop(db)

mux := http.NewServeMux()
dbQueries := database.New(db)

// create our seed user
Expand All @@ -42,43 +36,14 @@ func main() {
dbQueries.CreateUser(ctx)
}

mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
t, err := template.ParseFiles("cmd/jobsummoner/index.html")

if err != nil {
slog.Error("could not parse template", tint.Err(err))
}

JobPostings, err := dbQueries.GetUserJobPostings(ctx, 1)

if err != nil {
slog.Error("failed to query job postings", tint.Err(err))
}

type FormattedJobPosting struct {
database.GetUserJobPostingsRow
TimeAgo string
}

formattedJobPostings := make([]FormattedJobPosting, 0, len(JobPostings))

for _, jobPosting := range JobPostings {
formattedJobPostings = append(formattedJobPostings, FormattedJobPosting{GetUserJobPostingsRow: jobPosting, TimeAgo: timeAgo(jobPosting.LastPosted)})
}

homepage := struct {
JobPostings []FormattedJobPosting
}{
formattedJobPostings,
}
go linkedincrawler.ScrapeLoop(db)

err = t.Execute(w, homepage)
mux, err := handlers.NewHandlerMux(db)

if err != nil {
slog.Error("could not execute template", tint.Err(err))
}
})
mux.Handle("/metrics/", promhttp.Handler())
if err != nil {
slog.Error("problem initializing handler mux", err)
return
}

corsMux := middlewareCors(mux)

Expand All @@ -103,42 +68,3 @@ func middlewareCors(next http.Handler) http.Handler {
next.ServeHTTP(w, r)
})
}

func timeAgo(from time.Time) string {
now := time.Now()
diff := now.Sub(from)

if diff < time.Minute {
if int(diff.Seconds()) == 1 {
return fmt.Sprintf("%d second ago", int(diff.Seconds()))
}
return fmt.Sprintf("%d seconds ago", int(diff.Seconds()))
} else if diff < time.Hour {
if int(diff.Minutes()) == 1 {
return fmt.Sprintf("%d minute ago", int(diff.Minutes()))
}
return fmt.Sprintf("%d minutes ago", int(diff.Minutes()))
} else if diff < time.Hour*24 {
if int(diff.Hours()) == 1 {
return fmt.Sprintf("%d hour ago", int(diff.Hours()))
}
return fmt.Sprintf("%d hours ago", int(diff.Hours()))
} else if diff < time.Hour*24*30 {
days := diff / (time.Hour * 24)
if days == 1 {
return fmt.Sprintf("%d day ago", int(days))
}
return fmt.Sprintf("%d days ago", int(days))
} else if diff < time.Hour*24*365 {
months := diff / (time.Hour * 24 * 30)
if months == 1 {
return fmt.Sprintf("%d month ago", int(months))
}
return fmt.Sprintf("%d months ago", int(months))
}
years := diff / (time.Hour * 24 * 365)
if years == 1 {
return fmt.Sprintf("%d year ago", int(years))
}
return fmt.Sprintf("%d years ago", int(years))
}
24 changes: 24 additions & 0 deletions cmd/jobsummoner/user_job_postings.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{{define "user_job_postings"}}
{{range .JobPostings}}
<div id="user_job_posting-{{ .JobPostingID }}" class="p-4 bg-gray-100 mb-2 flex justify-between items-center"
href="{{.JobPostingUrl}}">
<div class="flex items-center">
{{if .CompanyAvatar.String}}
<img class="size-10 rounded-lg mr-4" src="{{.CompanyAvatar.String}}" alt="">
{{else}}
<div class="size-10 rounded-lg mr-4 bg-gray-300 flex items-center justify-center">
<p class="text-lg text-gray-600">?</p>
</div>
{{end}}
<div>
<p class="font-bold">{{.Position}}</p>
<p>{{.CompanyName}}</p>
<p class="text-sm text-gray-500">Posted {{.TimeAgo}}</p>
</div>
</div>

<button type="button" hx-patch="/user_job_postings/{{ .JobPostingID }}"
hx-target="#user_job_posting-{{ .JobPostingID }}" hx-swap="outerHTML">Hide</button>
</div>
{{end}}
{{end}}
13 changes: 7 additions & 6 deletions internal/database/job_postings.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions internal/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

37 changes: 28 additions & 9 deletions internal/database/user_job_postings.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions internal/handlers/handlers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package handlers

import (
"database/sql"
"net/http"

"github.com/m1yon/jobsummoner/internal/database"
"github.com/prometheus/client_golang/prometheus/promhttp"
)

type handlersConfig struct {
DB *database.Queries
}

func NewHandlerMux(db *sql.DB) (*http.ServeMux, error) {
mux := http.NewServeMux()
dbQueries := database.New(db)

cfg := handlersConfig{
DB: dbQueries,
}

mux.HandleFunc("/", cfg.rootHandler)
mux.HandleFunc("PATCH /user_job_postings/{jobPostingID}", cfg.putUserJobPostingsHandler)

mux.Handle("/metrics/", promhttp.Handler())

return mux, nil
}
Loading

0 comments on commit f031f76

Please sign in to comment.