Skip to content

Commit 1af0eb1

Browse files
feat: link frontend to backend for guests
1 parent 4701446 commit 1af0eb1

File tree

16 files changed

+245
-248
lines changed

16 files changed

+245
-248
lines changed

backend/docs/swagger.yaml

Lines changed: 56 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -139,16 +139,12 @@ definitions:
139139
items:
140140
type: integer
141141
type: array
142-
hotel_id:
143-
type: string
144142
limit:
145143
maximum: 100
146144
minimum: 1
147145
type: integer
148146
search:
149147
type: string
150-
required:
151-
- hotel_id
152148
type: object
153149
GuestPage:
154150
properties:
@@ -162,18 +158,25 @@ definitions:
162158
GuestWithBooking:
163159
properties:
164160
first_name:
161+
example: Jane
165162
type: string
166163
floor:
164+
example: 3
167165
type: integer
168166
group_size:
167+
example: 2
169168
type: integer
170169
id:
170+
example: 530e8400-e458-41d4-a716-446655440000
171171
type: string
172172
last_name:
173+
example: Doe
173174
type: string
174175
preferred_name:
176+
example: Jane
175177
type: string
176178
room_number:
179+
example: 301
177180
type: integer
178181
required:
179182
- first_name
@@ -504,41 +507,36 @@ paths:
504507
post:
505508
consumes:
506509
- application/json
507-
description: Retrieves guests optionally filtered by floor
510+
description: Creates a guest with the given data
508511
parameters:
509-
- description: Hotel ID (UUID)
510-
in: header
511-
name: X-Hotel-ID
512-
required: true
513-
type: string
514-
- description: Guest filters
512+
- description: Guest data
515513
in: body
516-
name: body
514+
name: request
517515
required: true
518516
schema:
519-
$ref: '#/definitions/GuestFilters'
517+
$ref: '#/definitions/CreateGuest'
520518
produces:
521519
- application/json
522520
responses:
523521
"200":
524522
description: OK
525523
schema:
526-
$ref: '#/definitions/GuestPage'
524+
$ref: '#/definitions/Guest'
527525
"400":
528-
description: Bad Request
526+
description: Invalid guest body format
529527
schema:
530528
additionalProperties:
531529
type: string
532530
type: object
533531
"500":
534-
description: Internal Server Error
532+
description: Internal server error
535533
schema:
536534
additionalProperties:
537535
type: string
538536
type: object
539537
security:
540538
- BearerAuth: []
541-
summary: Get Guests
539+
summary: Creates a guest
542540
tags:
543541
- guests
544542
/api/v1/guests/{id}:
@@ -626,6 +624,47 @@ paths:
626624
summary: Updates a guest
627625
tags:
628626
- guests
627+
/api/v1/guests/search:
628+
post:
629+
consumes:
630+
- application/json
631+
description: Retrieves guests optionally filtered by floor
632+
parameters:
633+
- description: Hotel ID (UUID)
634+
in: header
635+
name: X-Hotel-ID
636+
required: true
637+
type: string
638+
- description: Guest filters
639+
in: body
640+
name: body
641+
required: true
642+
schema:
643+
$ref: '#/definitions/GuestFilters'
644+
produces:
645+
- application/json
646+
responses:
647+
"200":
648+
description: OK
649+
schema:
650+
$ref: '#/definitions/GuestPage'
651+
"400":
652+
description: Bad Request
653+
schema:
654+
additionalProperties:
655+
type: string
656+
type: object
657+
"500":
658+
description: Internal Server Error
659+
schema:
660+
additionalProperties:
661+
type: string
662+
type: object
663+
security:
664+
- BearerAuth: []
665+
summary: Get Guests
666+
tags:
667+
- guests
629668
/api/v1/guests/stays/{id}:
630669
get:
631670
consumes:

backend/internal/handler/guests.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func (h *GuestsHandler) UpdateGuest(c *fiber.Ctx) error {
168168
// @Failure 400 {object} map[string]string
169169
// @Failure 500 {object} map[string]string
170170
// @Security BearerAuth
171-
// @Router /api/v1/guests [post]
171+
// @Router /api/v1/guests/search [post]
172172
func (h *GuestsHandler) GetGuests(c *fiber.Ctx) error {
173173
hotelID := c.Get("X-Hotel-ID")
174174
var filters models.GuestFilters

backend/internal/models/guests.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type Guest struct {
2424
} //@name Guest
2525

2626
type GuestFilters struct {
27-
HotelID string `json:"hotel_id" validate:"required,uuid"`
27+
HotelID string `json:"hotel_id" validate:"required,uuid" swaggerignore:"true"`
2828
Floors []int `json:"floors"`
2929
GroupSize []int `json:"group_size"`
3030
Search string `json:"search"`
@@ -40,13 +40,13 @@ type GuestPage struct {
4040
} // @name GuestPage
4141

4242
type GuestWithBooking struct {
43-
ID string `json:"id"`
44-
FirstName string `json:"first_name"`
45-
LastName string `json:"last_name"`
46-
PreferredName string `json:"preferred_name"`
47-
Floor int `json:"floor"`
48-
RoomNumber int `json:"room_number"`
49-
GroupSize *int `json:"group_size"`
43+
ID string `json:"id" validate:"required" example:"530e8400-e458-41d4-a716-446655440000"`
44+
FirstName string `json:"first_name" validate:"required" example:"Jane"`
45+
LastName string `json:"last_name" validate:"required" example:"Doe"`
46+
PreferredName string `json:"preferred_name" validate:"required" example:"Jane"`
47+
Floor int `json:"floor" validate:"required" example:"3"`
48+
RoomNumber int `json:"room_number" validate:"required" example:"301"`
49+
GroupSize *int `json:"group_size" example:"2"`
5050
} // @name GuestWithBooking
5151

5252
type GuestWithStays struct {

backend/internal/repository/guests.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,10 @@ func (r *GuestsRepository) FindGuestWithStayHistory(ctx context.Context, id stri
108108
var status *models.BookingStatus
109109

110110
if guest == nil {
111-
guest = &models.GuestWithStays{}
111+
guest = &models.GuestWithStays{
112+
CurrentStays: []models.Stay{},
113+
PastStays: []models.Stay{},
114+
}
112115
}
113116

114117
err := rows.Scan(

clients/shared/src/index.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,18 @@ export {
4545
usePostApiV1Guests,
4646
useGetApiV1GuestsId,
4747
usePutApiV1GuestsId,
48+
usePostApiV1GuestsSearchHook,
49+
useGetApiV1GuestsStaysId,
4850
} from "./api/generated/endpoints/guests/guests";
4951

52+
export type {
53+
GuestWithBooking,
54+
GuestWithStays,
55+
GuestPage,
56+
GuestFilters,
57+
Stay,
58+
} from "./api/generated/models";
59+
5060
export { usePostRooms, useGetRoomsFloors } from "./api/generated/endpoints/rooms/rooms";
5161

5262
export type {

clients/web/src/components/guests/GuestNotesCard.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { useState } from "react";
22

33
type GuestNotesCardProps = {
4-
initialNotes: string;
4+
initialNotes?: string;
55
};
66

77
export function GuestNotesCard({ initialNotes }: GuestNotesCardProps) {
88
const [isEditing, setIsEditing] = useState(false);
9-
const [notes, setNotes] = useState(initialNotes);
10-
const [draft, setDraft] = useState(initialNotes);
9+
const [notes, setNotes] = useState(initialNotes ?? "");
10+
const [draft, setDraft] = useState(initialNotes ?? "");
1111

1212
const startEditing = () => {
1313
setDraft(notes);

clients/web/src/components/guests/GuestProfileCard.tsx

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1+
import type { GuestWithStays } from "@shared";
12
import { UserRound } from "lucide-react";
2-
import type { GuestProfile } from "./guest-mocks";
3+
import { formatDate } from "../../utils/dates";
34

45
type GuestProfileCardProps = {
5-
guest: GuestProfile;
6+
guest: GuestWithStays;
67
};
78

89
function DetailRow({ label, value }: { label: string; value: string }) {
@@ -15,6 +16,8 @@ function DetailRow({ label, value }: { label: string; value: string }) {
1516
}
1617

1718
export function GuestProfileCard({ guest }: GuestProfileCardProps) {
19+
const currentStay = (guest.current_stays ?? [])[0];
20+
1821
return (
1922
<section className="border border-black bg-white px-[1vw] py-[2vh]">
2023
<div className="mb-[2vh] flex items-start gap-[1.1vw]">
@@ -23,28 +26,27 @@ export function GuestProfileCard({ guest }: GuestProfileCardProps) {
2326
</div>
2427
<div>
2528
<p className="text-[2vw] font-medium leading-tight text-black">
26-
{guest.preferredName}
29+
{guest.first_name} {guest.last_name}
2730
</p>
28-
<p className="text-[1vw] text-black">{guest.pronouns}</p>
2931
</div>
3032
</div>
3133

32-
<div className="border-b border-[#d3d8df] pb-[1vh]">
33-
<DetailRow label="Government Name" value={guest.governmentName} />
34-
<DetailRow label="Date of Birth" value={guest.dateOfBirth} />
35-
</div>
36-
3734
<div className="pt-[1vh]">
38-
<DetailRow label="Room" value={guest.room} />
39-
<DetailRow label="Group Size" value={String(guest.groupSize)} />
40-
<DetailRow
41-
label="Arrival"
42-
value={`${guest.arrivalTime} ${guest.arrivalDate}`}
43-
/>
44-
<DetailRow
45-
label="Departure"
46-
value={`${guest.departureTime} ${guest.departureDate}`}
47-
/>
35+
{currentStay ? (
36+
<>
37+
<DetailRow label="Room" value={String(currentStay.room_number)} />
38+
<DetailRow
39+
label="Arrival"
40+
value={formatDate(currentStay.arrival_date)}
41+
/>
42+
<DetailRow
43+
label="Departure"
44+
value={formatDate(currentStay.departure_date)}
45+
/>
46+
</>
47+
) : (
48+
<p className="text-[1vw] text-[#b6bac3]">No active stay.</p>
49+
)}
4850
</div>
4951
</section>
5052
);

clients/web/src/components/guests/GuestQuickListTable.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
import type { GuestWithBooking } from "@shared";
12
import { UserRound } from "lucide-react";
2-
import type { GuestListItem } from "./guest-mocks";
33

44
type GuestQuickListTableProps = {
5-
guests: Array<GuestListItem>;
5+
guests: Array<GuestWithBooking>;
66
groupFilter: string;
77
floorFilter: string;
88
onGroupFilterChange: (value: string) => void;
@@ -68,14 +68,14 @@ export function GuestQuickListTable({
6868
>
6969
{avatarPill()}
7070
<p className="truncate text-[1vw] text-black">
71-
{guest.governmentName}
71+
{guest.first_name} {guest.last_name}
7272
</p>
7373
<p className="truncate text-[1vw] text-black">
74-
{guest.preferredName}
74+
{guest.preferred_name}
7575
</p>
76-
<p className="text-[1vw] text-black">{guest.groupSize}</p>
76+
<p className="text-[1vw] text-black">{guest.group_size ?? "—"}</p>
7777
<p className="text-[1vw] text-black">{guest.floor}</p>
78-
<p className="text-[1vw] text-black">{guest.room}</p>
78+
<p className="text-[1vw] text-black">{guest.room_number}</p>
7979
</button>
8080
))}
8181
{guests.length === 0 && (

clients/web/src/components/guests/GuestSpecialNeedsCard.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
import type { GuestProfile } from "./guest-mocks";
1+
type SpecialNeeds = {
2+
dietaryRestrictions: string;
3+
accessibilityNeeds: string;
4+
sensorySensitivities: string;
5+
medicalConditions: string;
6+
};
27

38
type GuestSpecialNeedsCardProps = {
4-
specialNeeds: GuestProfile["specialNeeds"];
9+
specialNeeds: SpecialNeeds;
510
};
611

712
function SpecialNeedsRow({ label, value }: { label: string; value: string }) {

clients/web/src/components/guests/HousekeepingPreferencesCard.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
import type { GuestProfile } from "./guest-mocks";
1+
type HousekeepingPreferences = {
2+
frequency: string;
3+
doNotDisturb: string;
4+
};
25

36
type HousekeepingPreferencesCardProps = {
4-
housekeeping: GuestProfile["housekeeping"];
7+
housekeeping: HousekeepingPreferences;
58
};
69

710
function PreferenceRow({ label, value }: { label: string; value: string }) {

0 commit comments

Comments
 (0)