Complete and working implementation of renderCalc.tsx | v1.0
This commit is contained in:
@@ -1,29 +1,9 @@
|
|||||||
import InputComponent from "@/app/utils/Input";
|
import RenderCalculator from "./renderCalc";
|
||||||
import Input from "@/app/utils/Input";
|
|
||||||
import { CalculatorRegistry } from "@/app/utils/calculators/registry";
|
|
||||||
export default async function Calculator({params} : {params:Promise<{section:string, id:string}>}){
|
export default async function Calculator({params} : {params:Promise<{section:string, id:string}>}){
|
||||||
const calcData : {section:string, id:string} = await params;
|
const calcData : {section:string, id:string} = await params;
|
||||||
const calculator = CalculatorRegistry[calcData.section].calculators.find(e => e.id === calcData.id);
|
|
||||||
console.log(calculator);
|
|
||||||
return calculator ? (
|
|
||||||
<>
|
|
||||||
<div className="mb-6 mt-10">
|
|
||||||
<h1 className="text-2xl font-semibold">
|
|
||||||
{calculator?.name}
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<p className="text-gray-500 mt-1 max-w-xl">
|
|
||||||
{calculator?.desc}
|
|
||||||
</p>
|
|
||||||
<h1 className="text-1xl font-semibold">
|
|
||||||
Unit of the value:- {calculator?.unit}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
{calculator.inputs.map(e => {
|
|
||||||
return(
|
return(
|
||||||
<InputComponent {...e}/>
|
<RenderCalculator key={calcData.id} section={calcData.section} id={calcData.id}/>
|
||||||
);
|
);
|
||||||
})}
|
|
||||||
</>
|
|
||||||
) : null;
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import InputComponent from "@/app/utils/Input";
|
||||||
|
import Input from "@/app/utils/Input";
|
||||||
|
import Result from "@/app/utils/Result";
|
||||||
|
import { CalculatorRegistry } from "@/app/utils/calculators/registry";
|
||||||
|
import { Interpretation } from "@/app/utils/calculators/types";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export default function RenderCalculator({section, id} : {section:string, id:string}){
|
||||||
|
const calculator = CalculatorRegistry[section].calculators.find(e => e.id === id);
|
||||||
|
const [form, setForm] = useState<Record<string, string | number>>({});
|
||||||
|
const [value, setValue] = useState<string | number>("");
|
||||||
|
function handleDataChange(key:string, value:string){
|
||||||
|
setForm(prev => {
|
||||||
|
return {
|
||||||
|
...prev,
|
||||||
|
[key]:value
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const [showResult, setResultStatus] = useState<boolean>(false);
|
||||||
|
const [result, setResult] = useState<Interpretation>({
|
||||||
|
level:"none",
|
||||||
|
message:"none"
|
||||||
|
});
|
||||||
|
console.log(form);
|
||||||
|
return calculator ? (
|
||||||
|
<>
|
||||||
|
<div className="mb-6 mt-10">
|
||||||
|
<h1 className="text-2xl font-semibold">
|
||||||
|
{calculator?.name}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p className="text-gray-500 mt-1 max-w-xl">
|
||||||
|
{calculator?.desc}
|
||||||
|
</p>
|
||||||
|
<h1 className="text-1xl font-semibold">
|
||||||
|
Unit of the value:- {calculator?.unit}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div className="max-w-2xl">
|
||||||
|
<form onSubmit={(e: React.SubmitEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setResultStatus(true);
|
||||||
|
const calculatedValue = calculator.calc_func(form);
|
||||||
|
setValue(calculatedValue);
|
||||||
|
setResult(calculator.interpret_func(calculatedValue));
|
||||||
|
}}>
|
||||||
|
<div className="card max-w-auto bg-white bg-base-100 shadow-sm">
|
||||||
|
<div className="card-body">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-x-6 gap-y-4">
|
||||||
|
{calculator.inputs.map(e => {
|
||||||
|
return(
|
||||||
|
<InputComponent key={e.id} {...e} handleDataChange={handleDataChange}/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<button type={"submit"} className="btn md:col-span-2 w-full text-white border-none bg-[#ed1b24] hover:bg-[#c9161e]"
|
||||||
|
>Calculate</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{showResult ? <h3>
|
||||||
|
<Result
|
||||||
|
interpretation={result}
|
||||||
|
calculated_value={value}
|
||||||
|
unit={calculator.unit ?? ""}
|
||||||
|
/>
|
||||||
|
</h3> : null}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : null;
|
||||||
|
}
|
||||||
@@ -7,12 +7,14 @@ const font = Roboto({});
|
|||||||
export default function LayoutClient({children} : {children:React.ReactNode}){
|
export default function LayoutClient({children} : {children:React.ReactNode}){
|
||||||
const [navbar, setNavbar] = useState<boolean>(false);
|
const [navbar, setNavbar] = useState<boolean>(false);
|
||||||
return(
|
return(
|
||||||
<div className={`grid grid-cols-[300px_1fr] grid-rows-[60px_1fr_40px] overflow-hidden calculators-container ${font.className}`}>
|
<div className={`grid grid-cols-[300px_1fr] grid-rows-[60px_1fr_40px] calculators-container ${font.className}`}>
|
||||||
<Navbar navbarToggle={setNavbar}/>
|
<Navbar navbarToggle={setNavbar}/>
|
||||||
<Sidemenu isNavOpen={navbar}/>
|
<Sidemenu isNavOpen={navbar}/>
|
||||||
<div className="content">
|
<div className="content w-full flex justify-center px-4 pb-6">
|
||||||
|
<div className="w-full max-w-2xl">
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="footer"></div>
|
<div className="footer"></div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,23 +2,22 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Input } from "./calculators/types";
|
import { Input } from "./calculators/types";
|
||||||
|
|
||||||
export default function InputComponent({id, type, inputOptions, min, max, required, defaultUnit, unitOptions, name, placeholder} : Input){
|
export default function InputComponent({id, type, inputOptions, min, max, required, defaultUnit, unitOptions, name, placeholder, handleDataChange} : Input){
|
||||||
const [showError, setErrorStatus] = useState(false);
|
const [showError, setErrorStatus] = useState(false);
|
||||||
const [error, setError] = useState<string>();
|
const [error, setError] = useState<string>();
|
||||||
const [option, setOption] = useState<string>("");
|
const [option, setOption] = useState<string>("");
|
||||||
console.log(id);
|
|
||||||
if(type === "number"){
|
if(type === "number"){
|
||||||
console.log(min);
|
|
||||||
return(
|
return(
|
||||||
<>
|
<>
|
||||||
<fieldset className="fieldset">
|
<fieldset className="fieldset">
|
||||||
<legend className="fieldset-legend text-black">{name}</legend>
|
<legend className="fieldset-legend text-black">{name}</legend>
|
||||||
<input type="number"
|
<input type="number"
|
||||||
id={id}
|
id={id}
|
||||||
className="input bg-white"
|
className="input bg-white border-solid border-black"
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
min={min}
|
min={min}
|
||||||
max={max}
|
max={max}
|
||||||
|
step={0.1}
|
||||||
required={required}
|
required={required}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
if(e.target.value === ""){
|
if(e.target.value === ""){
|
||||||
@@ -34,6 +33,7 @@ export default function InputComponent({id, type, inputOptions, min, max, requir
|
|||||||
}else{
|
}else{
|
||||||
setError("");
|
setError("");
|
||||||
setErrorStatus(false);
|
setErrorStatus(false);
|
||||||
|
handleDataChange !== undefined ? handleDataChange(id, e.target.value) : null;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -46,11 +46,14 @@ export default function InputComponent({id, type, inputOptions, min, max, requir
|
|||||||
<fieldset className="fieldset">
|
<fieldset className="fieldset">
|
||||||
<legend className="fieldset-legend text-black">{name}</legend>
|
<legend className="fieldset-legend text-black">{name}</legend>
|
||||||
<select value={option}
|
<select value={option}
|
||||||
className="select bg-white"
|
className="select bg-white border-solid border-black"
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setOption(e.target.value);
|
setOption(e.target.value);
|
||||||
}}>
|
handleDataChange !== undefined ? handleDataChange(id, e.target.value) : null;
|
||||||
<option value="" disabled selected hidden>{placeholder}</option>
|
}}
|
||||||
|
required={required}
|
||||||
|
>
|
||||||
|
<option value="" disabled hidden>{placeholder}</option>
|
||||||
{inputOptions?.map(e => {
|
{inputOptions?.map(e => {
|
||||||
return(
|
return(
|
||||||
<option key={e.label} value={e.value}>{e.value}</option>
|
<option key={e.label} value={e.value}>{e.value}</option>
|
||||||
|
|||||||
29
src/app/utils/Result.tsx
Normal file
29
src/app/utils/Result.tsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { Interpretation } from "./calculators/types";
|
||||||
|
|
||||||
|
export default function Result({interpretation, calculated_value, unit} : {interpretation:Interpretation, calculated_value:string | number, unit:string
|
||||||
|
}){
|
||||||
|
var {level, message, diagnosis, advice} = interpretation;
|
||||||
|
var levelClass = "";
|
||||||
|
if(level === "none" || level === "low"){
|
||||||
|
levelClass = "bg-success";
|
||||||
|
}else if(level === "moderate"){
|
||||||
|
levelClass = "bg-orange-600";
|
||||||
|
}else if(level === "high" || level === "severe"){
|
||||||
|
levelClass = "bg-red-500";
|
||||||
|
}else{
|
||||||
|
levelClass = "bg-white";
|
||||||
|
}
|
||||||
|
console.log(levelClass);
|
||||||
|
return(
|
||||||
|
<div className={`card max-w-auto ${levelClass} bg-base-100 shadow-sm mt-5 ${levelClass}`}>
|
||||||
|
<div className="card-body">
|
||||||
|
<h2 className="card-title self-center">Calculated Score/Value: {calculated_value} {unit}</h2>
|
||||||
|
<p>{message}</p>
|
||||||
|
{diagnosis ? <p>Diagnosis: {diagnosis}</p> : null}
|
||||||
|
{advice ? <p>Advice: {advice}</p> : null}
|
||||||
|
<div className="card-actions justify-end">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -8,7 +8,11 @@ export default function Section({sectionName, Calculators, id} : {sectionName:st
|
|||||||
<ul>
|
<ul>
|
||||||
{Calculators.map((e) => {
|
{Calculators.map((e) => {
|
||||||
return(
|
return(
|
||||||
<li><a key={e.id} href={`/calculate/${id}/${e.id}`}>{e.name}</a></li>
|
<li key={e.id}>
|
||||||
|
<a href={`/calculate/${id}/${e.id}`}>
|
||||||
|
{e.name}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const parameters:Input[] = [
|
|||||||
{
|
{
|
||||||
id:"gender",
|
id:"gender",
|
||||||
name:"Gender",
|
name:"Gender",
|
||||||
placeholder:"Enter your gender",
|
placeholder:"Select gender",
|
||||||
type:"select",
|
type:"select",
|
||||||
inputOptions:[
|
inputOptions:[
|
||||||
{
|
{
|
||||||
@@ -22,7 +22,7 @@ const parameters:Input[] = [
|
|||||||
id:"age",
|
id:"age",
|
||||||
type:"number",
|
type:"number",
|
||||||
name:"Age",
|
name:"Age",
|
||||||
placeholder:"Enter your age",
|
placeholder:"Enter age",
|
||||||
min:18,
|
min:18,
|
||||||
max:95,
|
max:95,
|
||||||
required:true
|
required:true
|
||||||
@@ -31,7 +31,7 @@ const parameters:Input[] = [
|
|||||||
id:"creatinine",
|
id:"creatinine",
|
||||||
type:"number",
|
type:"number",
|
||||||
name:"Creatinine",
|
name:"Creatinine",
|
||||||
placeholder:"Enter your serum creatinine values",
|
placeholder:"Enter serum creatinine values in mg/dL",
|
||||||
min:0.2,
|
min:0.2,
|
||||||
max:20,
|
max:20,
|
||||||
required:true
|
required:true
|
||||||
@@ -40,7 +40,7 @@ const parameters:Input[] = [
|
|||||||
id:"weight",
|
id:"weight",
|
||||||
type:"number",
|
type:"number",
|
||||||
name:"Weight",
|
name:"Weight",
|
||||||
placeholder:"Enter your weight in kilograms",
|
placeholder:"Enter weight in kilograms",
|
||||||
min:10,
|
min:10,
|
||||||
max:100 ,
|
max:100 ,
|
||||||
required:true
|
required:true
|
||||||
@@ -52,8 +52,8 @@ function calc_func(values : Values):number{
|
|||||||
const weight = values.weight as number;
|
const weight = values.weight as number;
|
||||||
const creatinine = values.creatinine as number;
|
const creatinine = values.creatinine as number;
|
||||||
return gender === "male"
|
return gender === "male"
|
||||||
? ((140 - age) * weight)/(72 * creatinine)
|
? Math.floor(((140 - age) * weight)/(72 * creatinine))
|
||||||
: (((140 - age) * weight)/(72 * creatinine)) * 0.85;
|
: Math.floor((((140 - age) * weight)/(72 * creatinine)) * 0.85);
|
||||||
}
|
}
|
||||||
function interpret_func(gfr:number):Interpretation{
|
function interpret_func(gfr:number):Interpretation{
|
||||||
if(gfr >= 90){
|
if(gfr >= 90){
|
||||||
|
|||||||
@@ -22,11 +22,12 @@ export interface Input{
|
|||||||
max?:number,
|
max?:number,
|
||||||
required?:boolean,
|
required?:boolean,
|
||||||
defaultUnit?:string,
|
defaultUnit?:string,
|
||||||
unitOptions?:string[]
|
unitOptions?:string[],
|
||||||
|
handleDataChange?:Function
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Interpretation{
|
export interface Interpretation{
|
||||||
level?: "none" | "low" | "moderate" | "high" | "severe",
|
level: "none" | "low" | "moderate" | "high" | "severe",
|
||||||
diagnosis?:string,
|
diagnosis?:string,
|
||||||
message:string,
|
message:string,
|
||||||
advice?:string
|
advice?:string
|
||||||
|
|||||||
Reference in New Issue
Block a user