278 lines
7.3 KiB
Markdown
278 lines
7.3 KiB
Markdown
|
|
# Client Name Check API Documentation
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
API endpoint untuk mengecek apakah nama client sudah ada atau belum dalam sistem. Endpoint ini mengembalikan status exist/not exist dengan pesan yang sesuai.
|
||
|
|
|
||
|
|
## Endpoint
|
||
|
|
|
||
|
|
### Check Client Name Exists
|
||
|
|
**GET** `/clients/check-name/{name}`
|
||
|
|
|
||
|
|
#### Description
|
||
|
|
Mengecek apakah nama client sudah ada dalam sistem atau belum.
|
||
|
|
|
||
|
|
#### Parameters
|
||
|
|
- **name** (path, required): Nama client yang akan dicek keberadaannya
|
||
|
|
|
||
|
|
#### Headers
|
||
|
|
- Tidak memerlukan authentication (public endpoint)
|
||
|
|
|
||
|
|
#### Response
|
||
|
|
|
||
|
|
##### Success Response (200) - Name Available
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": true,
|
||
|
|
"messages": ["Client name is available"],
|
||
|
|
"data": {
|
||
|
|
"name": "My Company",
|
||
|
|
"exists": false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
##### Success Response (200) - Name Already Used
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": true,
|
||
|
|
"messages": ["Name has been used"],
|
||
|
|
"data": {
|
||
|
|
"name": "My Company",
|
||
|
|
"exists": true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
##### Response Fields
|
||
|
|
- **name** (string): Nama client yang dicek
|
||
|
|
- **exists** (boolean): Status apakah nama sudah ada (`true`) atau belum (`false`)
|
||
|
|
|
||
|
|
#### Error Responses
|
||
|
|
|
||
|
|
##### 500 Internal Server Error
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"success": false,
|
||
|
|
"messages": ["Database error message"]
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage Examples
|
||
|
|
|
||
|
|
### cURL Example
|
||
|
|
```bash
|
||
|
|
# Check if client name exists
|
||
|
|
curl -X GET "http://localhost:8080/clients/check-name/My%20Company"
|
||
|
|
|
||
|
|
# Response if name exists
|
||
|
|
{
|
||
|
|
"success": true,
|
||
|
|
"messages": ["Name has been used"],
|
||
|
|
"data": {
|
||
|
|
"name": "My Company",
|
||
|
|
"exists": true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
# Response if name doesn't exist
|
||
|
|
{
|
||
|
|
"success": true,
|
||
|
|
"messages": ["Client name is available"],
|
||
|
|
"data": {
|
||
|
|
"name": "My Company",
|
||
|
|
"exists": false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### JavaScript Example
|
||
|
|
```javascript
|
||
|
|
const checkClientNameExists = async (name) => {
|
||
|
|
try {
|
||
|
|
const response = await fetch(`/clients/check-name/${encodeURIComponent(name)}`, {
|
||
|
|
method: 'GET',
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json'
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
const data = await response.json();
|
||
|
|
|
||
|
|
if (data.success) {
|
||
|
|
return {
|
||
|
|
exists: data.data.exists,
|
||
|
|
message: data.messages[0]
|
||
|
|
};
|
||
|
|
} else {
|
||
|
|
console.error('Check failed:', data.messages);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
console.error('Error checking client name:', error);
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// Usage
|
||
|
|
const result = await checkClientNameExists('My Company');
|
||
|
|
if (result) {
|
||
|
|
if (result.exists) {
|
||
|
|
console.log('Name is already used:', result.message);
|
||
|
|
} else {
|
||
|
|
console.log('Name is available:', result.message);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### React Hook Example
|
||
|
|
```javascript
|
||
|
|
import { useState, useEffect } from 'react';
|
||
|
|
|
||
|
|
const useClientNameCheck = (name) => {
|
||
|
|
const [exists, setExists] = useState(null);
|
||
|
|
const [message, setMessage] = useState('');
|
||
|
|
const [loading, setLoading] = useState(false);
|
||
|
|
const [error, setError] = useState(null);
|
||
|
|
|
||
|
|
useEffect(() => {
|
||
|
|
const checkName = async () => {
|
||
|
|
if (!name || name.length < 2) {
|
||
|
|
setExists(null);
|
||
|
|
setMessage('');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
setLoading(true);
|
||
|
|
setError(null);
|
||
|
|
|
||
|
|
const response = await fetch(`/clients/check-name/${encodeURIComponent(name)}`);
|
||
|
|
const data = await response.json();
|
||
|
|
|
||
|
|
if (data.success) {
|
||
|
|
setExists(data.data.exists);
|
||
|
|
setMessage(data.messages[0]);
|
||
|
|
} else {
|
||
|
|
setError(data.messages[0]);
|
||
|
|
}
|
||
|
|
} catch (err) {
|
||
|
|
setError('Failed to check client name');
|
||
|
|
} finally {
|
||
|
|
setLoading(false);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// Debounce the check
|
||
|
|
const timeoutId = setTimeout(checkName, 500);
|
||
|
|
return () => clearTimeout(timeoutId);
|
||
|
|
}, [name]);
|
||
|
|
|
||
|
|
return { exists, message, loading, error };
|
||
|
|
};
|
||
|
|
|
||
|
|
// Usage in component
|
||
|
|
const ClientNameInput = () => {
|
||
|
|
const [name, setName] = useState('');
|
||
|
|
const { exists, message, loading, error } = useClientNameCheck(name);
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
value={name}
|
||
|
|
onChange={(e) => setName(e.target.value)}
|
||
|
|
placeholder="Enter client name"
|
||
|
|
/>
|
||
|
|
|
||
|
|
{loading && <span>Checking...</span>}
|
||
|
|
{error && <span style={{color: 'red'}}>Error: {error}</span>}
|
||
|
|
{exists === true && <span style={{color: 'red'}}>{message}</span>}
|
||
|
|
{exists === false && <span style={{color: 'green'}}>{message}</span>}
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
### Form Validation Example
|
||
|
|
```javascript
|
||
|
|
const validateClientName = async (name) => {
|
||
|
|
if (!name || name.length < 2) {
|
||
|
|
return { valid: false, message: 'Client name must be at least 2 characters' };
|
||
|
|
}
|
||
|
|
|
||
|
|
if (name.length > 100) {
|
||
|
|
return { valid: false, message: 'Client name must be less than 100 characters' };
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
const response = await fetch(`/clients/check-name/${encodeURIComponent(name)}`);
|
||
|
|
const data = await response.json();
|
||
|
|
|
||
|
|
if (data.success) {
|
||
|
|
if (data.data.exists) {
|
||
|
|
return { valid: false, message: data.messages[0] };
|
||
|
|
} else {
|
||
|
|
return { valid: true, message: data.messages[0] };
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
return { valid: false, message: 'Unable to check client name availability' };
|
||
|
|
}
|
||
|
|
} catch (error) {
|
||
|
|
return { valid: false, message: 'Network error occurred' };
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// Usage in form submission
|
||
|
|
const handleSubmit = async (formData) => {
|
||
|
|
const nameValidation = await validateClientName(formData.name);
|
||
|
|
if (!nameValidation.valid) {
|
||
|
|
setError(nameValidation.message);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Proceed with form submission
|
||
|
|
submitForm(formData);
|
||
|
|
};
|
||
|
|
```
|
||
|
|
|
||
|
|
## Use Cases
|
||
|
|
1. **Client Registration**: Mengecek ketersediaan nama client saat registrasi
|
||
|
|
2. **Real-time Validation**: Validasi nama client secara real-time saat user mengetik
|
||
|
|
3. **Client Name Suggestion**: Memberikan saran nama client alternatif jika nama sudah ada
|
||
|
|
4. **Profile Update**: Mengecek nama client baru saat user ingin mengubah nama client
|
||
|
|
5. **Admin Panel**: Admin mengecek ketersediaan nama client untuk client baru
|
||
|
|
|
||
|
|
## Performance Considerations
|
||
|
|
- Endpoint ini tidak memerlukan authentication, sehingga lebih cepat
|
||
|
|
- Menggunakan query database yang efisien untuk pengecekan keberadaan
|
||
|
|
- Response yang minimal (hanya status exist/not exist) untuk performa optimal
|
||
|
|
- Cocok untuk real-time validation dengan debouncing
|
||
|
|
|
||
|
|
## Security Notes
|
||
|
|
- Endpoint ini bersifat public dan tidak memerlukan authentication
|
||
|
|
- Tidak mengembalikan data sensitif client
|
||
|
|
- Hanya mengembalikan status boolean exist/not exist
|
||
|
|
- Nama client di-validate untuk mencegah injection attacks
|
||
|
|
|
||
|
|
## Message Responses
|
||
|
|
|
||
|
|
| Status | Message | Description |
|
||
|
|
|--------|---------|-------------|
|
||
|
|
| `exists: false` | "Client name is available" | Nama client tersedia untuk digunakan |
|
||
|
|
| `exists: true` | "Name has been used" | Nama client sudah digunakan |
|
||
|
|
|
||
|
|
## Comparison with Other Endpoints
|
||
|
|
|
||
|
|
| Endpoint | Purpose | Authentication | Response |
|
||
|
|
|----------|---------|----------------|----------|
|
||
|
|
| `/clients/check-name/{name}` | Check client name exists | Not required | Boolean status only |
|
||
|
|
| `/clients/{id}` | Get client by ID | Required | Full client data |
|
||
|
|
| `/clients/profile` | Get current client profile | Required | Current client data |
|
||
|
|
|
||
|
|
## Notes
|
||
|
|
- Endpoint ini menggunakan method `FindByName` untuk pencarian berdasarkan nama
|
||
|
|
- Jika terjadi error database, akan mengembalikan error 500
|
||
|
|
- Nama client case-sensitive (mengikuti konvensi sistem)
|
||
|
|
- Cocok untuk digunakan dalam form validation dan real-time checking
|
||
|
|
- URL encoding diperlukan untuk nama yang mengandung spasi atau karakter khusus
|