Overview
Sample management actions handle oil sample CRUD operations, analysis group analytics, and sample history tracking. All functions are located in src/app/actions/samples.ts.
Sample Operations
getSamplesService
Retrieves a paginated list of oil samples with optional filtering.
Query parameters for filtering and pagination Items per page (default: 10)
Search term for filtering samples
Filter by sampling point ID
Filter by laboratory name
Pagination metadata Whether there is a next page
Whether there is a previous page
Server Component
Filter by Asset
Filter by Lab and Site
Client Component
"use server" ;
import { getSamplesService } from "@/app/actions" ;
export default async function SamplesPage ({ searchParams }) {
const params = await searchParams ;
const page = parseInt ( String ( params ?. page ?? 1 ), 10 );
const limit = parseInt ( String ( params ?. limit ?? 10 ), 10 );
const { data : samples , meta } = await getSamplesService ({
page ,
limit
});
return < SampleTable data ={ samples } meta ={ meta } />;
}
This function throws on error, so wrap in try-catch when needed.
getSampleService
Retrieves a single sample by ID.
Complete sample object with wear metals, contaminants, particle counts, and viscosity levels
Basic Usage
With Error Handling
import { getSampleService } from "@/app/actions" ;
const sample = await getSampleService ( "sample-123" );
console . log ( sample . serial_number );
console . log ( sample . severity );
console . log ( sample . wear_metals );
console . log ( sample . contaminants );
addSampleService
Creates a new oil sample with analysis data.
Sample creation data Sample date as Unix timestamp
Oil in service hours/days
Filter change status (e.g., “Yes”, “No”)
Severity level (e.g., “Normal”, “Warning”, “Critical”)
Wear metal measurements (key: element, value: concentration)
Array of contaminant measurements Particle count measurements Particle size range (e.g., “>4μm”, “>6μm”)
Unit (e.g., “particles/mL”)
Viscosity measurements at different temperatures Unit (e.g., “cSt”, “mm²/s”)
additives
Record<string, string> | Additive[]
Additive measurements
Collection date (ISO string)
URL to lab report document
Standard API response object Whether the operation succeeded
Client Component
With Document Upload
"use client" ;
import { addSampleService } from "@/app/actions" ;
import { AddSamplePayload } from "@/schema" ;
import { toast } from "sonner" ;
export function AddSampleForm () {
const handleSubmit = async ( data : AddSamplePayload ) => {
const payload : AddSamplePayload = {
site: { id: data . site . id },
asset: { id: data . asset . id },
sampling_point: { id: data . sampling_point . id },
serial_number: data . serial_number ,
date_sampled: new Date ( data . date_sampled ). getTime (),
lab_name: data . lab_name ,
service_meter_reading: data . service_meter_reading ,
hrs: data . hrs ,
oil_in_service: data . oil_in_service ,
filter_changed: data . filter_changed ,
oil_drained: data . oil_drained ,
severity: data . severity ,
wear_metals: {
Iron: "25" ,
Copper: "12" ,
Chrome: "5" ,
},
contaminants: [
{ type: "Water" , value: 150 , unit: "ppm" },
{ type: "Fuel" , value: 2.5 , unit: "%" },
],
particle_counts: [
{ size_range: ">4μm" , count: 5000 , unit: "particles/mL" },
{ size_range: ">6μm" , count: 2500 , unit: "particles/mL" },
],
};
const response = await addSampleService ( payload );
if ( response . success ) {
toast . success ( "Sample added successfully" );
router . push ( "/samples" );
} else {
toast . error ( response . message || "Failed to add sample" );
}
};
return < form onSubmit ={ handleSubmit }> ...</ form > ;
}
editSampleService
Updates an existing sample.
payload
EditSamplePayload
required
Updated sample data (same structure as AddSamplePayload)
Standard API response object
import { editSampleService } from "@/app/actions" ;
import { toast } from "sonner" ;
const handleUpdate = async ( sampleId : string , data : EditSamplePayload ) => {
const response = await editSampleService ( sampleId , data );
if ( response . success ) {
toast . success ( "Sample updated successfully" );
} else {
toast . error ( response . message );
}
};
deleteSampleService
Deletes a sample.
Standard API response object
import { deleteSampleService } from "@/app/actions" ;
import { toast } from "sonner" ;
const handleDelete = async ( sampleId : string ) => {
const response = await deleteSampleService ( sampleId );
if ( response . success ) {
toast . success ( "Sample deleted successfully" );
} else {
toast . error ( response . message );
}
};
Analytics Operations
getSampleAnalysisGroupsAnalyticsService
Retrieves analytics for sample analysis groups (wear metals, contaminants, etc.).
Analysis category (e.g., “wear_metals”, “contaminants”, “particle_counts”)
Time period in days for trend analysis
Response with analytics data Whether the operation succeeded
Analytics data for the specified category
Basic Usage
Multiple Categories
import { getSampleAnalysisGroupsAnalyticsService } from "@/app/actions" ;
const response = await getSampleAnalysisGroupsAnalyticsService (
"wear_metals" ,
30
);
if ( response . success ) {
console . log ( "Wear metals trends:" , response . data );
}
Sample History Operations
getSamplingPointSampleHistoryService
Retrieves sample history for a specific sampling point with filtering and pagination.
Query parameters for filtering Start date for date range filter
End date for date range filter
Sample history response Whether the operation succeeded
Error message if applicable
Basic Usage
Date Range Filter
Server Component
import { getSamplingPointSampleHistoryService } from "@/app/actions" ;
const { success , data : samples , meta } =
await getSamplingPointSampleHistoryService ( "sampling-point-123" , {
page: 1 ,
limit: 20 ,
});
if ( success ) {
console . log ( `Found ${ meta . total } historical samples` );
}
This function returns a success flag instead of throwing, making it safe to use without try-catch.
Type Definitions
Import types from @/types and schemas from @/schema:
import {
Sample ,
WearMetal ,
Contaminant ,
ParticleCount ,
ViscosityLevel
} from "@/types" ;
import {
AddSamplePayload ,
EditSamplePayload ,
ADD_SAMPLE_SCHEMA
} from "@/schema" ;
import { ApiResponse } from "@/app/actions" ;
import {
SampleHistoryResponse ,
SampleHistoryMeta
} from "@/app/actions/samples" ;