Added Percent symbol in the Input which accepts Percent value.

Updated Doctor list
This commit is contained in:
Amey Bhagwat 2026-11-05 17:41:32 +05:30
parent 96ee4427f1
commit a49fa82703
4 changed files with 122 additions and 54 deletions

View File

@ -205,7 +205,7 @@ Sr NO,TASKFORCE,ZBM Name,RBM Name,ABM Name,HQ,TM ID,TM Name,HCP NAME,LEGACY_CODE
204,Respiratory 2,Shaikh Mohseen Ahmed,Prashant Gakkhar,SURAJ RAWAT,AJMER,162115,HIMANSHU GARG,Dr.PRAMOD DADHICH,CLX0013432,11743902,Chest Physician,A+,100028825,Dr.PRAMOD DADHICH,dadhichrashmi@gmail.com,9829083879
205,Respiratory 2,Shaikh Mohseen Ahmed,Prashant Gakkhar,SURAJ RAWAT,AJMER,162115,HIMANSHU GARG,DR NEERAJ GUPTA,CIR21066,10280704,Chest Physician,A+,100116917,DR NEERAJ GUPTA,drneerajajmer@yahoo.com,9829101942
206,Respiratory 2,Shaikh Mohseen Ahmed,Prashant Gakkhar,SURAJ RAWAT,S MADHOPUR,168610,VIPUL SHARMA,Dr.Umesh Kumar Jatav,CLX0384426,10255366,Chest Physician,A+,100075453,Dr.Umesh Kumar Jatav,jahaji28@gmail.com,9602158647
207,Respiratory 2,Shaikh Mohseen Ahmed,Prashant Gakkhar,SURAJ RAWAT,S MADHOPUR,168610,VIPUL SHARMA,Dr.Prem raj Singh,CIP610172,7659526,Chest Physician,A+,100037592,Dr.Prem raj Singh,drpremrajsingh@gmail.com,9929460655 &6350474968
207,Respiratory 2,Shaikh Mohseen Ahmed,Prashant Gakkhar,SURAJ RAWAT,S MADHOPUR,168610,VIPUL SHARMA,Dr.Prem raj Singh,CIP610172,7659526,Chest Physician,A+,100037592,Dr.Prem raj Singh,drpremrajsingh@gmail.com,9929460655
208,Respiratory 2,Amandeep sharma,Umesh garg,Abhinav Sharma,TM-Jalandhar 17089,150541,Ishant Setia,PUNEET SINGH PERHAR,CLX1239048,12632335,Chest Physician,A+,100041086,PUNEET SINGH PERHAR,puneetperhar@yahoo.com,9779149838
209,Respiratory 2,Amandeep sharma,Umesh garg,Abhinav Sharma,TM-AMRITSAR 7465,171383,Arun Kumar,Mandeep Singh,CLX1650772,11311299,Chest Physician,A+,100056055,Mandeep Singh,mandeepsingh27@gmail.com,9811660365
210,Respiratory 2,Amandeep sharma,Umesh garg,Abhinav Sharma,TM-AMRITSAR 23513,171358,Ankush Kapoor,naresh chawla,CIP1067150,15023224,Chest Physician,A,100087159,naresh chawla,dr.nareshchawla@gmail.com,9814104155

1 Sr NO TASKFORCE ZBM Name RBM Name ABM Name HQ TM ID TM Name HCP NAME LEGACY_CODE PCODE SPECIALITY CLASS VENDORCODE VENDORNAME Email ID Contact No
205 204 Respiratory 2 Shaikh Mohseen Ahmed Prashant Gakkhar SURAJ RAWAT AJMER 162115 HIMANSHU GARG Dr.PRAMOD DADHICH CLX0013432 11743902 Chest Physician A+ 100028825 Dr.PRAMOD DADHICH dadhichrashmi@gmail.com 9829083879
206 205 Respiratory 2 Shaikh Mohseen Ahmed Prashant Gakkhar SURAJ RAWAT AJMER 162115 HIMANSHU GARG DR NEERAJ GUPTA CIR21066 10280704 Chest Physician A+ 100116917 DR NEERAJ GUPTA drneerajajmer@yahoo.com 9829101942
207 206 Respiratory 2 Shaikh Mohseen Ahmed Prashant Gakkhar SURAJ RAWAT S MADHOPUR 168610 VIPUL SHARMA Dr.Umesh Kumar Jatav CLX0384426 10255366 Chest Physician A+ 100075453 Dr.Umesh Kumar Jatav jahaji28@gmail.com 9602158647
208 207 Respiratory 2 Shaikh Mohseen Ahmed Prashant Gakkhar SURAJ RAWAT S MADHOPUR 168610 VIPUL SHARMA Dr.Prem raj Singh CIP610172 7659526 Chest Physician A+ 100037592 Dr.Prem raj Singh drpremrajsingh@gmail.com 9929460655 &6350474968 9929460655
209 208 Respiratory 2 Amandeep sharma Umesh garg Abhinav Sharma TM-Jalandhar 17089 150541 Ishant Setia PUNEET SINGH PERHAR CLX1239048 12632335 Chest Physician A+ 100041086 PUNEET SINGH PERHAR puneetperhar@yahoo.com 9779149838
210 209 Respiratory 2 Amandeep sharma Umesh garg Abhinav Sharma TM-AMRITSAR 7465 171383 Arun Kumar Mandeep Singh CLX1650772 11311299 Chest Physician A+ 100056055 Mandeep Singh mandeepsingh27@gmail.com 9811660365
211 210 Respiratory 2 Amandeep sharma Umesh garg Abhinav Sharma TM-AMRITSAR 23513 171358 Ankush Kapoor naresh chawla CIP1067150 15023224 Chest Physician A 100087159 naresh chawla dr.nareshchawla@gmail.com 9814104155

View File

@ -729,6 +729,14 @@ a:focus-visible {
.survey-grid-input input {
flex: 1;
min-width: 0;
-moz-appearance: textfield;
appearance: textfield;
}
.survey-grid-input input::-webkit-outer-spin-button,
.survey-grid-input input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.survey-grid-suffix {
@ -737,6 +745,38 @@ a:focus-visible {
color: var(--text-muted);
}
.percent-input {
position: relative;
display: block;
flex: 1;
min-width: 0;
}
.site .percent-input input {
padding-right: 2rem;
-moz-appearance: textfield;
appearance: textfield;
}
.percent-input input::-webkit-outer-spin-button,
.percent-input input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.percent-unit {
position: absolute;
top: 50%;
right: 0.75rem;
transform: translateY(-50%);
color: var(--text-muted);
pointer-events: none;
}
.survey-grid-percent .survey-grid-value {
width: 7.5rem;
}
.survey-grid td.survey-grid-choice {
text-align: center;
vertical-align: middle;
@ -880,6 +920,10 @@ a:focus-visible {
font-size: 1.25rem;
}
.survey-grid-percent .survey-grid-value {
width: auto;
}
.flow-steps li {
font-size: 0.68rem;
}

View File

@ -126,6 +126,18 @@ function blurOnWheel(event) {
event.currentTarget.blur();
}
/** Show a "%" inside a percentage input; the saved value stays a plain number. */
function PercentInput({ children }) {
return (
<span className="percent-input">
{children}
<span className="percent-unit" aria-hidden="true">
%
</span>
</span>
);
}
/**
* @param {{ messages: string[] }} props
*/
@ -213,27 +225,30 @@ function QuestionField({
}
if (question.type === 'number' || question.type === 'percentage') {
const input = (
<input
type="number"
inputMode={question.integer ? 'numeric' : 'decimal'}
min={question.min}
max={question.max}
aria-invalid={invalid || undefined}
value={value === undefined || value === null ? '' : value}
onKeyDown={rangeKeyDown(question)}
onWheel={blurOnWheel}
onChange={(event) => {
const raw = event.target.value;
if (!inRange(question, raw)) {
return;
}
onChange(raw === '' ? '' : Number(raw));
}}
/>
);
return (
<div className="survey-field">
<label>
{question.label}
<input
type="number"
inputMode={question.integer ? 'numeric' : 'decimal'}
min={question.min}
max={question.max}
aria-invalid={invalid || undefined}
value={value === undefined || value === null ? '' : value}
onKeyDown={rangeKeyDown(question)}
onWheel={blurOnWheel}
onChange={(event) => {
const raw = event.target.value;
if (!inRange(question, raw)) {
return;
}
onChange(raw === '' ? '' : Number(raw));
}}
/>
{question.type === 'percentage' ? <PercentInput>{input}</PercentInput> : input}
</label>
{errors}
</div>
@ -318,16 +333,17 @@ function QuestionField({
if (question.type === 'grid_percentage' || question.type === 'grid_number') {
const grid = value && typeof value === 'object' ? value : {};
const percent = question.type === 'grid_percentage';
return (
<div className="survey-field">
<fieldset aria-invalid={invalid || undefined}>
<legend className={legendClass}>{question.label}</legend>
<table className="survey-grid">
<table className={percent ? 'survey-grid survey-grid-percent' : 'survey-grid'}>
<thead>
<tr>
<th scope="col">Pack type</th>
{question.columns.map((column) => (
<th key={column.id} scope="col">
<th key={column.id} scope="col" className="survey-grid-value">
{column.label}
</th>
))}
@ -337,40 +353,45 @@ function QuestionField({
{question.rows.map((row) => (
<tr key={row.id}>
<th scope="row">{row.label}</th>
{question.columns.map((column) => (
<td key={column.id}>
<span className="cell-label">{column.label}</span>
<div className="survey-grid-input">
<input
type="number"
inputMode={question.integer ? 'numeric' : 'decimal'}
min={question.min}
max={question.max}
aria-invalid={invalid || undefined}
aria-label={`${row.label}, ${column.label}`}
value={grid[row.id]?.[column.id] ?? ''}
onKeyDown={rangeKeyDown(question)}
onWheel={blurOnWheel}
onChange={(event) => {
const raw = event.target.value;
if (!inRange(question, raw)) {
return;
}
onChange({
...grid,
[row.id]: {
...(grid[row.id] ?? {}),
[column.id]: raw === '' ? '' : Number(raw),
},
});
}}
/>
{question.suffix ? (
<span className="survey-grid-suffix">{question.suffix}</span>
) : null}
</div>
</td>
))}
{question.columns.map((column) => {
const cellInput = (
<input
type="number"
inputMode={question.integer ? 'numeric' : 'decimal'}
min={question.min}
max={question.max}
aria-invalid={invalid || undefined}
aria-label={`${row.label}, ${column.label}`}
value={grid[row.id]?.[column.id] ?? ''}
onKeyDown={rangeKeyDown(question)}
onWheel={blurOnWheel}
onChange={(event) => {
const raw = event.target.value;
if (!inRange(question, raw)) {
return;
}
onChange({
...grid,
[row.id]: {
...(grid[row.id] ?? {}),
[column.id]: raw === '' ? '' : Number(raw),
},
});
}}
/>
);
return (
<td key={column.id} className="survey-grid-value">
<span className="cell-label">{column.label}</span>
<div className="survey-grid-input">
{percent ? <PercentInput>{cellInput}</PercentInput> : cellInput}
{question.suffix ? (
<span className="survey-grid-suffix">{question.suffix}</span>
) : null}
</div>
</td>
);
})}
</tr>
))}
</tbody>

View File

@ -95,6 +95,7 @@ describe('survey steps', () => {
fireEvent.change(field, { target: { value: '100' } });
expect(field).toHaveValue(100);
expect(field.closest('.percent-input')?.querySelector('.percent-unit')).toHaveTextContent('%');
});
it('blocks the minus and exponent keys when the minimum is zero', async () => {
@ -144,6 +145,8 @@ describe('survey steps', () => {
fireEvent.change(cell, { target: { value: '-1' } });
expect(cell).toHaveValue(60);
expect(cell.closest('.percent-input')?.querySelector('.percent-unit')).toHaveTextContent('%');
expect(cell.closest('table')).toHaveClass('survey-grid-percent');
});
it('keeps a missing required answer on the current step', async () => {