Add error handling and new API methods for farm assistant features
- Introduced error messages in Persian for image analysis and chat functionalities in FarmAiAssistantChat and PlantPestDetection components. - Implemented a new postFormData method in ApiClient for handling file uploads. - Enhanced SmartFertilizationRecommendation and SmartIrrigationRecommendation components to fetch configuration data from the API, improving user experience with loading states and error handling. - Refactored components to utilize updated API services for better data management and responsiveness.
This commit is contained in:
@@ -123,6 +123,22 @@ export class ApiClient {
|
||||
return this.handleResponse<T>(response)
|
||||
}
|
||||
|
||||
/**
|
||||
* POST request with FormData (e.g. file upload). Does not set Content-Type so browser sets multipart/form-data.
|
||||
*/
|
||||
async postFormData<T>(endpoint: string, formData: FormData, customHeaders?: Record<string, string>): Promise<T> {
|
||||
const url = `${this.baseURL}${endpoint}`
|
||||
const headers = { ...this.getHeaders(customHeaders) }
|
||||
delete headers['Content-Type']
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: formData,
|
||||
})
|
||||
|
||||
return this.handleResponse<T>(response)
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT request
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* Farm AI Assistant API
|
||||
* GET context (farm bar data), POST chat (user message + optional farm_context/images).
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client'
|
||||
import type { FarmContext } from '@views/dashboards/farm/farmAiAssistant/farmAiAssistantTypes'
|
||||
|
||||
const PREFIX = '/api/farm-ai-assistant'
|
||||
|
||||
export interface FarmContextResponse {
|
||||
soilType: string
|
||||
waterEC: string
|
||||
selectedCrop: string
|
||||
growthStage: string
|
||||
lastIrrigationStatus: string
|
||||
}
|
||||
|
||||
export interface ChatSection {
|
||||
type: 'text' | 'list' | 'recommendation' | 'warning'
|
||||
title?: string
|
||||
content?: string
|
||||
items?: string[]
|
||||
icon?: 'droplet' | 'leaf' | 'warning' | 'fertilizer' | 'calendar'
|
||||
frequency?: string
|
||||
amount?: string
|
||||
timing?: string
|
||||
expandableExplanation?: string
|
||||
}
|
||||
|
||||
export interface ChatPayload {
|
||||
content: string
|
||||
farm_context?: FarmContext
|
||||
images?: string[]
|
||||
conversation_id?: string
|
||||
}
|
||||
|
||||
export interface ChatResponseData {
|
||||
message_id: string
|
||||
conversation_id: string
|
||||
content: string
|
||||
sections: ChatSection[]
|
||||
}
|
||||
|
||||
interface ApiResponse<T> {
|
||||
status: string
|
||||
data: T
|
||||
}
|
||||
|
||||
function unwrap<T>(res: ApiResponse<T>): T {
|
||||
return res.data
|
||||
}
|
||||
|
||||
export const farmAiAssistantService = {
|
||||
/**
|
||||
* Returns farm context for the context bar (soilType, waterEC, selectedCrop, growthStage, lastIrrigationStatus).
|
||||
*/
|
||||
getContext(): Promise<FarmContextResponse> {
|
||||
return apiClient
|
||||
.get<ApiResponse<FarmContextResponse>>(`${PREFIX}/context/`)
|
||||
.then(unwrap)
|
||||
},
|
||||
|
||||
/**
|
||||
* Send user message (and optional farm_context, images, conversation_id). Returns message with sections.
|
||||
*/
|
||||
chat(payload: ChatPayload): Promise<ChatResponseData> {
|
||||
return apiClient
|
||||
.post<ApiResponse<ChatResponseData>>(`${PREFIX}/chat/`, payload)
|
||||
.then(unwrap)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Fertilization Recommendation API
|
||||
* @see RECOMMENDATION_APIS.md
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client'
|
||||
|
||||
const PREFIX = '/api/fertilization-recommendation'
|
||||
|
||||
export interface FarmData {
|
||||
soilType: string
|
||||
organicMatter: string
|
||||
waterEC: string
|
||||
}
|
||||
|
||||
export interface GrowthStage {
|
||||
id: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
export interface CropOption {
|
||||
id: string
|
||||
labelKey: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
export interface FertilizationConfigResponse {
|
||||
farmData: FarmData
|
||||
growthStages: GrowthStage[]
|
||||
cropOptions: CropOption[]
|
||||
}
|
||||
|
||||
export interface FertilizationPlan {
|
||||
npkRatio: string
|
||||
amountPerHectare: string
|
||||
applicationMethod: string
|
||||
applicationInterval: string
|
||||
reasoning: string
|
||||
}
|
||||
|
||||
export interface FertilizationRecommendPayload {
|
||||
crop_id?: string
|
||||
growth_stage?: string
|
||||
soilType?: string
|
||||
organicMatter?: string
|
||||
waterEC?: string
|
||||
}
|
||||
|
||||
interface ApiResponse<T> {
|
||||
status: string
|
||||
data: T
|
||||
}
|
||||
|
||||
async function unwrap<T>(promise: Promise<ApiResponse<T>>): Promise<T> {
|
||||
const res = await promise
|
||||
return res.data
|
||||
}
|
||||
|
||||
export const fertilizationRecommendationService = {
|
||||
getConfig(): Promise<FertilizationConfigResponse> {
|
||||
return unwrap(apiClient.get<ApiResponse<FertilizationConfigResponse>>(`${PREFIX}/config/`))
|
||||
},
|
||||
|
||||
recommend(payload?: FertilizationRecommendPayload): Promise<{ plan: FertilizationPlan }> {
|
||||
return unwrap(apiClient.post<ApiResponse<{ plan: FertilizationPlan }>>(`${PREFIX}/recommend/`, payload ?? {}))
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Irrigation Recommendation API
|
||||
* @see RECOMMENDATION_APIS.md
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client'
|
||||
|
||||
const PREFIX = '/api/irrigation-recommendation'
|
||||
|
||||
export interface FarmInfo {
|
||||
soilType: string
|
||||
waterQuality: string
|
||||
climateZone: string
|
||||
}
|
||||
|
||||
export interface CropOption {
|
||||
id: string
|
||||
labelKey: string
|
||||
icon: string
|
||||
}
|
||||
|
||||
export interface IrrigationConfigResponse {
|
||||
farmInfo: FarmInfo
|
||||
cropOptions: CropOption[]
|
||||
}
|
||||
|
||||
export interface IrrigationPlan {
|
||||
frequencyPerWeek: number
|
||||
durationMinutes: number
|
||||
bestTimeOfDay: string
|
||||
moistureLevel: number
|
||||
warning?: string
|
||||
}
|
||||
|
||||
export interface IrrigationRecommendPayload {
|
||||
crop_id?: string
|
||||
soilType?: string
|
||||
waterQuality?: string
|
||||
climateZone?: string
|
||||
}
|
||||
|
||||
interface ApiResponse<T> {
|
||||
status: string
|
||||
data: T
|
||||
}
|
||||
|
||||
async function unwrap<T>(promise: Promise<ApiResponse<T>>): Promise<T> {
|
||||
const res = await promise
|
||||
return res.data
|
||||
}
|
||||
|
||||
export const irrigationRecommendationService = {
|
||||
getConfig(): Promise<IrrigationConfigResponse> {
|
||||
return unwrap(apiClient.get<ApiResponse<IrrigationConfigResponse>>(`${PREFIX}/config/`))
|
||||
},
|
||||
|
||||
recommend(payload?: IrrigationRecommendPayload): Promise<{ plan: IrrigationPlan }> {
|
||||
return unwrap(apiClient.post<ApiResponse<{ plan: IrrigationPlan }>>(`${PREFIX}/recommend/`, payload ?? {}))
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Pest Detection API
|
||||
* @see RECOMMENDATION_APIS.md
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client'
|
||||
|
||||
const PREFIX = '/api/pest-detection'
|
||||
|
||||
export interface PestAnalyzeResult {
|
||||
pest: string
|
||||
confidence: number
|
||||
description: string
|
||||
treatment: string
|
||||
}
|
||||
|
||||
interface ApiResponse<T> {
|
||||
status: string
|
||||
data: T
|
||||
}
|
||||
|
||||
async function unwrap<T>(promise: Promise<ApiResponse<T>>): Promise<T> {
|
||||
const res = await promise
|
||||
return res.data
|
||||
}
|
||||
|
||||
export const pestDetectionService = {
|
||||
/**
|
||||
* Analyze image (optional FormData with 'image' or 'file' key). Returns mock result if backend does not use image yet.
|
||||
*/
|
||||
analyze(formData?: FormData): Promise<PestAnalyzeResult> {
|
||||
if (formData) {
|
||||
return unwrap(apiClient.postFormData<ApiResponse<PestAnalyzeResult>>(`${PREFIX}/analyze/`, formData))
|
||||
}
|
||||
return unwrap(apiClient.post<ApiResponse<PestAnalyzeResult>>(`${PREFIX}/analyze/`, {}))
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user