Skip to content

Commit 3de582e

Browse files
committed
profile & team history work now
1 parent 8447335 commit 3de582e

File tree

11 files changed

+280
-14
lines changed

11 files changed

+280
-14
lines changed

api/openapi.yaml

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,33 @@ paths:
238238
content:
239239
application/json:
240240
schema: {}
241+
'/api/v1/users/{userId}/profile':
242+
get:
243+
tags:
244+
- Users
245+
summary: Get a profile by user ID
246+
operationId: getProfileById
247+
parameters:
248+
- name: userId
249+
in: path
250+
required: true
251+
style: simple
252+
explode: false
253+
schema:
254+
type: string
255+
format: uuid
256+
example: 81e17cb6-5c46-4934-b6d5-5c8356712cb6
257+
responses:
258+
'200':
259+
description: Detailed information of a profile
260+
content:
261+
application/json:
262+
schema:
263+
$ref: '#/components/schemas/ProfileResponse'
264+
'400':
265+
description: Bad request
266+
'500':
267+
description: Failed response
241268
/api/v1/games:
242269
get:
243270
tags:
@@ -807,6 +834,50 @@ components:
807834
format: uuid
808835
example: 81e17cb6-5c46-4934-b6d5-5c8356712cb6
809836
description: Unique identifier for the result entry
837+
ProfileResponse:
838+
type: object
839+
description: The response schema for a user's profile, including id, timestamps, team name, and team history.
840+
properties:
841+
id:
842+
type: string
843+
format: uuid
844+
description: The unique identifier for the user.
845+
created_at:
846+
type: string
847+
format: date-time
848+
description: The timestamp when the user profile was created.
849+
updated_at:
850+
type: string
851+
format: date-time
852+
description: The timestamp when the user profile was last updated.
853+
team_name:
854+
type: string
855+
description: The current name of the user's team.
856+
team_history:
857+
type: array
858+
description: The list of teams the user has been part of, including the periods of membership.
859+
items:
860+
$ref: '#/components/schemas/TeamHistory'
861+
TeamHistory:
862+
required:
863+
- name
864+
- join
865+
type: object
866+
description: The schema for recording the history of teams a user has joined and left.
867+
properties:
868+
name:
869+
type: string
870+
description: The name of the team.
871+
join:
872+
type: string
873+
format: date-time
874+
description: The timestamp when the user joined the team.
875+
example: '2024-01-23T04:56:07.000Z'
876+
left:
877+
type: string
878+
format: date-time
879+
description: The timestamp when the user left the team.
880+
example: '2024-01-23T04:56:07.000Z'
810881
UserResponse:
811882
type: object
812883
properties:
@@ -844,12 +915,12 @@ components:
844915
type: string
845916
description: The start time of the game
846917
format: date-time
847-
example: '2000-01-23T04:56:07.000Z'
918+
example: '2024-01-23T04:56:07.000Z'
848919
end_time:
849920
type: string
850921
description: The end time of the game
851922
format: date-time
852-
example: '2000-01-24T04:56:07.000Z'
923+
example: '2024-01-24T04:56:07.000Z'
853924
description:
854925
type: string
855926
description: A brief description of the game
@@ -868,12 +939,12 @@ components:
868939
type: string
869940
description: The start time of the game
870941
format: date-time
871-
example: '2000-01-23T04:56:07.000Z'
942+
example: '2024-01-23T04:56:07.000Z'
872943
end_time:
873944
type: string
874945
description: The end time of the game
875946
format: date-time
876-
example: '2000-01-24T04:56:07.000Z'
947+
example: '2024-01-24T04:56:07.000Z'
877948
description:
878949
type: string
879950
description: A brief description of the game

internal/app/database/struct_updater.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ func RegisterAllUpdates() map[string][]DatabaseUpdateFunc {
4141
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0014_update0014fix1)
4242
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0014_update0015)
4343
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0015_update0015testdata)
44+
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0015_update0016)
45+
allUpdates = RegisterDatabaseUpdate(allUpdates, DatabaseUpdate_update0016_update0016testdata)
4446
return allUpdates
4547
}
4648

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package database
2+
3+
import (
4+
"database/sql"
5+
"log/slog"
6+
"runtime"
7+
)
8+
9+
func DatabaseUpdate_update0016_update0016testdata(db *sql.DB, getInfo bool) (string, string, string, error) {
10+
11+
// WARNING!!!
12+
// Do not change the update if it has already been installed by other developers or in production.
13+
// To correct the database, create a new update and register it in the list of updates.
14+
15+
fromUpdateId, toUpdateId := ParseNameFuncUpdate(runtime.Caller(0))
16+
description := "Flush team_history table"
17+
if getInfo {
18+
return fromUpdateId, toUpdateId, description, nil
19+
}
20+
21+
query := `
22+
INSERT INTO team_history (user_id, team_id, joined_at)
23+
SELECT user_id, current_team_id, created_at
24+
FROM profiles
25+
`
26+
_, err := db.Query(query)
27+
if err != nil {
28+
slog.Error("Problem with select, query: " + query + "\n error:" + err.Error())
29+
return fromUpdateId, toUpdateId, description, err
30+
}
31+
return fromUpdateId, toUpdateId, description, nil
32+
}

internal/app/db/profile.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package db
2+
3+
import (
4+
"time"
5+
)
6+
7+
type Profile struct {
8+
CurrentTeam string `db:"name"`
9+
CreatedAt time.Time `db:"created_at"`
10+
UpdatedAt time.Time `db:"created_at"`
11+
}
12+
13+
type ProfileTeams struct {
14+
JoinedAt time.Time `db:"joined_at"`
15+
LeftAt *time.Time `db:"left_at"`
16+
Name string `db:"name"`
17+
}
18+
19+
type ProfileWithHistory struct {
20+
Profile Profile
21+
History []ProfileTeams
22+
}

internal/app/handlers/interface.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ func (siw *ServerInterfaceWrapper) GetUserById(w http.ResponseWriter, r *http.Re
120120
siw.handlers.GetUserById(w, r, id)
121121
}
122122

123+
func (siw *ServerInterfaceWrapper) GetProfileById(w http.ResponseWriter, r *http.Request, id openapi_types.UUID) {
124+
siw.handlers.GetProfileById(w, r, id)
125+
}
126+
123127
func (siw *ServerInterfaceWrapper) UpdateUser(w http.ResponseWriter, r *http.Request, id openapi_types.UUID) {
124128
siw.handlers.UpdateUser(w, r, id)
125129
}

internal/app/handlers/users.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,17 @@ func (h *Handlers) GetUserById(w http.ResponseWriter, r *http.Request, id openap
7373
api_helpers.RespondWithJSON(w, http.StatusOK, view.NewUserFromModel(user))
7474
}
7575

76+
func (h *Handlers) GetProfileById(w http.ResponseWriter, r *http.Request, id openapi_types.UUID) {
77+
repo := repository.NewUserRepository(h.DB)
78+
userProfile, err := repo.GetProfileWithHistory(r.Context(), id)
79+
if err != nil {
80+
slog.Warn(err.Error(), "handler", "GetProfileByIdHandler")
81+
api_helpers.RespondWithJSON(w, http.StatusInternalServerError, map[string]string{"error": "Failed to fetch user"})
82+
return
83+
}
84+
api_helpers.RespondWithJSON(w, http.StatusOK, view.NewProfileFromModel(userProfile))
85+
}
86+
7687
func (h *Handlers) ListUsers(w http.ResponseWriter, r *http.Request) {
7788
repo := repository.NewUserRepository(h.DB)
7889
users, err := repo.List(r.Context())

internal/app/repository/game.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func (r *gameRepo) GetGameDetails(ctx context.Context, id openapi_types.UUID) (*
3939
FROM games g
4040
JOIN team_games tg ON g.id = tg.game_id
4141
JOIN teams t ON tg.team_id = t.id
42-
JOIN profiles tm ON t.id = tm.team_id
42+
JOIN profiles tm ON t.id = tm.current_team_id
4343
JOIN users u ON tm.user_id = u.id
4444
WHERE g.id = $1;
4545
`

internal/app/repository/user.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type UserRepository interface {
1212
Create(ctx context.Context, user *models.User) error
1313
AddUserToTeams(ctx context.Context, userId openapi_types.UUID, teamIds *[]openapi_types.UUID) error
1414
GetById(ctx context.Context, id openapi_types.UUID) (*models.User, error)
15+
GetProfileWithHistory(ctx context.Context, id openapi_types.UUID) (*models.ProfileWithHistory, error)
1516
GetByUserName(ctx context.Context, id string) (*models.User, error)
1617
Update(ctx context.Context, user *models.User) error
1718
Delete(ctx context.Context, id openapi_types.UUID) error
@@ -47,6 +48,42 @@ func (r *userRepo) AddUserToTeams(ctx context.Context, userId openapi_types.UUID
4748
return nil
4849
}
4950

51+
func (r *userRepo) GetProfileWithHistory(ctx context.Context, id openapi_types.UUID) (*models.ProfileWithHistory, error) {
52+
query := `
53+
SELECT teams.name, created_at, updated_at
54+
FROM profiles JOIN teams on profiles.current_team_id=teams.id
55+
WHERE profiles.user_id = $1
56+
`
57+
profile := models.Profile{}
58+
err := r.db.QueryRowContext(ctx, query, id).Scan(&profile.CurrentTeam, &profile.CreatedAt, &profile.UpdatedAt)
59+
if err != nil {
60+
return nil, err
61+
}
62+
query = `
63+
SELECT joined_at, left_at, name
64+
FROM team_history
65+
JOIN teams ON teams.id = team_history.team_id
66+
WHERE user_id = $1
67+
`
68+
rows, err := r.db.QueryContext(ctx, query, id)
69+
var history []models.ProfileTeams
70+
for rows.Next() {
71+
var team models.ProfileTeams
72+
err := rows.Scan(&team.JoinedAt, &team.LeftAt, &team.Name)
73+
if err != nil {
74+
return nil, err
75+
}
76+
history = append(history, team)
77+
}
78+
if err != nil {
79+
return nil, err
80+
}
81+
return &models.ProfileWithHistory{
82+
Profile: profile,
83+
History: history,
84+
}, nil
85+
}
86+
5087
func (r *userRepo) GetById(ctx context.Context, id openapi_types.UUID) (*models.User, error) {
5188
query := `SELECT id, display_name, user_name, avatar_url, role, status FROM users WHERE id = $1`
5289
user := &models.User{}

internal/app/server/server.gen.go

Lines changed: 68 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)