From fa2c38f53f7351d029516f2810006470bbca40dc Mon Sep 17 00:00:00 2001 From: JaiiR320 Date: Wed, 14 Feb 2024 23:43:38 -0500 Subject: [PATCH] Improved look and feel --- .gitignore | 4 +- README.md | 29 +++++++++- bin/build-errors.log | 2 +- cmd/main.go | 46 ++++++++------- go.mod | 1 + go.sum | 2 + model/functions.go | 4 +- model/globals.go | 2 + scripts/buildGPTRequest.go | 11 +++- scripts/filterSongs.go | 29 +--------- static/output.css | 86 ++++++++++++++++++++++++----- view/components/addTagForm.templ | 4 +- view/components/addTagForm_templ.go | 2 +- view/components/songCard.templ | 8 ++- view/components/songCard_templ.go | 42 +++++++++----- view/input.css | 6 +- view/layout/content.templ | 22 +++----- view/layout/content_templ.go | 48 +++------------- view/layout/navbar.templ | 2 +- view/layout/navbar_templ.go | 2 +- view/pages/home.templ | 4 +- view/pages/home_templ.go | 2 +- 22 files changed, 213 insertions(+), 145 deletions(-) diff --git a/.gitignore b/.gitignore index a81fead..9ad4d66 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ /bin # Tailwind CLI -tailwind.exe \ No newline at end of file +tailwind.exe + +.env \ No newline at end of file diff --git a/README.md b/README.md index ace0f63..b5db227 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,29 @@ # SpotifAI - + +## Description + +Website used to load in a user's liked library, then go through each song and use AI to tag the songs. There will be MANY tags, so a search bar is used to search keywords that equal or match the tag. Once a tags have been selected, you can export that to a playlist to Spotify. + +## Key features + +- AI tagging songs +- Filter library by tags +- Export to playlist + +## Roadmap + +- Add a user to the website +- Import a user's library and list +- read through user's library and create tags +- add filtering by fuzzy find +- export tagged songs to a playlist + +## Future additions + +- Remove or add tags to specific songs +- Create custom tags (playlists) +- Global database with all songs and all tags (might be extremely taxing think of paging to reduce object size) +- Search global database using same search system +- Intelligent addition of tags +- Improve tagging and tag names +- Standalone Spotify addon? diff --git a/bin/build-errors.log b/bin/build-errors.log index b8e822a..d00c2fa 100644 --- a/bin/build-errors.log +++ b/bin/build-errors.log @@ -1 +1 @@ -exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file +exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1 \ No newline at end of file diff --git a/cmd/main.go b/cmd/main.go index 1279713..befc5f8 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -33,9 +33,6 @@ func main() { router.PUT("/tag", HandleAddTag) router.DELETE("/tag/:name", HandleDeleteTag) - // initialize liked songs list - scripts.InitializeSongList("example.json") - log.Fatal(router.Start(":3000")) } @@ -96,11 +93,37 @@ func HandleSpotifyCallback(c echo.Context) error { } log.Println(model.CurrentUser.DisplayName, "logged in") + err = getLikedSongs() + if err != nil { + return err + } + model.Logged = true return c.Redirect(http.StatusFound, "/") } +func getLikedSongs() error { + log.Println("Getting liked songs") + client := req.C() + resp, err := client.R(). + SetHeader("Authorization", "Bearer "+model.AccessToken.AccessToken). + SetSuccessResult(&model.LikedSongsResponse). + Get("https://api.spotify.com/v1/me/tracks") + if err != nil { + return err + } + + if resp.GetStatusCode() != http.StatusOK { + return fmt.Errorf("no response from Spotify") + } + + model.LikedSongs = model.LikedSongsResponse.Items + model.FilteredSongs = model.LikedSongsResponse.Items + + return nil +} + func getToken(c echo.Context) error { log.Println("Getting token") idAndSecret := base64.StdEncoding.EncodeToString([]byte(model.Client_id + ":" + model.Client_secret)) @@ -113,7 +136,6 @@ func getToken(c echo.Context) error { SetQueryParam("code", c.QueryParam("code")). SetQueryParam("redirect_uri", "http://localhost:3000/callback"). SetSuccessResult(&model.AccessToken). - EnableDump(). Post("https://accounts.spotify.com/api/token") if err != nil { return err @@ -132,7 +154,6 @@ func getUser() error { resp, err := client.R(). SetHeader("Authorization", "Bearer "+model.AccessToken.AccessToken). SetSuccessResult(&model.CurrentUser). - EnableDump(). Get("https://api.spotify.com/v1/me") if err != nil { return err @@ -144,18 +165,3 @@ func getUser() error { return nil } - -// req := scripts.Get("https://api.spotify.com/v1/me"). -// WithHeader("Authorization", "Bearer "+model.AccessToken.AccessToken). -// WithObject(&model.CurrentUser) -// return req.Do() - -// post := scripts.Post("https://accounts.spotify.com/api/token"). -// WithHeader("Content-Type", "application/x-www-form-urlencoded"). -// WithHeader("Authorization", "Basic "+idAndSecret). -// WithQuery("grant_type", "authorization_code"). -// WithQuery("code", c.QueryParam("code")). -// WithQuery("redirect_uri", "http://localhost:3000/callback"). -// WithObject(&model.AccessToken) - -// return post.Do() diff --git a/go.mod b/go.mod index 74f3b0a..df91f58 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/imroc/req/v3 v3.42.3 // indirect + github.com/joho/godotenv v1.5.1 // indirect github.com/klauspost/compress v1.17.6 // indirect github.com/labstack/gommon v0.4.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect diff --git a/go.sum b/go.sum index ad4461d..bb33f73 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/imroc/req/v3 v3.42.3 h1:ryPG2AiwouutAopwPxKpWKyxgvO8fB3hts4JXlh3PaE= github.com/imroc/req/v3 v3.42.3/go.mod h1:Axz9Y/a2b++w5/Jht3IhQsdBzrG1ftJd1OJhu21bB2Q= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/klauspost/compress v1.17.6 h1:60eq2E/jlfwQXtvZEeBUYADs+BwKBWURIY+Gj2eRGjI= github.com/klauspost/compress v1.17.6/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8= diff --git a/model/functions.go b/model/functions.go index 6bfdf8b..ebab13a 100644 --- a/model/functions.go +++ b/model/functions.go @@ -1,6 +1,8 @@ package model -import "github.com/JaiiR320/SpotifAI/utils" +import ( + "github.com/JaiiR320/SpotifAI/utils" +) func AddTag(tag string) { Tags = append(Tags, tag) diff --git a/model/globals.go b/model/globals.go index b5a13a8..5db6148 100644 --- a/model/globals.go +++ b/model/globals.go @@ -5,6 +5,8 @@ var Tags []string var LikedSongs []Item var FilteredSongs []Item +var LikedSongsResponse Playlist + // Access variables var AccessToken TokenResponse var CurrentUser User diff --git a/scripts/buildGPTRequest.go b/scripts/buildGPTRequest.go index 1b4934b..dcb2659 100644 --- a/scripts/buildGPTRequest.go +++ b/scripts/buildGPTRequest.go @@ -4,14 +4,21 @@ import ( "encoding/json" "errors" "net/http" + "os" "github.com/JaiiR320/SpotifAI/model" "github.com/imroc/req/v3" + "github.com/joho/godotenv" ) -var OpenAIKey = "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" - func GenerateTracks(tracks []model.Item, tags []string) (string, error) { + err := godotenv.Load(".env") + if err != nil { + return "", err + } + + OpenAIKey := os.Getenv("OPENAI_KEY") + if len(tracks) == 0 || len(tags) == 0 { return "", errors.New("no tracks or tags to filter") } diff --git a/scripts/filterSongs.go b/scripts/filterSongs.go index dc86d64..910ccd9 100644 --- a/scripts/filterSongs.go +++ b/scripts/filterSongs.go @@ -9,15 +9,16 @@ import ( func FilterSongs(songs []model.Item, tags []string) []model.Item { if len(tags) == 0 { + log.Println("No tags to filter") return model.LikedSongs } - //GenerateTracks(model.LikedSongs, model.Tags) log.Print("Filtering songs") selectedItems := make([]model.Item, 0) - for i := 0; i < 15; i++ { + for i := 0; i < 20; i++ { randomIndex := rand.Intn(len(model.LikedSongs)) selectedItems = append(selectedItems, model.LikedSongs[randomIndex]) } + //return GenerateTracks(model.LikedSongs, model.Tags) return selectedItems } @@ -28,27 +29,3 @@ type Song struct { type Songs struct { Songs []Song `json:"songs"` } - -// Filter Songs -// str, err := GenerateTracks(model.LikedSongs, model.Tags) -// if err != nil { -// log.Panic(err) -// } - -// var jsonSongs Songs -// err = json.Unmarshal([]byte(str), &jsonSongs) -// if err != nil { -// log.Panic(err) -// } - -// var filteredSongs []model.Item - -// for _, s := range jsonSongs.Songs { -// for _, song := range songs { -// if strings.Contains(song.Track.Name, s.Title) { -// filteredSongs = append(filteredSongs, song) -// } -// } -// } - -// return filteredSongs diff --git a/static/output.css b/static/output.css index a9174ad..2c90d5a 100644 --- a/static/output.css +++ b/static/output.css @@ -577,6 +577,10 @@ video { height: 3rem; } +.h-24 { + height: 6rem; +} + .h-6 { height: 1.5rem; } @@ -585,6 +589,10 @@ video { height: 100%; } +.h-svh { + height: 100svh; +} + .w-1\/3 { width: 33.333333%; } @@ -605,6 +613,22 @@ video { width: auto; } +.w-full { + width: 100%; +} + +.w-4 { + width: 1rem; +} + +.w-9 { + width: 2.25rem; +} + +.flex-grow { + flex-grow: 1; +} + .scale-150 { --tw-scale-x: 1.5; --tw-scale-y: 1.5; @@ -623,18 +647,26 @@ video { align-items: center; } -.justify-start { - justify-content: flex-start; +.justify-normal { + justify-content: normal; } -.justify-center { - justify-content: center; +.justify-start { + justify-content: flex-start; } .justify-between { justify-content: space-between; } +.overflow-hidden { + overflow: hidden; +} + +.overflow-y-auto { + overflow-y: auto; +} + .truncate { overflow: hidden; text-overflow: ellipsis; @@ -695,24 +727,47 @@ video { padding-right: 0.75rem; } -.px-4 { - padding-left: 1rem; - padding-right: 1rem; -} - .py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; } +.pl-4 { + padding-left: 1rem; +} + .pt-1 { padding-top: 0.25rem; } +.pr-4 { + padding-right: 1rem; +} + +.pt-4 { + padding-top: 1rem; +} + +.pt-3 { + padding-top: 0.75rem; +} + +.pt-2 { + padding-top: 0.5rem; +} + +.pt-2\.5 { + padding-top: 0.625rem; +} + .text-center { text-align: center; } +.text-right { + text-align: right; +} + .align-middle { vertical-align: middle; } @@ -746,6 +801,11 @@ video { line-height: 1.75rem; } +.text-base { + font-size: 1rem; + line-height: 1.5rem; +} + .font-bold { font-weight: 700; } @@ -774,10 +834,6 @@ video { outline-offset: 2px; } -.filter { - filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow); -} - .transition-transform { transition-property: transform; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); @@ -792,6 +848,10 @@ video { transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } +.fitView { + height: calc(100vh - 7.5rem); +} + .hover\:scale-110:hover { --tw-scale-x: 1.1; --tw-scale-y: 1.1; diff --git a/view/components/addTagForm.templ b/view/components/addTagForm.templ index 7698d84..5affe35 100644 --- a/view/components/addTagForm.templ +++ b/view/components/addTagForm.templ @@ -2,14 +2,14 @@ package components templ AddTagForm(){
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } diff --git a/view/components/songCard.templ b/view/components/songCard.templ index bff8bfc..288c140 100644 --- a/view/components/songCard.templ +++ b/view/components/songCard.templ @@ -1,6 +1,7 @@ package components import "github.com/JaiiR320/SpotifAI/model" +import "strconv" func truncate(str string, m int) string { if len(str) > m { @@ -10,9 +11,12 @@ func truncate(str string, m int) string { } -templ SongCard(song model.Track){ +templ SongCard(song model.Track, index int){
-
+
+
+ { strconv.Itoa(index + 1) } +
Song Image
diff --git a/view/components/songCard_templ.go b/view/components/songCard_templ.go index 02c274b..9d6c929 100644 --- a/view/components/songCard_templ.go +++ b/view/components/songCard_templ.go @@ -11,6 +11,7 @@ import "io" import "bytes" import "github.com/JaiiR320/SpotifAI/model" +import "strconv" func truncate(str string, m int) string { if len(str) > m { @@ -20,7 +21,7 @@ func truncate(str string, m int) string { } -func SongCard(song model.Track) templ.Component { +func SongCard(song model.Track, index int) templ.Component { return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) if !templ_7745c5c3_IsBuffer { @@ -33,7 +34,20 @@ func SongCard(song model.Track) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var2 string + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(index + 1)) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `view\components\songCard.templ`, Line: 17, Col: 41} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
+
-
+
Tags
-
- @components.AddTagForm() -
+ @components.AddTagForm()
for _, tag := range model.Tags { @@ -20,22 +18,16 @@ templ Content(){ }
-
+
if !model.Logged {
Please login
} else { -
- @TrackList(model.FilteredSongs) -
+ for i, item := range model.FilteredSongs { + @components.SongCard(item.Track, i) + } }
-} - -templ TrackList(items []model.Item){ - for _, item := range items { - @components.SongCard(item.Track) - } } \ No newline at end of file diff --git a/view/layout/content_templ.go b/view/layout/content_templ.go index 0a24e6c..52e44db 100644 --- a/view/layout/content_templ.go +++ b/view/layout/content_templ.go @@ -28,7 +28,7 @@ func Content() templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Tags
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
Tags
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -36,7 +36,7 @@ func Content() templ.Component { if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -46,7 +46,7 @@ func Content() templ.Component { return templ_7745c5c3_Err } } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } @@ -56,17 +56,11 @@ func Content() templ.Component { return templ_7745c5c3_Err } } else { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - templ_7745c5c3_Err = TrackList(model.FilteredSongs).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err + for i, item := range model.FilteredSongs { + templ_7745c5c3_Err = components.SongCard(item.Track, i).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } } } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("
") @@ -79,29 +73,3 @@ func Content() templ.Component { return templ_7745c5c3_Err }) } - -func TrackList(items []model.Item) templ.Component { - return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) { - templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer) - if !templ_7745c5c3_IsBuffer { - templ_7745c5c3_Buffer = templ.GetBuffer() - defer templ.ReleaseBuffer(templ_7745c5c3_Buffer) - } - ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var2 := templ.GetChildren(ctx) - if templ_7745c5c3_Var2 == nil { - templ_7745c5c3_Var2 = templ.NopComponent - } - ctx = templ.ClearChildren(ctx) - for _, item := range items { - templ_7745c5c3_Err = components.SongCard(item.Track).Render(ctx, templ_7745c5c3_Buffer) - if templ_7745c5c3_Err != nil { - return templ_7745c5c3_Err - } - } - if !templ_7745c5c3_IsBuffer { - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W) - } - return templ_7745c5c3_Err - }) -} diff --git a/view/layout/navbar.templ b/view/layout/navbar.templ index 8d1e726..6f52342 100644 --- a/view/layout/navbar.templ +++ b/view/layout/navbar.templ @@ -38,7 +38,7 @@ templ userImage(){ } templ Navbar(){ -