feat: auto-select sample when scanning sample number
- Add support for scanning sample numbers (8 digits) in addition to access numbers (10 digits) - Backend: Detect input type based on length, extract sample code and access suffix - Frontend: Auto-select matching sample and highlight with primary ring border - When sample number scanned (e.g., 10135026), extracts sample code (101) and auto-checks it
This commit is contained in:
parent
2b1cccd2be
commit
e5eac13036
@ -125,3 +125,8 @@ language_backend:
|
|||||||
# list of regex patterns which, when matched, mark a memory entry as read‑only.
|
# list of regex patterns which, when matched, mark a memory entry as read‑only.
|
||||||
# Extends the list from the global configuration, merging the two lists.
|
# Extends the list from the global configuration, merging the two lists.
|
||||||
read_only_memory_patterns: []
|
read_only_memory_patterns: []
|
||||||
|
|
||||||
|
# line ending convention to use when writing source files.
|
||||||
|
# Possible values: unset (use global setting), "lf", "crlf", or "native" (platform default)
|
||||||
|
# This does not affect Serena's own files (e.g. memories and configuration files), which always use native line endings.
|
||||||
|
line_ending:
|
||||||
|
|||||||
@ -9,11 +9,32 @@ class SamplesController extends BaseController
|
|||||||
{
|
{
|
||||||
use ResponseTrait;
|
use ResponseTrait;
|
||||||
|
|
||||||
public function show($accessnumber)
|
public function show($input)
|
||||||
{
|
{
|
||||||
$db = \Config\Database::connect();
|
$db = \Config\Database::connect();
|
||||||
|
|
||||||
$sql = "SELECT right(p.PATNUMBER,16) as [patnumber], ISNULL(p.FIRSTNAME,'') + ' ' + ISNULL(p.NAME,'') as [Name],
|
$scannedSampleCode = '';
|
||||||
|
|
||||||
|
if (strlen($input) == 10) {
|
||||||
|
$accessnumber = $input;
|
||||||
|
} else {
|
||||||
|
$redacc = substr($input, 3, 5);
|
||||||
|
$scannedSampleCode = substr($input, 0, 3);
|
||||||
|
|
||||||
|
$sql = "SELECT TOP 1 SPR.SP_ACCESSNUMBER
|
||||||
|
FROM SP_REQUESTS SPR
|
||||||
|
WHERE SPR.SP_ACCESSNUMBER LIKE '%$redacc' AND YEAR(SPR.REQDATE) = YEAR(GETDATE())
|
||||||
|
ORDER BY SPR.REQDATE DESC";
|
||||||
|
$query = $db->query($sql);
|
||||||
|
$row = $query->getRowArray();
|
||||||
|
$accessnumber = $row['SP_ACCESSNUMBER'] ?? null;
|
||||||
|
|
||||||
|
if (!$accessnumber) {
|
||||||
|
return $this->response->setJSON(['data' => null]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = "SELECT right(p.PATNUMBER,16) as [patnumber], ISNULL(p.FIRSTNAME,'') + ' ' + ISNULL(p.NAME,'') as [Name],
|
||||||
case when format(p.BIRTHDATE,'MMdd')=format(spr.COLLECTIONDATE,'MMdd') then DATEDIFF(YEAR,p.BIRTHDATE, spr.COLLECTIONDATE)
|
case when format(p.BIRTHDATE,'MMdd')=format(spr.COLLECTIONDATE,'MMdd') then DATEDIFF(YEAR,p.BIRTHDATE, spr.COLLECTIONDATE)
|
||||||
else FLOOR(DATEDIFF(DAY, p.BIRTHDATE, spr.COLLECTIONDATE) / 365.25) end ,
|
else FLOOR(DATEDIFF(DAY, p.BIRTHDATE, spr.COLLECTIONDATE) / 365.25) end ,
|
||||||
[Gender] = case
|
[Gender] = case
|
||||||
@ -38,6 +59,7 @@ class SamplesController extends BaseController
|
|||||||
'ktp' => $results['DMG_CKTPNO'] ?? '',
|
'ktp' => $results['DMG_CKTPNO'] ?? '',
|
||||||
'comment' => $results['COMMENTTEXT'] ?? '',
|
'comment' => $results['COMMENTTEXT'] ?? '',
|
||||||
'accessnumber' => $accessnumber,
|
'accessnumber' => $accessnumber,
|
||||||
|
'scannedSampleCode' => $scannedSampleCode,
|
||||||
];
|
];
|
||||||
|
|
||||||
$samples = [];
|
$samples = [];
|
||||||
|
|||||||
@ -100,7 +100,10 @@ $roleConfig = $config['phlebo'];
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<template x-for="sample in samples" :key="sample.sampcode">
|
<template x-for="sample in samples" :key="sample.sampcode">
|
||||||
<tr :class="sample.selected ? (sample.colstatus == 1 ? 'bg-success/10' : 'bg-warning/10') : ''">
|
<tr :class="[
|
||||||
|
sample.selected ? (sample.colstatus == 1 ? 'bg-success/10' : 'bg-warning/10') : '',
|
||||||
|
isScannedSample(sample) ? 'ring-2 ring-primary ring-inset' : ''
|
||||||
|
]">
|
||||||
<td class="text-center p-2">
|
<td class="text-center p-2">
|
||||||
<input type="checkbox"
|
<input type="checkbox"
|
||||||
class="checkbox checkbox-xs checkbox-primary"
|
class="checkbox checkbox-xs checkbox-primary"
|
||||||
@ -173,6 +176,7 @@ $roleConfig = $config['phlebo'];
|
|||||||
isLoading: false,
|
isLoading: false,
|
||||||
isSaving: false,
|
isSaving: false,
|
||||||
searched: false,
|
searched: false,
|
||||||
|
scannedSampleCode: '',
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
@ -203,10 +207,11 @@ $roleConfig = $config['phlebo'];
|
|||||||
comment: data.data.comment || ''
|
comment: data.data.comment || ''
|
||||||
};
|
};
|
||||||
this.comment = data.data.comment || '';
|
this.comment = data.data.comment || '';
|
||||||
|
this.scannedSampleCode = data.data.scannedSampleCode || '';
|
||||||
|
|
||||||
this.samples = (data.data.samples || []).map(s => ({
|
this.samples = (data.data.samples || []).map(s => ({
|
||||||
...s,
|
...s,
|
||||||
selected: s.colstatus == 1
|
selected: s.colstatus == 1 || (this.scannedSampleCode && s.sampcode === this.scannedSampleCode)
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
this.patient = {};
|
this.patient = {};
|
||||||
@ -224,6 +229,10 @@ $roleConfig = $config['phlebo'];
|
|||||||
return this.samples.some(s => s.selected && s.colstatus != 1);
|
return this.samples.some(s => s.selected && s.colstatus != 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
isScannedSample(sample) {
|
||||||
|
return this.scannedSampleCode && sample.sampcode === this.scannedSampleCode;
|
||||||
|
},
|
||||||
|
|
||||||
hasChanges() {
|
hasChanges() {
|
||||||
const toCollect = this.samples.some(s => s.selected && s.colstatus != 1);
|
const toCollect = this.samples.some(s => s.selected && s.colstatus != 1);
|
||||||
const toUncollect = this.samples.some(s => !s.selected && s.colstatus == 1);
|
const toUncollect = this.samples.some(s => !s.selected && s.colstatus == 1);
|
||||||
@ -294,10 +303,7 @@ $roleConfig = $config['phlebo'];
|
|||||||
|
|
||||||
const totalChanged = samplesToCollect.length + samplesToUncollect.length;
|
const totalChanged = samplesToCollect.length + samplesToUncollect.length;
|
||||||
this.showToast(`Updated ${totalChanged} sample(s)`, 'success');
|
this.showToast(`Updated ${totalChanged} sample(s)`, 'success');
|
||||||
|
this.resetForm();
|
||||||
setTimeout(() => {
|
|
||||||
this.resetForm();
|
|
||||||
}, 1000);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
this.showToast('Save failed', 'error');
|
this.showToast('Save failed', 'error');
|
||||||
@ -322,14 +328,7 @@ $roleConfig = $config['phlebo'];
|
|||||||
},
|
},
|
||||||
|
|
||||||
resetForm() {
|
resetForm() {
|
||||||
this.accessnumber = '';
|
setTimeout(() => window.location.reload(), 1500);
|
||||||
this.patient = {};
|
|
||||||
this.samples = [];
|
|
||||||
this.comment = '';
|
|
||||||
this.searched = false;
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs.accessInput.focus();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showToast(message, type = 'success') {
|
showToast(message, type = 'success') {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user