-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
329 lines (309 loc) · 16.9 KB
/
Copy pathapp.js
File metadata and controls
329 lines (309 loc) · 16.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
const pathCards = [
["What is coding?", "Coding means reading the medical note and choosing standard codes that describe the patient's condition and the care provided."],
["What is billing?", "Billing means using those codes, insurance details, provider information, and payer rules to ask for payment."],
["Why so many rules?", "Codes affect payment, data, audits, and patient bills. The rules protect accuracy and prevent guessing."],
["What should I learn first?", "Start with medical words, then ICD-10-CM diagnosis coding, then CPT/HCPCS procedure and supply coding, then billing workflow."],
["When am I ready?", "You are ready when you can explain your answers from the documentation and find rules in the book without panic."]
];
const topics = [
{
title: "Coder vs Biller",
short: "Who does what?",
meaning: "A coder focuses on turning documentation into accurate diagnosis and procedure codes. A biller focuses on turning those codes into a clean claim and following the claim until it is paid, denied, corrected, appealed, or closed.",
example: "A provider documents diabetes with neuropathy. The coder identifies the diagnosis code. The biller checks insurance, submits the claim, posts payment, and handles denials.",
terms: ["Claim", "Denial", "Clean claim"]
},
{
title: "ICD-10-CM",
short: "Diagnosis codes",
meaning: "ICD-10-CM explains why the patient was seen. It covers diseases, symptoms, injuries, screenings, history, and status codes.",
example: "If the patient is seen for type 2 diabetes, ICD-10-CM is the code set that describes that diagnosis.",
terms: ["ICD-10-CM", "Diagnosis", "Tabular List"]
},
{
title: "CPT",
short: "Service codes",
meaning: "CPT describes professional medical services and procedures, such as office visits, surgeries, lab services, imaging, and medicine services.",
example: "If a physician performs an office visit or removes a lesion, CPT is usually involved.",
terms: ["CPT", "E/M", "Modifier"]
},
{
title: "HCPCS Level II",
short: "Supplies and drugs",
meaning: "HCPCS Level II covers many supplies, drugs, durable medical equipment, ambulance services, and other items that CPT may not fully describe.",
example: "A wheelchair, oxygen equipment, or certain injected drugs may use HCPCS Level II.",
terms: ["HCPCS", "DME", "Units"]
},
{
title: "Clean Claim",
short: "A claim ready to process",
meaning: "A clean claim has the required patient, provider, payer, diagnosis, procedure, date, charge, and policy information so the payer can process it without preventable errors.",
example: "Wrong member ID, missing authorization, or invalid modifier can stop a claim from being clean.",
terms: ["Clean claim", "NPI", "POS"]
},
{
title: "Denial",
short: "Not paid as submitted",
meaning: "A denial means the payer processed the claim but did not pay it as submitted. The fix depends on the reason. You do not automatically resubmit.",
example: "A medical necessity denial means you must review the payer policy and documentation before deciding whether to correct or appeal.",
terms: ["Denial", "EOB", "Medical necessity"]
}
];
const visuals = [
{
label: "Code Sets",
img: "assets/visuals/code_sets_map.svg",
title: "Which code set do I use?",
text: "Think of code sets as different languages. ICD-10-CM explains why. CPT and HCPCS explain what was done. ICD-10-PCS is for inpatient hospital procedures."
},
{
label: "Revenue Cycle",
img: "assets/visuals/revenue_cycle_flow.svg",
title: "How money moves",
text: "The revenue cycle starts before the visit with scheduling and insurance checks. Errors early in the process can cause denials later."
},
{
label: "Lookup Path",
img: "assets/visuals/icd10cm_lookup_path.svg",
title: "How to look up ICD-10-CM",
text: "Start with the chart. Look in the Alphabetic Index. Verify in the Tabular List. Then apply official guidelines."
},
{
label: "Denials",
img: "assets/visuals/denial_decision_tree.svg",
title: "How to think about denials",
text: "A denial is a problem to diagnose. First read the payer's reason, then decide whether the correct next step is a correction, appeal, records request, or write-off."
}
];
const bucketQuestions = [
{
prompt: "Patient has acute bronchitis.",
answer: "Diagnosis coding",
why: "This describes the patient's condition, so it belongs in ICD-10-CM diagnosis coding."
},
{
prompt: "Provider performed an office visit.",
answer: "Procedure/service coding",
why: "An office visit is a professional service, usually described with CPT."
},
{
prompt: "Insurance denied because authorization was missing.",
answer: "Billing",
why: "Authorization and denial follow-up are part of billing and revenue cycle work."
}
];
const nextQuestions = [
{
prompt: "A claim is rejected because the patient date of birth does not match the payer file.",
answer: "Fix the registration or eligibility data.",
why: "A rejection often means the payer could not process the claim. Fix the data before resubmitting."
},
{
prompt: "You found a possible ICD-10-CM code in the Alphabetic Index.",
answer: "Verify it in the Tabular List.",
why: "The Tabular List contains notes, specificity, laterality, and exclusions."
},
{
prompt: "A payer denied a test for medical necessity.",
answer: "Review documentation and payer policy.",
why: "Do not change codes just to get paid. The medical record must support the claim."
}
];
const dictionary = [
{ term: "AAPC", full: "American Academy of Professional Coders", meaning: "Credentialing and education organization. CPC and CPB are AAPC credentials.", kind: "acronym" },
{ term: "AHIMA", full: "American Health Information Management Association", meaning: "Credentialing and health information organization. CCA, CCS, and CCS-P are AHIMA credentials.", kind: "acronym" },
{ term: "CPC", full: "Certified Professional Coder", meaning: "A common AAPC credential for physician and professional-service coding.", kind: "acronym" },
{ term: "CPB", full: "Certified Professional Biller", meaning: "AAPC credential focused on billing, claims, payment, and revenue cycle.", kind: "acronym" },
{ term: "CCA", full: "Certified Coding Associate", meaning: "AHIMA entry-level coding credential.", kind: "acronym" },
{ term: "CCS", full: "Certified Coding Specialist", meaning: "AHIMA coding credential often connected with facility coding.", kind: "acronym" },
{ term: "CCS-P", full: "Certified Coding Specialist-Physician-based", meaning: "AHIMA credential focused on physician-based coding.", kind: "acronym" },
{ term: "ICD-10-CM", full: "International Classification of Diseases, 10th Revision, Clinical Modification", meaning: "Diagnosis code system. It answers why the patient was seen.", kind: "acronym" },
{ term: "CPT", full: "Current Procedural Terminology", meaning: "Procedure and service code system. It often answers what professional service was done.", kind: "acronym" },
{ term: "HCPCS", full: "Healthcare Common Procedure Coding System", meaning: "Code system that includes CPT and Level II supply, drug, and service codes.", kind: "acronym" },
{ term: "E/M", full: "Evaluation and Management", meaning: "Visit services such as office visits, hospital visits, and consultations.", kind: "acronym" },
{ term: "DME", full: "Durable Medical Equipment", meaning: "Reusable medical equipment such as wheelchairs, oxygen equipment, or walkers.", kind: "acronym" },
{ term: "NPI", full: "National Provider Identifier", meaning: "Standard provider ID number used in claims.", kind: "acronym" },
{ term: "POS", full: "Place of Service", meaning: "Code showing where the service happened, such as office, hospital, or telehealth.", kind: "acronym" },
{ term: "EOB", full: "Explanation of Benefits", meaning: "Payer statement explaining how insurance handled a claim.", kind: "acronym" },
{ term: "ERA", full: "Electronic Remittance Advice", meaning: "Electronic version of payment and denial details.", kind: "acronym" },
{ term: "COB", full: "Coordination of Benefits", meaning: "Decides which insurance pays first when a patient has more than one plan.", kind: "acronym" },
{ term: "NCCI", full: "National Correct Coding Initiative", meaning: "CMS edits that help identify bundled or mutually exclusive code pairs.", kind: "acronym" },
{ term: "MUE", full: "Medically Unlikely Edit", meaning: "CMS edit that limits units that are likely reasonable for one date of service.", kind: "acronym" },
{ term: "LCD", full: "Local Coverage Determination", meaning: "Medicare contractor rule explaining when a service is covered locally.", kind: "acronym" },
{ term: "NCD", full: "National Coverage Determination", meaning: "National Medicare coverage rule.", kind: "acronym" },
{ term: "Modifier", full: "Coding add-on", meaning: "Two-character code added to CPT or HCPCS to explain a special circumstance.", kind: "term" },
{ term: "Claim", full: "Payment request", meaning: "Request for payment sent to insurance.", kind: "term" },
{ term: "Clean claim", full: "Processable claim", meaning: "A claim that has the needed information and can be processed without preventable errors.", kind: "term" },
{ term: "Denial", full: "Not paid as submitted", meaning: "A claim was processed but not paid as submitted.", kind: "term" },
{ term: "Rejection", full: "Stopped before processing", meaning: "A claim was stopped before processing because something was missing or invalid.", kind: "term" },
{ term: "Medical necessity", full: "Why the service is needed", meaning: "The service makes sense for the patient's condition and payer rules.", kind: "term" },
{ term: "Authorization", full: "Payer approval", meaning: "Approval required before some services.", kind: "term" },
{ term: "Tabular List", full: "ICD-10-CM verification section", meaning: "The place where you confirm the code and read notes before final selection.", kind: "term" },
{ term: "Diagnosis", full: "Patient condition", meaning: "The illness, symptom, injury, screening reason, or health status being reported.", kind: "term" },
{ term: "Units", full: "Quantity billed", meaning: "The number of billable items, tests, drug amounts, or service units reported.", kind: "term" }
];
let activeTopic = 0;
let activeVisual = 0;
let bucketIndex = 0;
let nextIndex = 0;
let flashIndex = 0;
let flashShowingMeaning = false;
function renderPath() {
document.querySelector("#pathCards").innerHTML = pathCards.map((card, index) => `
<article class="path-card">
<div class="num">${index + 1}</div>
<h3>${card[0]}</h3>
<p>${card[1]}</p>
</article>
`).join("");
}
function renderTopics() {
document.querySelector("#topicList").innerHTML = topics.map((topic, index) => `
<button class="topic-btn ${index === activeTopic ? "active" : ""}" type="button" data-topic="${index}">
${topic.title}
</button>
`).join("");
const topic = topics[activeTopic];
document.querySelector("#explainerCard").innerHTML = `
<h3>${topic.title}</h3>
<p>${topic.short}</p>
<div class="explain-box"><strong>What it means</strong><p>${topic.meaning}</p></div>
<div class="example-box"><strong>Example</strong><p>${topic.example}</p></div>
<div>${topic.terms.map(term => `<span class="term-chip">${term}: ${lookupMeaning(term)}</span>`).join("")}</div>
`;
document.querySelectorAll(".topic-btn").forEach(btn => {
btn.addEventListener("click", () => {
activeTopic = Number(btn.dataset.topic);
renderTopics();
});
});
}
function renderVisuals() {
const visual = visuals[activeVisual];
document.querySelector("#visualCopy").innerHTML = `<h3>${visual.title}</h3><p>${visual.text}</p>`;
document.querySelector("#visualImg").src = visual.img;
document.querySelector("#visualImg").alt = visual.title;
document.querySelector("#visualButtons").innerHTML = visuals.map((item, index) => `
<button class="visual-btn ${index === activeVisual ? "active" : ""}" type="button" data-visual="${index}">${item.label}</button>
`).join("");
document.querySelectorAll(".visual-btn").forEach(btn => {
btn.addEventListener("click", () => {
activeVisual = Number(btn.dataset.visual);
renderVisuals();
});
});
}
function renderBucketPractice() {
const q = bucketQuestions[bucketIndex % bucketQuestions.length];
const options = ["Diagnosis coding", "Procedure/service coding", "Billing"];
document.querySelector("#bucketPractice").innerHTML = practiceTemplate(q.prompt, options, "bucket");
bindPractice("#bucketPractice", q, () => {
bucketIndex = (bucketIndex + 1) % bucketQuestions.length;
renderBucketPractice();
});
}
function renderNextPractice() {
const q = nextQuestions[nextIndex % nextQuestions.length];
const options = [
"Fix the registration or eligibility data.",
"Verify it in the Tabular List.",
"Review documentation and payer policy.",
"Resubmit without checking anything."
];
document.querySelector("#nextStepPractice").innerHTML = practiceTemplate(q.prompt, options, "next");
bindPractice("#nextStepPractice", q, () => {
nextIndex = (nextIndex + 1) % nextQuestions.length;
renderNextPractice();
});
}
function practiceTemplate(prompt, options, id) {
return `
<div class="prompt"><strong>${prompt}</strong><span>Choose the best beginner answer.</span></div>
<div class="answers">
${options.map(option => `<button class="answer" type="button" data-answer="${option}">${option}</button>`).join("")}
</div>
<div class="feedback" id="${id}Feedback">Pick one. Mistakes are part of learning.</div>
<button class="button next" type="button" id="${id}Next">Next small step</button>
`;
}
function bindPractice(scope, q, nextFn) {
const root = document.querySelector(scope);
root.querySelectorAll(".answer").forEach(btn => {
btn.addEventListener("click", () => {
const correct = btn.dataset.answer === q.answer;
btn.classList.add(correct ? "correct" : "wrong");
const fb = root.querySelector(".feedback");
fb.className = `feedback ${correct ? "good" : "bad"}`;
fb.textContent = `${correct ? "Yes." : "Not quite."} ${q.why}`;
}, { once: true });
});
root.querySelector(".next").addEventListener("click", nextFn);
}
function renderDictionary() {
const q = document.querySelector("#termSearch").value.toLowerCase().trim();
const rows = dictionary.filter(item => !q || `${item.term} ${item.full} ${item.meaning}`.toLowerCase().includes(q));
document.querySelector("#terms").innerHTML = rows.map(item => `
<article class="term-card">
<strong>${item.term}</strong>
<em>${item.full}</em>
<p>${item.meaning}</p>
<span>${item.kind}</span>
</article>
`).join("") || `<article class="term-card"><strong>No match yet</strong><p>Try a shorter word like claim, code, denial, or CPT.</p></article>`;
}
function lookupMeaning(term) {
const item = dictionary.find(row => row.term.toLowerCase() === term.toLowerCase());
return item ? item.meaning : "important word to remember";
}
function renderSpotlight() {
const todayIndex = Math.floor(Date.now() / 86400000) % dictionary.length;
const item = dictionary[todayIndex];
document.querySelector("#termSpotlight").innerHTML = `
<strong>Term to remember: ${item.term}</strong>
<span>${item.full} — ${item.meaning}</span>
`;
}
function renderFlashcard() {
const acronyms = dictionary.filter(item => item.kind === "acronym");
const item = acronyms[flashIndex % acronyms.length];
document.querySelector("#flashCount").textContent = `${flashIndex + 1} / ${acronyms.length}`;
document.querySelector("#flashcard").innerHTML = flashShowingMeaning
? `<strong>${item.full}</strong><span>${item.term}: ${item.meaning}</span>`
: `<strong>${item.term}</strong><span>Tap Show meaning when ready</span>`;
}
function renderReviewStack() {
const rows = dictionary.slice(0, 8);
document.querySelector("#reviewStack").innerHTML = rows.map(item => `
<div class="review-row">
<strong>${item.term} = ${item.full}</strong>
<span>${item.meaning}</span>
</div>
`).join("");
}
function init() {
renderPath();
renderTopics();
renderVisuals();
renderBucketPractice();
renderNextPractice();
renderSpotlight();
renderFlashcard();
renderReviewStack();
renderDictionary();
document.querySelector("#termSearch").addEventListener("input", renderDictionary);
document.querySelector("#showMeaning").addEventListener("click", () => {
flashShowingMeaning = true;
renderFlashcard();
});
document.querySelector("#flashcard").addEventListener("click", () => {
flashShowingMeaning = !flashShowingMeaning;
renderFlashcard();
});
document.querySelector("#nextFlashcard").addEventListener("click", () => {
const acronyms = dictionary.filter(item => item.kind === "acronym");
flashIndex = (flashIndex + 1) % acronyms.length;
flashShowingMeaning = false;
renderFlashcard();
});
}
init();