Skip to content

Commit 5fe5126

Browse files
authored
Merge pull request #2 from KunalKumar-1/attendees
feat: added attendees to events
2 parents dd13b1d + 50d4003 commit 5fe5126

File tree

8 files changed

+277
-9
lines changed

8 files changed

+277
-9
lines changed

cmd/api/auth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func (app *application) registerUser(c *gin.Context) {
3838
Password: register.Password,
3939
Name: register.Name,
4040
}
41-
41+
//checking
4242
err = app.models.Users.Insert(user)
4343
if err != nil {
4444
c.JSON(http.StatusInternalServerError, gin.H{

cmd/api/events.go

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"github.com/kunalkumar-1/Evently/internals/database"
1010
)
1111

12-
// create event
12+
// create event handler
1313
func (app *application) createEvent(c *gin.Context) {
1414

1515
var event database.Event
@@ -144,3 +144,140 @@ func (app *application) deleteEvent(c *gin.Context) {
144144

145145
c.JSON(http.StatusNoContent, nil)
146146
}
147+
148+
func (app *application) addAttendeeToEvent(c *gin.Context) {
149+
eventId, err := strconv.Atoi(c.Param("id"))
150+
if err != nil {
151+
c.JSON(http.StatusBadRequest, gin.H{
152+
"error": "Invalid event Id",
153+
})
154+
return
155+
}
156+
157+
userId, err := strconv.Atoi(c.Param("userId"))
158+
if err != nil {
159+
c.JSON(http.StatusBadRequest, gin.H{
160+
"error": "Invalid user Id",
161+
})
162+
return
163+
}
164+
165+
event, err := app.models.Events.Get(eventId) //get event by id
166+
if err != nil { // if error in getting event
167+
c.JSON(http.StatusInternalServerError, gin.H{
168+
"error": "Failed to retrieve event",
169+
})
170+
return
171+
}
172+
if event == nil { // if event not found
173+
c.JSON(http.StatusBadRequest, gin.H{
174+
"error": "Event not found",
175+
})
176+
return
177+
}
178+
179+
userToAdd, err := app.models.Users.Get(userId) //get user by id
180+
if err != nil { // if error in getting user
181+
c.JSON(http.StatusInternalServerError, gin.H{
182+
"error": "Failed to retrieve user",
183+
})
184+
return
185+
}
186+
if userToAdd == nil {
187+
c.JSON(http.StatusNotFound, gin.H{
188+
"error": "User not found",
189+
})
190+
return
191+
}
192+
193+
existingAttendee, err := app.models.Attendees.GetByEventAndAttendee(event.Id, userToAdd.Id) //get user by id
194+
if err != nil { // if error in getting user
195+
c.JSON(http.StatusInternalServerError, gin.H{
196+
"error": "Failed to retrieve attendee",
197+
})
198+
return
199+
}
200+
if existingAttendee != nil {
201+
c.JSON(http.StatusConflict, gin.H{
202+
"error": "Attendee already Exists",
203+
})
204+
return
205+
}
206+
207+
attendee := &database.Attendee{
208+
EventId: eventId,
209+
UserId: userToAdd.Id,
210+
}
211+
212+
_, err = app.models.Attendees.Insert(attendee)
213+
if err != nil {
214+
c.JSON(http.StatusInternalServerError, gin.H{
215+
"error": "failed to add attendee",
216+
})
217+
return
218+
}
219+
220+
c.JSON(http.StatusCreated, attendee)
221+
}
222+
223+
func (app *application) getAttendeesForEvent(c *gin.Context) {
224+
id, err := strconv.Atoi(c.Param("id"))
225+
if err != nil {
226+
c.JSON(http.StatusBadRequest, gin.H{
227+
"error": "Invalid event Id",
228+
})
229+
return
230+
}
231+
users, err := app.models.Attendees.GetAttendeeByEvent(id)
232+
if err != nil {
233+
c.JSON(http.StatusInternalServerError, gin.H{
234+
"error": "failed to retrieve Attendees for events",
235+
})
236+
return
237+
}
238+
c.JSON(http.StatusOK, users)
239+
}
240+
241+
func (app *application) deleteAttendeeFromEvent(c *gin.Context) {
242+
id, err := strconv.Atoi(c.Param("id")) //event id
243+
if err != nil {
244+
c.JSON(http.StatusBadRequest, gin.H{
245+
"error": "Invalid event Id",
246+
})
247+
}
248+
249+
userId, err := strconv.Atoi(c.Param("userId"))
250+
if err != nil {
251+
c.JSON(http.StatusBadRequest, gin.H{
252+
"error": "Invalid userId Id",
253+
})
254+
}
255+
256+
err = app.models.Attendees.Delete(userId, id)
257+
if err != nil {
258+
c.JSON(http.StatusInternalServerError, gin.H{
259+
"error": "Failed to delete attendee",
260+
})
261+
}
262+
263+
c.JSON(http.StatusNoContent, nil)
264+
}
265+
266+
func (app *application) getEventsByAttendee(c *gin.Context) {
267+
id, err := strconv.Atoi(c.Param("id"))
268+
if err != nil {
269+
c.JSON(http.StatusBadRequest, gin.H{
270+
"error": "Invalid attendee Id",
271+
})
272+
return
273+
}
274+
user, err := app.models.Users.Get(id)
275+
if err != nil {
276+
c.JSON(http.StatusInternalServerError, gin.H{
277+
"error": "failed to get events",
278+
})
279+
return
280+
}
281+
282+
c.JSON(http.StatusOK, user)
283+
}

cmd/api/routes.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ func (app *application) routes() http.Handler {
1111

1212
v1 := r.Group("/api/v1")
1313
{
14-
v1.POST("/events", app.createEvent) // create event
15-
v1.GET("/events", app.getAllEvent) // get all events
16-
v1.GET("/events/:id", app.getEvent) // get event by id
17-
v1.PUT("/events/:id", app.updateEvent) // update event by id
18-
v1.DELETE("/events/:id", app.deleteEvent) //delete the event by id
14+
v1.POST("/events", app.createEvent) // create event
15+
v1.GET("/events", app.getAllEvent) // get all events
16+
v1.GET("/events/:id", app.getEvent) // get event by id
17+
v1.PUT("/events/:id", app.updateEvent) // update event by id
18+
v1.DELETE("/events/:id", app.deleteEvent) //delete the event by id
19+
v1.GET("/events/:id/attendees/:userId", app.getAttendeesForEvent) // get attendee to event
20+
v1.POST("/events/:id/attendees/:userId", app.addAttendeeToEvent) // add attendee to event
21+
v1.DELETE("/events/:id/attendees/:userId", app.deleteAttendeeFromEvent) //delete attendee from event
22+
v1.GET("/events/:id/attendees", app.getEventsByAttendee) //get attendees for event
1923

2024
v1.POST("/auth/register", app.registerUser) // register user
2125
}

data.db

0 Bytes
Binary file not shown.

internals/database/attendee.go

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package database
22

3-
import "database/sql"
3+
import (
4+
"context"
5+
"database/sql"
6+
"time"
7+
)
48

59
type AttendeeModel struct {
610
Db *sql.DB
@@ -11,3 +15,110 @@ type Attendee struct {
1115
EventId int `json:"eventid"`
1216
UserId int `json:"userid"`
1317
}
18+
19+
// Insert a new attendee into the database
20+
func (a *AttendeeModel) Insert(attendee *Attendee) (*Attendee, error) {
21+
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
22+
defer cancel()
23+
24+
query := `INSERT INTO attendees (event_id, user_id) VALUES($1, $2) RETURNING id`
25+
err := a.Db.QueryRowContext(ctx, query, attendee.EventId, attendee.UserId).Scan(&attendee.Id)
26+
27+
if err != nil {
28+
return nil, err
29+
}
30+
return attendee, nil
31+
}
32+
33+
// GetByEventAndAttendee retrieves an attendee by event ID and user ID
34+
func (a *AttendeeModel) GetByEventAndAttendee(eventId, userId int) (*Attendee, error) {
35+
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
36+
defer cancel()
37+
38+
query := `SELECT id, event_id, user_id FROM attendees WHERE event_id = $1 AND user_id = $2`
39+
40+
var attendee Attendee
41+
err := a.Db.QueryRowContext(ctx, query, eventId, userId).Scan(&attendee.Id, &attendee.EventId, &attendee.UserId)
42+
if err != nil {
43+
if err == sql.ErrNoRows {
44+
return nil, nil
45+
}
46+
47+
return nil, err
48+
}
49+
return &attendee, nil
50+
}
51+
52+
func (a *AttendeeModel) GetAttendeeByEvent(eventId int) ([]*User, error) {
53+
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
54+
defer cancel()
55+
56+
query := `
57+
SELECT u.id, u.name, u.email
58+
FROM users u
59+
JOIN attendees a ON u.id = a.user_id
60+
WHERE a.event_id = $1
61+
`
62+
rows, err := a.Db.QueryContext(ctx, query, eventId)
63+
if err != nil {
64+
return nil, err
65+
}
66+
67+
defer rows.Close()
68+
69+
var users []*User
70+
71+
for rows.Next() { // looping through all the rows
72+
var user User
73+
err := rows.Scan(&user.Id, &user.Name, &user.Email)
74+
if err != nil {
75+
return nil, err
76+
}
77+
78+
users = append(users, &user) // appending the user to the users slice
79+
}
80+
81+
return users, nil
82+
}
83+
84+
func (a *AttendeeModel) Delete(userId, eventId int) error {
85+
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
86+
defer cancel()
87+
88+
query := `DELETE FROM attendees WHERE user_id = $1 AND event_id = $2`
89+
_, err := a.Db.ExecContext(ctx, query, userId, eventId)
90+
if err != nil {
91+
return err
92+
}
93+
return nil
94+
}
95+
96+
func (a *AttendeeModel) GetEventsByAttendee(AttendeeId int) ([]*Event, error) {
97+
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
98+
defer cancel()
99+
100+
query := `
101+
SELECT e.id, e.owner_id, e.name, e.description, e.date, e.location
102+
FROM events e
103+
JOIN attendees a ON e.id = a.event_id
104+
WHERE a.user_id = $1
105+
`
106+
row, err := a.Db.QueryContext(ctx, query, AttendeeId)
107+
if err != nil {
108+
return nil, err
109+
}
110+
111+
defer row.Close()
112+
113+
var events []*Event
114+
115+
for row.Next() {
116+
var event Event
117+
err := row.Scan(&event.Id, &event.OwnerId, &event.Name, &event.Description, &event.Date, &event.Location)
118+
if err != nil {
119+
return nil, err
120+
}
121+
events = append(events, &event)
122+
}
123+
return events, nil
124+
}

internals/database/users.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,19 @@ func (u *UserModel) Insert(user *User) error {
2626
return u.Db.QueryRowContext(ctx, query, user.Name, user.Email, user.Password).Scan(&user.Id)
2727

2828
}
29+
30+
func (u *UserModel) Get(id int) (*User, error) {
31+
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
32+
defer cancel()
33+
34+
query := `SELECT * FROM users WHERE id = $1`
35+
var user User
36+
err := u.Db.QueryRowContext(ctx, query, id).Scan(&user.Id, &user.Name, &user.Email, &user.Password)
37+
if err != nil {
38+
if err == sql.ErrNoRows {
39+
return nil, nil
40+
}
41+
return nil, err
42+
}
43+
return &user, nil
44+
}

tmp/build-errors.log

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +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 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 1

tmp/main

1.42 KB
Binary file not shown.

0 commit comments

Comments
 (0)