@@ -7,6 +7,57 @@ import (
77 "gorm.io/gorm"
88)
99
10+ type UserPreferences map [string ]interface {}
11+
12+ const (
13+ PREF_SHOW_LOCATION = "privacy.show_location"
14+ PREF_SHOW_LAST_SEEN = "privacy.show_last_seen"
15+ PREF_ALLOW_SEARCH = "privacy.allow_search"
16+
17+ PREF_LANGUAGE = "app.language"
18+ PREF_THEME = "app.theme"
19+ PREF_TIMEZONE = "app.timezone"
20+ PREF_NOTIFICATIONS = "notifications.enabled"
21+ PREF_EMAIL_NOTIFICATIONS = "notifications.email"
22+ PREF_PUSH_NOTIFICATIONS = "notifications.push"
23+ )
24+
25+ func DefaultUserPreferences () UserPreferences {
26+ return UserPreferences {
27+ PREF_SHOW_LOCATION : true ,
28+ PREF_SHOW_LAST_SEEN : true ,
29+ PREF_ALLOW_SEARCH : true ,
30+ PREF_LANGUAGE : "tr" ,
31+ PREF_THEME : "auto" ,
32+ PREF_TIMEZONE : "Europe/Istanbul" ,
33+ PREF_NOTIFICATIONS : true ,
34+ PREF_EMAIL_NOTIFICATIONS : false ,
35+ PREF_PUSH_NOTIFICATIONS : true ,
36+ }
37+ }
38+
39+ func (up UserPreferences ) GetBool (key string , defaultVal bool ) bool {
40+ if val , exists := up [key ]; exists {
41+ if boolVal , ok := val .(bool ); ok {
42+ return boolVal
43+ }
44+ }
45+ return defaultVal
46+ }
47+
48+ func (up UserPreferences ) GetString (key string , defaultVal string ) string {
49+ if val , exists := up [key ]; exists {
50+ if strVal , ok := val .(string ); ok {
51+ return strVal
52+ }
53+ }
54+ return defaultVal
55+ }
56+
57+ func (up UserPreferences ) Set (key string , value interface {}) {
58+ up [key ] = value
59+ }
60+
1061type User struct {
1162 ID uint `json:"id" gorm:"primaryKey"`
1263 Username string `json:"username" gorm:"uniqueIndex;not null" validate:"required,min=3,max=50"`
@@ -27,6 +78,8 @@ type User struct {
2778 IsOnline bool `json:"is_online" gorm:"default:false"`
2879 LastSeen * time.Time `json:"last_seen"`
2980
81+ Preferences UserPreferences `json:"preferences" gorm:"type:jsonb;default:'{}'"`
82+
3083 OwnedClubs []Club `json:"owned_clubs,omitempty" gorm:"foreignKey:OwnerID" swaggerignore:"true"`
3184 ClubMemberships []ClubMembership `json:"club_memberships,omitempty" gorm:"foreignKey:UserID" swaggerignore:"true"`
3285 Posts []Post `json:"posts,omitempty" gorm:"foreignKey:UserID" swaggerignore:"true"`
@@ -41,23 +94,23 @@ type User struct {
4194
4295type PublicUserProfile struct {
4396 ID uint `json:"id"`
44- Username string `json:"username"`
45- FirstName string `json:"first_name"`
46- LastName string `json:"last_name"`
47- AvatarURL * string `json:"avatar_url"`
48- Location * string `json:"location"`
49- FavoriteGenres pq.StringArray `json:"favorite_genres"`
50- Bio * string `json:"bio"`
51- BooksRead int `json:"books_read"`
52- Badges pq.StringArray `json:"badges"`
53- IsOnline bool `json:"is_online"`
54- LastSeen * time.Time `json:"last_seen,omitempty"`
55- JoinedAt time.Time `json:"joined_at"`
56-
57- TotalPosts int `json:"total_posts"`
58- TotalComments int `json:"total_comments"`
59- ClubsCount int `json:"clubs_count"`
60- ReadingStreak int `json:"reading_streak,omitempty"`
97+ Username string `json:"username"`
98+ FirstName string `json:"first_name"`
99+ LastName string `json:"last_name"`
100+ AvatarURL * string `json:"avatar_url"`
101+ Location * string `json:"location"`
102+ FavoriteGenres pq.StringArray `json:"favorite_genres"`
103+ Bio * string `json:"bio"`
104+ BooksRead int `json:"books_read"`
105+ Badges pq.StringArray `json:"badges"`
106+ IsOnline bool `json:"is_online"`
107+ LastSeen * time.Time `json:"last_seen,omitempty"`
108+ JoinedAt time.Time `json:"joined_at"`
109+
110+ TotalPosts int `json:"total_posts"`
111+ TotalComments int `json:"total_comments"`
112+ ClubsCount int `json:"clubs_count"`
113+ ReadingStreak int `json:"reading_streak,omitempty"`
61114}
62115
63116type UserResponse struct {
@@ -79,6 +132,8 @@ type UserResponse struct {
79132 IsOnline bool `json:"is_online"`
80133 LastSeen * time.Time `json:"last_seen"`
81134
135+ Preferences UserPreferences `json:"preferences"`
136+
82137 OwnedClubs []Club `json:"owned_clubs,omitempty" swaggerignore:"true"`
83138 ClubMemberships []ClubMembership `json:"club_memberships,omitempty" swaggerignore:"true"`
84139 Posts []Post `json:"posts,omitempty" swaggerignore:"true"`
@@ -148,7 +203,15 @@ type UpdateAccountRequest struct {
148203 Username * string `json:"username,omitempty" validate:"omitempty,min=3,max=50"`
149204}
150205
206+ type UpdatePreferencesRequest struct {
207+ Preferences UserPreferences `json:"preferences" validate:"required"`
208+ }
209+
151210func (u * User ) ToResponse () UserResponse {
211+ if len (u .Preferences ) == 0 {
212+ u .Preferences = DefaultUserPreferences ()
213+ }
214+
152215 return UserResponse {
153216 ID : u .ID ,
154217 Username : u .Username ,
@@ -166,6 +229,7 @@ func (u *User) ToResponse() UserResponse {
166229 Badges : u .Badges ,
167230 IsOnline : u .IsOnline ,
168231 LastSeen : u .LastSeen ,
232+ Preferences : u .Preferences ,
169233 OwnedClubs : u .OwnedClubs ,
170234 ClubMemberships : u .ClubMemberships ,
171235 Posts : u .Posts ,
@@ -187,19 +251,34 @@ type SuccessResponse struct {
187251}
188252
189253func (u * User ) ToPublicProfile () PublicUserProfile {
190- return PublicUserProfile {
191- ID : u .ID ,
192- Username : u .Username ,
193- FirstName : u .FirstName ,
194- LastName : u .LastName ,
195- AvatarURL : u .AvatarURL ,
196- Location : u .Location ,
197- FavoriteGenres : u .FavoriteGenres ,
198- Bio : u .Bio ,
199- BooksRead : u .BooksRead ,
200- Badges : u .Badges ,
201- IsOnline : u .IsOnline ,
202- LastSeen : u .LastSeen ,
203- JoinedAt : u .CreatedAt ,
204- }
205- }
254+ prefs := u .Preferences
255+ if len (prefs ) == 0 {
256+ prefs = DefaultUserPreferences ()
257+ }
258+
259+ profile := PublicUserProfile {
260+ ID : u .ID ,
261+ Username : u .Username ,
262+ FirstName : u .FirstName ,
263+ LastName : u .LastName ,
264+ JoinedAt : u .CreatedAt ,
265+ BooksRead : u .BooksRead ,
266+ Badges : u .Badges ,
267+ IsOnline : u .IsOnline ,
268+ }
269+
270+ if prefs .GetBool (PREF_SHOW_LOCATION , true ) {
271+ profile .Location = u .Location
272+ }
273+
274+ if prefs .GetBool (PREF_SHOW_LAST_SEEN , true ) && u .LastSeen != nil && u .IsOnline {
275+ since := time .Since (* u .LastSeen )
276+ if since <= 15 * time .Minute {
277+ profile .LastSeen = u .LastSeen
278+ }
279+ }
280+
281+ profile .AvatarURL = u .AvatarURL
282+
283+ return profile
284+ }
0 commit comments