api-v1/public/index.html

1109 lines
46 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BuySellService API Tester</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 15px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
padding: 30px;
}
h1 {
color: #333;
text-align: center;
margin-bottom: 10px;
font-size: 2.5em;
}
.subtitle {
text-align: center;
color: #666;
margin-bottom: 30px;
font-size: 1.1em;
}
.section {
margin-bottom: 40px;
padding: 25px;
background: #f8f9fa;
border-radius: 10px;
border-left: 4px solid #667eea;
}
.section h2 {
color: #667eea;
margin-bottom: 20px;
font-size: 1.8em;
}
.form-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
color: #333;
font-weight: 600;
}
input, textarea, select {
width: 100%;
padding: 10px;
border: 2px solid #ddd;
border-radius: 5px;
font-size: 14px;
transition: border-color 0.3s;
}
input:focus, textarea:focus, select:focus {
outline: none;
border-color: #667eea;
}
textarea {
resize: vertical;
min-height: 80px;
}
.btn {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 12px 25px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
font-weight: 600;
transition: transform 0.2s, box-shadow 0.2s;
margin-right: 10px;
margin-top: 10px;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.btn-secondary {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
}
.btn-success {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
}
.response {
margin-top: 20px;
padding: 15px;
background: #1e1e1e;
color: #d4d4d4;
border-radius: 5px;
font-family: 'Courier New', monospace;
font-size: 13px;
max-height: 400px;
overflow-y: auto;
white-space: pre-wrap;
word-wrap: break-word;
}
.response.success {
background: #1e3a1e;
color: #90ee90;
}
.response.error {
background: #3a1e1e;
color: #ff6b6b;
}
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15px;
}
@media (max-width: 768px) {
.grid {
grid-template-columns: 1fr;
}
}
.endpoint-info {
background: #e8f4f8;
padding: 10px;
border-radius: 5px;
margin-bottom: 15px;
font-size: 0.9em;
color: #555;
}
.endpoint-info strong {
color: #667eea;
}
</style>
</head>
<body>
<div class="container">
<h1>🐄 BuySellService API Tester</h1>
<p class="subtitle">Test your Livestock Marketplace API endpoints</p>
<!-- Users Section -->
<div class="section">
<h2>👤 Users API</h2>
<div class="endpoint-info">
<strong>Base URL:</strong> http://localhost:3200/users<br>
<strong>Note:</strong> Create users before creating listings or saved addresses.
</div>
<div class="grid">
<div>
<h3>Get All Users</h3>
<button class="btn" onclick="getUsers()">Get Users</button>
</div>
<div>
<h3>Get Single User</h3>
<div class="form-group">
<label>User ID (UUID):</label>
<input type="text" id="getUserId" placeholder="Enter user UUID">
</div>
<button class="btn" onclick="getUser()">Get User</button>
</div>
</div>
<h3>Create User</h3>
<div class="endpoint-info" style="background: #d1ecf1; border-left-color: #0c5460;">
<strong>💡 Quick Create:</strong> You can create a user with a specific UUID (like the one in your error) by providing the "id" field.
</div>
<div class="grid">
<div>
<div class="form-group">
<label>User ID (UUID) - Optional:</label>
<input type="text" id="createUserId" placeholder="Leave empty to auto-generate">
<small style="color: #666; font-size: 0.85em; display: block; margin-top: 5px;">
Use: aaf295cb-a19e-4179-a2df-31c0c64ea9f4 (from your error)
</small>
</div>
<div class="form-group">
<label>Name:</label>
<input type="text" id="createUserName" placeholder="John Doe" required>
</div>
<div class="form-group">
<label>Phone Number:</label>
<input type="text" id="createUserPhone" placeholder="+919876543210" required>
</div>
</div>
<div>
<div class="form-group">
<label>Avatar URL (Optional):</label>
<input type="text" id="createUserAvatar" placeholder="https://example.com/avatar.jpg">
</div>
<div class="form-group">
<label>Language (Optional):</label>
<input type="text" id="createUserLanguage" value="en" placeholder="en">
</div>
<div class="form-group">
<label>Country Code:</label>
<input type="text" id="createUserCountryCode" value="+91" placeholder="+91">
</div>
</div>
</div>
<button class="btn btn-success" onclick="createUser()">Create User</button>
<h3 style="margin-top: 20px;">Update User</h3>
<div class="form-group">
<label>User ID to Update:</label>
<input type="text" id="updateUserId" placeholder="Enter user UUID">
</div>
<div class="form-group">
<label>New Name:</label>
<input type="text" id="updateUserName" placeholder="Updated name">
</div>
<button class="btn btn-secondary" onclick="updateUser()">Update User</button>
<div id="usersResponse" class="response" style="display: none;"></div>
</div>
<!-- Listings Section -->
<div class="section">
<h2>📋 Listings API</h2>
<div class="endpoint-info">
<strong>Base URL:</strong> http://localhost:3200/listings<br>
<strong>Note:</strong> Species ID and Breed ID must be UUIDs (not integers). Use the dropdowns below or enter UUIDs manually.
</div>
<div class="grid" style="margin-bottom: 20px;">
<div>
<h3>Get Available Species</h3>
<button class="btn" onclick="loadSpeciesList()">Load Species</button>
<div id="speciesListResponse" class="response" style="display: none; margin-top: 10px;"></div>
</div>
<div>
<h3>Get Available Breeds</h3>
<div class="form-group">
<label>Filter by Species ID (optional):</label>
<input type="text" id="filterBreedsSpeciesId" placeholder="Enter species UUID">
</div>
<button class="btn" onclick="loadBreedsList()">Load Breeds</button>
<div id="breedsListResponse" class="response" style="display: none; margin-top: 10px;"></div>
</div>
</div>
<div class="grid">
<div>
<h3>Get All Listings</h3>
<div class="form-group">
<label>Status:</label>
<select id="listingStatus">
<option value="active">Active</option>
<option value="sold">Sold</option>
<option value="expired">Expired</option>
</select>
</div>
<button class="btn" onclick="getListings()">Get Listings</button>
</div>
<div>
<h3>Get Single Listing</h3>
<div class="form-group">
<label>Listing ID:</label>
<input type="text" id="listingId" placeholder="Enter listing UUID">
</div>
<button class="btn" onclick="getListing()">Get Listing</button>
</div>
</div>
<div class="grid">
<div>
<h3>Search Listings</h3>
<div class="form-group">
<label>Search Query:</label>
<input type="text" id="searchQuery" placeholder="e.g., cow, buffalo">
</div>
<button class="btn btn-success" onclick="searchListings()">Search</button>
</div>
<div>
<h3>Near Me Search</h3>
<div class="form-group">
<label>Latitude:</label>
<input type="number" id="nearLat" placeholder="18.5204" step="any">
</div>
<div class="form-group">
<label>Longitude:</label>
<input type="number" id="nearLng" placeholder="73.8567" step="any">
</div>
<button class="btn btn-success" onclick="nearMeSearch()">Find Nearby</button>
</div>
</div>
<h3>Create Listing</h3>
<div class="endpoint-info" style="background: #fff3cd; border-left-color: #ffc107;">
<strong>⚠️ Important:</strong> The Seller ID must be a valid UUID that exists in the users table.
If you get a foreign key error, the user doesn't exist. You need to create the user first or use an existing user UUID.
</div>
<div class="form-group">
<label>Seller ID (UUID):</label>
<input type="text" id="sellerId" placeholder="Enter seller UUID (must exist in users table)">
<small style="color: #666; font-size: 0.85em; display: block; margin-top: 5px;">
Example: aaf295cb-a19e-4179-a2df-31c0c64ea9f4
</small>
</div>
<div class="grid">
<div>
<div class="form-group">
<label>Title:</label>
<input type="text" id="listingTitle" placeholder="e.g., High-yield Gir cow">
</div>
<div class="form-group">
<label>Price:</label>
<input type="number" id="listingPrice" placeholder="55000">
</div>
<div class="form-group">
<label>Currency:</label>
<input type="text" id="listingCurrency" value="INR" placeholder="INR">
</div>
<div class="form-group">
<label>Listing Type:</label>
<select id="listingType">
<option value="sale">Sale</option>
<option value="stud_service">Stud Service</option>
<option value="adoption">Adoption</option>
</select>
</div>
</div>
<div>
<div class="form-group">
<label>Species:</label>
<select id="speciesId">
<option value="">Loading species...</option>
</select>
<small style="color: #666; font-size: 0.85em;">Or enter UUID manually below</small>
</div>
<div class="form-group">
<label>Species ID (UUID) - Manual Entry:</label>
<input type="text" id="speciesIdManual" placeholder="Enter UUID if not in dropdown">
</div>
<div class="form-group">
<label>Breed:</label>
<select id="breedId">
<option value="">Select species first</option>
</select>
<small style="color: #666; font-size: 0.85em;">Or enter UUID manually below</small>
</div>
<div class="form-group">
<label>Breed ID (UUID) - Manual Entry:</label>
<input type="text" id="breedIdManual" placeholder="Enter UUID if not in dropdown">
</div>
<div class="form-group">
<label>Sex:</label>
<select id="animalSex">
<option value="M">Male</option>
<option value="F">Female</option>
<option value="Neutered">Neutered</option>
</select>
</div>
<div class="form-group">
<label>Age (months):</label>
<input type="number" id="ageMonths" placeholder="36">
</div>
</div>
</div>
<button class="btn btn-success" onclick="createListing()">Create Listing</button>
<h3 style="margin-top: 20px;">Update Listing</h3>
<div class="form-group">
<label>Listing ID to Update:</label>
<input type="text" id="updateListingId" placeholder="Enter listing UUID">
</div>
<div class="form-group">
<label>New Title:</label>
<input type="text" id="updateTitle" placeholder="Updated title">
</div>
<div class="form-group">
<label>New Price:</label>
<input type="number" id="updatePrice" placeholder="New price">
</div>
<button class="btn btn-secondary" onclick="updateListing()">Update Listing</button>
<h3 style="margin-top: 20px;">Delete Listing</h3>
<div class="form-group">
<label>Listing ID to Delete:</label>
<input type="text" id="deleteListingId" placeholder="Enter listing UUID">
</div>
<button class="btn btn-secondary" onclick="deleteListing()">Delete Listing</button>
<div id="listingsResponse" class="response" style="display: none;"></div>
</div>
<!-- Locations Section -->
<div class="section">
<h2>📍 Locations API</h2>
<div class="endpoint-info">
<strong>Base URL:</strong> http://localhost:3200/locations
</div>
<div class="grid">
<div>
<h3>Get User Locations</h3>
<div class="form-group">
<label>User ID (UUID):</label>
<input type="text" id="locationUserId" placeholder="Enter user UUID">
</div>
<button class="btn" onclick="getUserLocations()">Get Locations</button>
</div>
<div>
<h3>Get Single Location</h3>
<div class="form-group">
<label>Location ID:</label>
<input type="text" id="singleLocationId" placeholder="Enter location UUID">
</div>
<button class="btn" onclick="getLocation()">Get Location</button>
</div>
</div>
<h3>Create Location</h3>
<div class="endpoint-info" style="background: #fff3cd; border-left-color: #ffc107;">
<strong> Note:</strong> User ID is optional for captured locations (is_saved_address = false),
but required and must exist in users table for saved addresses (is_saved_address = true).
</div>
<div class="grid">
<div>
<div class="form-group">
<label>User ID (UUID) - Optional:</label>
<input type="text" id="createLocationUserId" placeholder="Leave empty for captured locations">
<small style="color: #666; font-size: 0.85em; display: block; margin-top: 5px;">
Required only if "Is Saved Address" is Yes
</small>
</div>
<div class="form-group">
<label>Latitude:</label>
<input type="number" id="createLat" placeholder="18.5204" step="any">
</div>
<div class="form-group">
<label>Longitude:</label>
<input type="number" id="createLng" placeholder="73.8567" step="any">
</div>
<div class="form-group">
<label>Country:</label>
<input type="text" id="createCountry" value="India" placeholder="India">
</div>
<div class="form-group">
<label>State:</label>
<input type="text" id="createState" placeholder="Maharashtra">
</div>
</div>
<div>
<div class="form-group">
<label>District:</label>
<input type="text" id="createDistrict" placeholder="Pune">
</div>
<div class="form-group">
<label>City/Village:</label>
<input type="text" id="createCity" placeholder="Baramati">
</div>
<div class="form-group">
<label>Pincode:</label>
<input type="text" id="createPincode" placeholder="413102">
</div>
<div class="form-group">
<label>Location Type:</label>
<select id="createLocationType">
<option value="farm">Farm</option>
<option value="home">Home</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group">
<label>Is Saved Address:</label>
<select id="createIsSaved">
<option value="true">Yes</option>
<option value="false">No</option>
</select>
</div>
</div>
</div>
<button class="btn btn-success" onclick="createLocation()">Create Location</button>
<h3 style="margin-top: 20px;">Update Location</h3>
<div class="form-group">
<label>Location ID to Update:</label>
<input type="text" id="updateLocationId" placeholder="Enter location UUID">
</div>
<div class="form-group">
<label>New City/Village:</label>
<input type="text" id="updateCity" placeholder="Updated city">
</div>
<button class="btn btn-secondary" onclick="updateLocation()">Update Location</button>
<div id="locationsResponse" class="response" style="display: none;"></div>
</div>
<!-- Chat Section -->
<div class="section">
<h2>💬 Chat API</h2>
<div class="endpoint-info">
<strong>Base URL:</strong> http://localhost:3200/chat
</div>
<div class="grid">
<div>
<h3>Create/Get Conversation</h3>
<div class="form-group">
<label>Buyer ID (UUID):</label>
<input type="text" id="buyerId" placeholder="Enter buyer UUID">
</div>
<div class="form-group">
<label>Seller ID (UUID):</label>
<input type="text" id="sellerIdChat" placeholder="Enter seller UUID">
</div>
<button class="btn" onclick="createConversation()">Create/Get Conversation</button>
</div>
<div>
<h3>Get User Conversations</h3>
<div class="form-group">
<label>User ID (UUID):</label>
<input type="text" id="conversationUserId" placeholder="Enter user UUID">
</div>
<button class="btn" onclick="getUserConversations()">Get Conversations</button>
</div>
</div>
<div class="grid">
<div>
<h3>Get Messages</h3>
<div class="form-group">
<label>Conversation ID (UUID):</label>
<input type="text" id="conversationId" placeholder="Enter conversation UUID">
</div>
<button class="btn" onclick="getMessages()">Get Messages</button>
</div>
<div>
<h3>Send Message</h3>
<div class="form-group">
<label>Conversation ID:</label>
<input type="text" id="messageConversationId" placeholder="Enter conversation UUID">
</div>
<div class="form-group">
<label>Sender ID:</label>
<input type="text" id="senderId" placeholder="Enter sender UUID">
</div>
<div class="form-group">
<label>Receiver ID:</label>
<input type="text" id="receiverId" placeholder="Enter receiver UUID">
</div>
<div class="form-group">
<label>Message Content:</label>
<textarea id="messageContent" placeholder="Type your message..."></textarea>
</div>
<button class="btn btn-success" onclick="sendMessage()">Send Message</button>
</div>
</div>
<div id="chatResponse" class="response" style="display: none;"></div>
</div>
</div>
<script>
const API_BASE = 'http://localhost:3200';
// Load species and breeds on page load
let speciesList = [];
let breedsList = [];
async function loadSpecies() {
try {
const response = await fetch(`${API_BASE}/listings/species`);
speciesList = await response.json();
const select = document.getElementById('speciesId');
select.innerHTML = '<option value="">Select a species</option>';
speciesList.forEach(species => {
const option = document.createElement('option');
option.value = species.id;
option.textContent = species.name;
select.appendChild(option);
});
} catch (error) {
console.error('Error loading species:', error);
document.getElementById('speciesId').innerHTML = '<option value="">Error loading species</option>';
}
}
async function loadBreeds(speciesId) {
try {
const url = speciesId
? `${API_BASE}/listings/breeds?species_id=${speciesId}`
: `${API_BASE}/listings/breeds`;
const response = await fetch(url);
breedsList = await response.json();
const select = document.getElementById('breedId');
select.innerHTML = '<option value="">Select a breed</option>';
breedsList.forEach(breed => {
const option = document.createElement('option');
option.value = breed.id;
option.textContent = breed.name;
select.appendChild(option);
});
} catch (error) {
console.error('Error loading breeds:', error);
document.getElementById('breedId').innerHTML = '<option value="">Error loading breeds</option>';
}
}
// Load species on page load
window.addEventListener('DOMContentLoaded', () => {
loadSpecies();
// Load breeds when species is selected
document.getElementById('speciesId').addEventListener('change', (e) => {
const speciesId = e.target.value;
if (speciesId) {
loadBreeds(speciesId);
} else {
document.getElementById('breedId').innerHTML = '<option value="">Select species first</option>';
}
});
});
// Helper functions to display species and breeds
async function loadSpeciesList() {
try {
const response = await fetch(`${API_BASE}/listings/species`);
const data = await response.json();
showResponse('speciesListResponse', data, !response.ok);
} catch (error) {
showResponse('speciesListResponse', { error: error.message }, true);
}
}
async function loadBreedsList() {
try {
const speciesId = document.getElementById('filterBreedsSpeciesId').value;
const url = speciesId
? `${API_BASE}/listings/breeds?species_id=${speciesId}`
: `${API_BASE}/listings/breeds`;
const response = await fetch(url);
const data = await response.json();
showResponse('breedsListResponse', data, !response.ok);
} catch (error) {
showResponse('breedsListResponse', { error: error.message }, true);
}
}
function showResponse(elementId, data, isError = false) {
const element = document.getElementById(elementId);
element.style.display = 'block';
element.className = `response ${isError ? 'error' : 'success'}`;
element.textContent = JSON.stringify(data, null, 2);
}
// Listings API Functions
async function getListings() {
try {
const status = document.getElementById('listingStatus').value;
const response = await fetch(`${API_BASE}/listings?status=${status}`);
const data = await response.json();
showResponse('listingsResponse', data, !response.ok);
} catch (error) {
showResponse('listingsResponse', { error: error.message }, true);
}
}
async function getListing() {
try {
const id = document.getElementById('listingId').value;
if (!id) {
alert('Please enter a listing ID');
return;
}
const response = await fetch(`${API_BASE}/listings/${id}`);
const data = await response.json();
showResponse('listingsResponse', data, !response.ok);
} catch (error) {
showResponse('listingsResponse', { error: error.message }, true);
}
}
async function searchListings() {
try {
const q = document.getElementById('searchQuery').value;
if (!q) {
alert('Please enter a search query');
return;
}
const response = await fetch(`${API_BASE}/listings/search?q=${encodeURIComponent(q)}`);
const data = await response.json();
showResponse('listingsResponse', data, !response.ok);
} catch (error) {
showResponse('listingsResponse', { error: error.message }, true);
}
}
async function nearMeSearch() {
try {
const lat = document.getElementById('nearLat').value;
const lng = document.getElementById('nearLng').value;
if (!lat || !lng) {
alert('Please enter both latitude and longitude');
return;
}
const response = await fetch(`${API_BASE}/listings/near-me?lat=${lat}&lng=${lng}`);
const data = await response.json();
showResponse('listingsResponse', data, !response.ok);
} catch (error) {
showResponse('listingsResponse', { error: error.message }, true);
}
}
async function createListing() {
try {
// Get species_id - prefer dropdown, fallback to manual entry
const speciesId = document.getElementById('speciesId').value || document.getElementById('speciesIdManual').value;
// Get breed_id - prefer dropdown, fallback to manual entry (can be null)
const breedId = document.getElementById('breedId').value || document.getElementById('breedIdManual').value;
if (!speciesId) {
alert('Please select or enter a Species ID (UUID)');
return;
}
const listingData = {
seller_id: document.getElementById('sellerId').value,
title: document.getElementById('listingTitle').value,
price: parseFloat(document.getElementById('listingPrice').value),
currency: document.getElementById('listingCurrency').value,
is_negotiable: true,
listing_type: document.getElementById('listingType').value,
animal: {
species_id: speciesId, // UUID, not integer
breed_id: breedId || null, // UUID or null, not integer
sex: document.getElementById('animalSex').value,
age_months: parseInt(document.getElementById('ageMonths').value) || null,
purpose: 'dairy',
health_status: 'healthy',
vaccinated: true,
dewormed: true
}
};
const response = await fetch(`${API_BASE}/listings`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(listingData)
});
const data = await response.json();
if (!response.ok) {
let errorMsg = data.error || 'Unknown error';
if (errorMsg.includes('does not exist')) {
errorMsg += '\n\n💡 Tip: Make sure the Seller ID is a valid UUID that exists in the users table. You may need to create the user first.';
}
showResponse('listingsResponse', { error: errorMsg }, true);
} else {
showResponse('listingsResponse', data, false);
}
} catch (error) {
showResponse('listingsResponse', {
error: `Network error: ${error.message}\n\n💡 Tip: Make sure the server is running and the Seller ID is a valid UUID.`
}, true);
}
}
async function updateListing() {
try {
const id = document.getElementById('updateListingId').value;
if (!id) {
alert('Please enter a listing ID');
return;
}
const updateData = {
title: document.getElementById('updateTitle').value,
price: parseFloat(document.getElementById('updatePrice').value)
};
const response = await fetch(`${API_BASE}/listings/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updateData)
});
const data = await response.json();
showResponse('listingsResponse', data, !response.ok);
} catch (error) {
showResponse('listingsResponse', { error: error.message }, true);
}
}
async function deleteListing() {
try {
const id = document.getElementById('deleteListingId').value;
if (!id) {
alert('Please enter a listing ID');
return;
}
const response = await fetch(`${API_BASE}/listings/${id}`, {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ deleted_reason: 'Test deletion' })
});
const data = await response.json();
showResponse('listingsResponse', data, !response.ok);
} catch (error) {
showResponse('listingsResponse', { error: error.message }, true);
}
}
// Locations API Functions
async function getUserLocations() {
try {
const userId = document.getElementById('locationUserId').value;
if (!userId) {
alert('Please enter a user ID');
return;
}
const response = await fetch(`${API_BASE}/locations/user/${userId}`);
const data = await response.json();
showResponse('locationsResponse', data, !response.ok);
} catch (error) {
showResponse('locationsResponse', { error: error.message }, true);
}
}
async function getLocation() {
try {
const id = document.getElementById('singleLocationId').value;
if (!id) {
alert('Please enter a location ID');
return;
}
const response = await fetch(`${API_BASE}/locations/${id}`);
const data = await response.json();
showResponse('locationsResponse', data, !response.ok);
} catch (error) {
showResponse('locationsResponse', { error: error.message }, true);
}
}
async function createLocation() {
try {
const locationData = {
user_id: document.getElementById('createLocationUserId').value || null,
lat: parseFloat(document.getElementById('createLat').value),
lng: parseFloat(document.getElementById('createLng').value),
country: document.getElementById('createCountry').value,
state: document.getElementById('createState').value,
district: document.getElementById('createDistrict').value,
city_village: document.getElementById('createCity').value,
pincode: document.getElementById('createPincode').value,
location_type: document.getElementById('createLocationType').value,
is_saved_address: document.getElementById('createIsSaved').value === 'true',
source_type: 'manual',
source_confidence: 'medium'
};
const response = await fetch(`${API_BASE}/locations`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(locationData)
});
const data = await response.json();
if (!response.ok) {
let errorMsg = data.error || 'Unknown error';
if (errorMsg.includes('does not exist')) {
errorMsg += '\n\n💡 Tip: If creating a saved address (is_saved_address = true), the User ID must exist in the users table. For captured locations, leave User ID empty.';
}
showResponse('locationsResponse', { error: errorMsg }, true);
} else {
showResponse('locationsResponse', data, false);
}
} catch (error) {
showResponse('locationsResponse', {
error: `Network error: ${error.message}\n\n💡 Tip: Make sure the server is running. If creating a saved address, ensure the User ID is a valid UUID that exists in the users table.`
}, true);
}
}
async function updateLocation() {
try {
const id = document.getElementById('updateLocationId').value;
if (!id) {
alert('Please enter a location ID');
return;
}
const updateData = {
city_village: document.getElementById('updateCity').value
};
const response = await fetch(`${API_BASE}/locations/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updateData)
});
const data = await response.json();
showResponse('locationsResponse', data, !response.ok);
} catch (error) {
showResponse('locationsResponse', { error: error.message }, true);
}
}
// Users API Functions
async function getUsers() {
try {
const response = await fetch(`${API_BASE}/users`);
const data = await response.json();
showResponse('usersResponse', data, !response.ok);
} catch (error) {
showResponse('usersResponse', { error: error.message }, true);
}
}
async function getUser() {
try {
const id = document.getElementById('getUserId').value;
if (!id) {
alert('Please enter a user ID');
return;
}
const response = await fetch(`${API_BASE}/users/${id}`);
const data = await response.json();
showResponse('usersResponse', data, !response.ok);
} catch (error) {
showResponse('usersResponse', { error: error.message }, true);
}
}
async function createUser() {
try {
const userData = {
name: document.getElementById('createUserName').value,
phone_number: document.getElementById('createUserPhone').value,
avatar_url: document.getElementById('createUserAvatar').value || null,
language: document.getElementById('createUserLanguage').value || null,
country_code: document.getElementById('createUserCountryCode').value || '+91'
};
// Add id if provided
const userId = document.getElementById('createUserId').value;
if (userId) {
userData.id = userId;
}
if (!userData.name || !userData.phone_number) {
alert('Name and Phone Number are required');
return;
}
const response = await fetch(`${API_BASE}/users`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
});
const data = await response.json();
if (!response.ok) {
let errorMsg = data.error || 'Unknown error';
if (errorMsg.includes('already exists')) {
errorMsg += '\n\n💡 Tip: A user with this phone number or ID already exists. Try a different phone number or ID.';
}
showResponse('usersResponse', { error: errorMsg }, true);
} else {
showResponse('usersResponse', data, false);
// Clear form on success
document.getElementById('createUserName').value = '';
document.getElementById('createUserPhone').value = '';
document.getElementById('createUserAvatar').value = '';
}
} catch (error) {
showResponse('usersResponse', {
error: `Network error: ${error.message}\n\n💡 Tip: Make sure the server is running.`
}, true);
}
}
async function updateUser() {
try {
const id = document.getElementById('updateUserId').value;
if (!id) {
alert('Please enter a user ID');
return;
}
const updateData = {
name: document.getElementById('updateUserName').value
};
const response = await fetch(`${API_BASE}/users/${id}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(updateData)
});
const data = await response.json();
showResponse('usersResponse', data, !response.ok);
} catch (error) {
showResponse('usersResponse', { error: error.message }, true);
}
}
// Chat API Functions
async function createConversation() {
try {
const buyerId = document.getElementById('buyerId').value;
const sellerId = document.getElementById('sellerIdChat').value;
if (!buyerId || !sellerId) {
alert('Please enter both buyer and seller IDs');
return;
}
const response = await fetch(`${API_BASE}/chat/conversations`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ buyer_id: buyerId, seller_id: sellerId })
});
const data = await response.json();
showResponse('chatResponse', data, !response.ok);
} catch (error) {
showResponse('chatResponse', { error: error.message }, true);
}
}
async function getUserConversations() {
try {
const userId = document.getElementById('conversationUserId').value;
if (!userId) {
alert('Please enter a user ID');
return;
}
const response = await fetch(`${API_BASE}/chat/conversations/user/${userId}`);
const data = await response.json();
showResponse('chatResponse', data, !response.ok);
} catch (error) {
showResponse('chatResponse', { error: error.message }, true);
}
}
async function getMessages() {
try {
const conversationId = document.getElementById('conversationId').value;
if (!conversationId) {
alert('Please enter a conversation ID');
return;
}
const response = await fetch(`${API_BASE}/chat/conversations/${conversationId}/messages`);
const data = await response.json();
showResponse('chatResponse', data, !response.ok);
} catch (error) {
showResponse('chatResponse', { error: error.message }, true);
}
}
async function sendMessage() {
try {
const messageData = {
conversation_id: document.getElementById('messageConversationId').value,
sender_id: document.getElementById('senderId').value,
receiver_id: document.getElementById('receiverId').value,
content: document.getElementById('messageContent').value,
message_type: 'text'
};
const response = await fetch(`${API_BASE}/chat/messages`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(messageData)
});
const data = await response.json();
showResponse('chatResponse', data, !response.ok);
} catch (error) {
showResponse('chatResponse', { error: error.message }, true);
}
}
</script>
</body>
</html>