source: petify-frontend/src/api/reviews.ts@ f6ed6e4

Last change on this file since f6ed6e4 was f6ed6e4, checked in by veronika-ils <ilioskaveronika@…>, 14 hours ago

feat: The app is consistent with the changes made in phase 1 and phase 2

  • Property mode set to 100644
File size: 5.2 KB
Line 
1function getBaseUrl(): string {
2 const base = (import.meta.env.VITE_API_BASE_URL as string | undefined) ?? ''
3 return base.replace(/\/$/, '')
4}
5
6function joinUrl(base: string, path: string): string {
7 if (!base) return path
8 return `${base}${path.startsWith('/') ? '' : '/'}${path}`
9}
10
11export interface Review {
12 reviewId: number
13 reviewerId: number
14 reviewerName: string
15 reviewerUsername: string
16 rating: number
17 comment: string
18 createdAt: string
19 updatedAt?: string
20}
21
22export type UserReviewInteractionType =
23 | 'EVENT'
24 | 'PERSONAL_INTERACTION'
25 | 'ONLINE'
26 | 'PHONE_CALL'
27 | 'OTHER'
28
29export async function createReview(
30 targetUserId: number,
31 userId: number,
32 rating: number,
33 comment: string,
34 interactionType: UserReviewInteractionType
35): Promise<Review> {
36 const url = joinUrl(getBaseUrl(), `/api/reviews/${targetUserId}`)
37 const response = await fetch(url, {
38 method: 'POST',
39 headers: {
40 'Content-Type': 'application/json',
41 'X-User-Id': String(userId),
42 },
43 body: JSON.stringify({
44 rating,
45 comment,
46 interactionType,
47 }),
48 })
49
50 if (!response.ok) {
51 const error = await response.json()
52 throw new Error(error.error || 'Failed to create review')
53 }
54
55 return await response.json()
56}
57
58export async function getReviewsByOwner(targetUserId: number): Promise<Review[]> {
59 const url = joinUrl(getBaseUrl(), `/api/reviews/${targetUserId}`)
60 const response = await fetch(url, {
61 method: 'GET',
62 headers: {
63 'Content-Type': 'application/json',
64 },
65 })
66
67 if (!response.ok) {
68 const text = await response.text()
69 throw new Error(`Failed to fetch reviews: ${response.status} ${response.statusText}. ${text.slice(0, 160)}`)
70 }
71
72 return await readJsonResponse<Review[]>(response, 'reviews')
73}
74
75export async function getReviewsLeftByUser(reviewerId: number): Promise<Review[]> {
76 const url = joinUrl(getBaseUrl(), `/api/reviews/by/${reviewerId}`)
77 const response = await fetch(url, {
78 method: 'GET',
79 headers: {
80 'Content-Type': 'application/json',
81 },
82 })
83
84 if (!response.ok) {
85 const text = await response.text()
86 throw new Error(`Failed to fetch reviews left by user: ${response.status} ${response.statusText}. ${text.slice(0, 160)}`)
87 }
88
89 return await readJsonResponse<Review[]>(response, 'reviews left by user')
90}
91
92export async function getReviewsByClinic(clinicId: number): Promise<Review[]> {
93 const url = joinUrl(getBaseUrl(), `/api/reviews/clinics/${clinicId}`)
94 const response = await fetch(url, {
95 method: 'GET',
96 headers: {
97 'Content-Type': 'application/json',
98 },
99 })
100
101 if (!response.ok) {
102 throw new Error('Failed to fetch clinic reviews')
103 }
104
105 return await response.json()
106}
107
108export async function createClinicReview(
109 clinicId: number,
110 userId: number,
111 rating: number,
112 comment: string
113): Promise<Review> {
114 const url = joinUrl(getBaseUrl(), `/api/reviews/clinics/${clinicId}`)
115 const response = await fetch(url, {
116 method: 'POST',
117 headers: {
118 'Content-Type': 'application/json',
119 'X-User-Id': String(userId),
120 },
121 body: JSON.stringify({
122 rating,
123 comment,
124 }),
125 })
126
127 if (!response.ok) {
128 const error = await response.json()
129 throw new Error(error.error || 'Failed to create clinic review')
130 }
131
132 return await response.json()
133}
134
135export async function getMyClinicReview(clinicId: number, userId: number): Promise<Review | null> {
136 const url = joinUrl(getBaseUrl(), `/api/reviews/clinics/${clinicId}/mine`)
137 const response = await fetch(url, {
138 method: 'GET',
139 headers: {
140 'Content-Type': 'application/json',
141 'X-User-Id': String(userId),
142 },
143 })
144
145 if (response.status === 204) {
146 return null
147 }
148
149 if (!response.ok) {
150 const error = await response.json()
151 throw new Error(error.error || 'Failed to fetch clinic review')
152 }
153
154 return await response.json()
155}
156
157export async function updateReview(
158 reviewId: number,
159 userId: number,
160 rating: number,
161 comment: string
162): Promise<Review> {
163 const url = joinUrl(getBaseUrl(), `/api/reviews/${reviewId}`)
164 const response = await fetch(url, {
165 method: 'PUT',
166 headers: {
167 'Content-Type': 'application/json',
168 'X-User-Id': String(userId),
169 },
170 body: JSON.stringify({
171 rating,
172 comment,
173 }),
174 })
175
176 if (!response.ok) {
177 const error = await response.json()
178 throw new Error(error.error || 'Failed to update review')
179 }
180
181 return await response.json()
182}
183
184export async function deleteReview(reviewId: number, userId: number): Promise<void> {
185 const url = joinUrl(getBaseUrl(), `/api/reviews/${reviewId}`)
186 const response = await fetch(url, {
187 method: 'DELETE',
188 headers: {
189 'Content-Type': 'application/json',
190 'X-User-Id': String(userId),
191 },
192 })
193
194 if (!response.ok) {
195 const error = await response.json()
196 throw new Error(error.error || 'Failed to delete review')
197 }
198}
199
200async function readJsonResponse<T>(response: Response, label: string): Promise<T> {
201 const contentType = response.headers.get('content-type') || ''
202 const text = await response.text()
203
204 if (!contentType.includes('application/json')) {
205 throw new Error(`Expected JSON for ${label}, but backend returned non-JSON. ${text.slice(0, 160)}`)
206 }
207
208 return JSON.parse(text) as T
209}
Note: See TracBrowser for help on using the repository browser.