Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sublet): add FE apis and interfaces #312

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions frontend/api/sublet/amenitiesApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// /api/amenitiesApi.ts

import { doApiRequest } from '@/utils/fetch'

const BASE_URL = 'api/sublet'

export const getAmenities = async (): Promise<string[]> => {
const response = await doApiRequest(`${BASE_URL}/listAmenities`)
if (!response.ok) {
console.error('Failed to fetch amenities')
return []
}
return response.json()
}
44 changes: 44 additions & 0 deletions frontend/api/sublet/offersApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// /api/offersApi.ts
import { CreateOfferRequest, OfferResponse } from '@/interfaces/sublet/Offer'
import { doApiRequest } from '@/utils/fetch'

const BASE_URL = 'api/sublet'

// Get all offers for a specific sublet
export const getOffers = async (subletId: string): Promise<OfferResponse[]> => {
const response = await doApiRequest(`${BASE_URL}/listOffers/${subletId}`)
if (!response.ok) {
console.error('Failed to fetch offers')
return []
}
return response.json()
}

// Create a new offer for a sublet
export const createOffer = async (
subletId: string,
data: CreateOfferRequest
): Promise<boolean> => {
const response = await doApiRequest(`${BASE_URL}/createOffer/${subletId}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!response.ok) {
console.error('Failed to create offer')
return false
}
return true
}

// Delete an offer by sublet ID (no request body required)
export const deleteOffer = async (subletId: string): Promise<boolean> => {
const response = await doApiRequest(`${BASE_URL}/destroyOffer/${subletId}`, {
method: 'DELETE',
})
if (!response.ok) {
console.error('Failed to delete offer')
return false
}
return true
}
109 changes: 109 additions & 0 deletions frontend/api/sublet/subletsApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// /api/subletsApi.ts
import {
CreateSubletImageRequest,
CreateSubletRequest,
Sublet,
SubletResponse,
UpdateSubletRequest,
} from '@/interfaces/sublet/Sublet'
import { doApiRequest } from '@/utils/fetch'

const BASE_URL = 'api/sublet'

export const getSublets = async (): Promise<SubletResponse[]> => {
const response = await doApiRequest(`${BASE_URL}/listSublets`)
if (!response.ok) {
console.error('Failed to fetch sublets')
return []
}
return response.json()
}

export const getSubletById = async (id: number): Promise<Sublet | null> => {
const response = await doApiRequest(
`${BASE_URL}/retrieveSubletSerializerRead/${id}`
)
if (!response.ok) {
console.error('Failed to fetch sublet')
return null
}
return response.json()
}

export const createSublet = async (
data: CreateSubletRequest
): Promise<SubletResponse | null> => {
const response = await doApiRequest(`${BASE_URL}/createSublet`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!response.ok) {
console.error('Failed to create sublet')
return null
}
return response.json()
}

export const updateSublet = async (
id: string,
data: UpdateSubletRequest
): Promise<SubletResponse | null> => {
const response = await doApiRequest(`${BASE_URL}/updateSublet/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (!response.ok) {
console.error('Failed to update sublet')
return null
}
return response.json()
}

export const deleteSublet = async (id: number): Promise<boolean> => {
const response = await doApiRequest(`${BASE_URL}/destroySublet/${id}`, {
method: 'DELETE',
})
if (!response.ok) {
console.error('Failed to delete sublet')
return false
}
return true
}

export const uploadSubletImage = async (
subletId: string,
data: CreateSubletImageRequest
): Promise<boolean> => {
const formData = new FormData()
formData.append('sublet', data.sublet.toString())
if (data.image) formData.append('image', data.image)

const response = await doApiRequest(
`${BASE_URL}/createSubletImage/${subletId}`,
{
method: 'POST',
body: formData,
}
)
if (!response.ok) {
console.error('Failed to upload sublet image')
return false
}
return true
}

export const deleteSubletImage = async (imageId: number): Promise<boolean> => {
const response = await doApiRequest(
`${BASE_URL}/destroySubletImage/${imageId}`,
{
method: 'DELETE',
}
)
if (!response.ok) {
console.error('Failed to delete sublet image')
return false
}
return true
}
18 changes: 18 additions & 0 deletions frontend/interfaces/sublet/Offer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// /interfaces/CreateOfferRequest.ts
export interface CreateOfferRequest {
phone_number: string // Required phone number
email?: string | null // Optional email, max length 255 characters
message: string // Message, max length 255 characters
sublet: number // Sublet ID
}

// /interfaces/OfferResponse.ts
export interface OfferResponse {
id: number // Offer ID
phone_number: string // Phone number of the user making the offer
email?: string | null // Optional email
message: string // Message content
created_date: string // ISO datetime string
user: string // User ID or name
sublet: number // Sublet ID associated with the offer
}
74 changes: 74 additions & 0 deletions frontend/interfaces/sublet/Sublet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// SubletListing.ts

export interface Sublet {
id: number
subletter: string // Name or ID of the subletter
amenities: string[] // Array of amenities as strings
title: string // Required, max length 255 characters
address?: string | null // Optional, max length 255 characters
beds?: number | null // Optional, integer
baths?: string | null // Optional, can be a decimal, e.g., "1.5"
description?: string | null // Optional description
external_link?: string | null // Optional external URL, must match a valid URL pattern
price: number // Required, integer value
negotiable: boolean // Indicates if the price is negotiable
start_date: string // Required, ISO 8601 date string
end_date: string // Required, ISO 8601 date string
expires_at: string // Required, ISO 8601 datetime string
}

// /interfaces/SubletResponse.ts
export interface SubletResponse {
id: number
subletter: string // Subletter’s name or ID
amenities: string[] // List of amenities
title: string
address?: string | null // Optional or nullable
beds?: number | null // Optional number of beds
baths?: string | null // Optional, can be a decimal
description?: string | null // Optional description
external_link?: string | null // Optional external URL
price: number
negotiable: boolean // Is price negotiable?
start_date: string // ISO date string
end_date: string // ISO date string
expires_at: string // ISO datetime string
}

// /interfaces/CreateSubletRequest.ts
export interface CreateSubletRequest {
amenities: string[]
title: string
address?: string | null
beds?: number | null
baths?: string | null
description?: string | null
external_link?: string | null
price: number
negotiable: boolean
start_date: string
end_date: string
expires_at: string
}

// /interfaces/UpdateSubletRequest.ts
export interface UpdateSubletRequest {
amenities: string[]
title: string
address?: string | null
beds?: number | null
baths?: string | null
description?: string | null
external_link?: string | null
price: number
negotiable: boolean
start_date: string
end_date: string
expires_at: string
}

// /interfaces/CreateSubletImageRequest.ts
export interface CreateSubletImageRequest {
sublet: number // Sublet ID
image: File | null // Binary image file
}
Loading