Adding dynamic input system, and some minor improvements in types.ts, registry.ts and test.ts
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 168 KiB |
@@ -1,12 +1,29 @@
|
|||||||
|
import InputComponent from "@/app/utils/Input";
|
||||||
import Input from "@/app/utils/Input";
|
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;
|
||||||
return(
|
const calculator = CalculatorRegistry[calcData.section].calculators.find(e => e.id === calcData.id);
|
||||||
|
console.log(calculator);
|
||||||
|
return calculator ? (
|
||||||
<>
|
<>
|
||||||
<h1>Section:- {calcData.section}</h1>
|
<div className="mb-6 mt-10">
|
||||||
<h1>Calculator ID:- {calcData.id}</h1>
|
<h1 className="text-2xl font-semibold">
|
||||||
<Input/>
|
{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(
|
||||||
|
<InputComponent {...e}/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</>
|
</>
|
||||||
)
|
) : null;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import LayoutClient from "./layoutClient";
|
import LayoutClient from "./layoutClient";
|
||||||
|
import { Roboto } from "next/font/google";
|
||||||
export default function CalculatorsLayout({children} : {children:React.ReactNode}){
|
export default function CalculatorsLayout({children} : {children:React.ReactNode}){
|
||||||
return(
|
return(
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Sidemenu from "../utils/Sidemenu";
|
import Sidemenu from "../utils/Sidemenu";
|
||||||
import Navbar from "../utils/Navbar";
|
import Navbar from "../utils/Navbar";
|
||||||
|
import { Roboto } from "next/font/google";
|
||||||
|
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">
|
<div className={`grid grid-cols-[300px_1fr] grid-rows-[60px_1fr_40px] overflow-hidden calculators-container ${font.className}`}>
|
||||||
<Navbar navbarToggle={setNavbar}/>
|
<Navbar navbarToggle={setNavbar}/>
|
||||||
<Sidemenu isNavOpen={navbar}/>
|
<Sidemenu isNavOpen={navbar}/>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
|
|||||||
@@ -1,11 +1,64 @@
|
|||||||
export default function Input(){
|
"use client"
|
||||||
return(
|
import { useState } from "react";
|
||||||
<>
|
import { Input } from "./calculators/types";
|
||||||
|
|
||||||
|
export default function InputComponent({id, type, inputOptions, min, max, required, defaultUnit, unitOptions, name, placeholder} : Input){
|
||||||
|
const [showError, setErrorStatus] = useState(false);
|
||||||
|
const [error, setError] = useState<string>();
|
||||||
|
const [option, setOption] = useState<string>("");
|
||||||
|
console.log(id);
|
||||||
|
if(type === "number"){
|
||||||
|
console.log(min);
|
||||||
|
return(
|
||||||
|
<>
|
||||||
|
<fieldset className="fieldset">
|
||||||
|
<legend className="fieldset-legend text-black">{name}</legend>
|
||||||
|
<input type="number"
|
||||||
|
id={id}
|
||||||
|
className="input bg-white"
|
||||||
|
placeholder={placeholder}
|
||||||
|
min={min}
|
||||||
|
max={max}
|
||||||
|
required={required}
|
||||||
|
onChange={(e) => {
|
||||||
|
if(e.target.value === ""){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const val = Number(e.target.value);
|
||||||
|
if(min !== undefined && val < min){
|
||||||
|
setError(`Value must be greater than or equal to ${min}`)
|
||||||
|
setErrorStatus(true);
|
||||||
|
}else if(max !== undefined && val > max){
|
||||||
|
setError(`Value must be smaller than or equal to ${max}`);
|
||||||
|
setErrorStatus(true);
|
||||||
|
}else{
|
||||||
|
setError("");
|
||||||
|
setErrorStatus(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{showError ? <p className="label text-red-400">{error}</p> : null}
|
||||||
|
</fieldset>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else if(type === "select"){
|
||||||
|
return(
|
||||||
<fieldset className="fieldset">
|
<fieldset className="fieldset">
|
||||||
<legend className="fieldset-legend text-black">Page title</legend>
|
<legend className="fieldset-legend text-black">{name}</legend>
|
||||||
<input type="text" className="input bg-white" placeholder="My awesome page" />
|
<select value={option}
|
||||||
<p className="label">You can edit page title later on from settings</p>
|
className="select bg-white"
|
||||||
|
onChange={(e) => {
|
||||||
|
setOption(e.target.value);
|
||||||
|
}}>
|
||||||
|
<option value="" disabled selected hidden>{placeholder}</option>
|
||||||
|
{inputOptions?.map(e => {
|
||||||
|
return(
|
||||||
|
<option key={e.label} value={e.value}>{e.value}</option>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
{/* <span className="label text-red-400">Optional</span> */}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</>
|
)
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
import Link from "next/link";
|
||||||
type Props = {
|
type Props = {
|
||||||
navbarToggle: React.Dispatch<React.SetStateAction<boolean>>;
|
navbarToggle: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Navbar({navbarToggle}: Props){
|
export default function Navbar({navbarToggle}: Props){
|
||||||
return(
|
return(
|
||||||
<div className="navbar bg-base-100 shadow-sm z-50">
|
<div className="navbar h-14 bg-base-100 shadow-sm z-50">
|
||||||
<div className="navbar-start">
|
<div className="navbar-start">
|
||||||
<div className="dropdown">
|
<div className="dropdown">
|
||||||
<button onClick={
|
<button onClick={
|
||||||
@@ -21,11 +21,13 @@ export default function Navbar({navbarToggle}: Props){
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="navbar-center">
|
<div className="navbar-center flex items-center justify-center">
|
||||||
<a href="/" className="flex items-center gap-2 leading-none translate-y-[10px]">
|
<Link href="/" className="flex items-center gap-2 w-fit">
|
||||||
<img src="/calcforcardiac_logo.png" className="w-32 h-32 object-contain" />
|
<img src="/calcforcardiac_logo.png" className="h-9 md:h-10 w-auto object-contain" />
|
||||||
<span className="text-lg font-semibold flex items-center relative top-[-10px]">CalcForCardiac</span>
|
<span className="text-lg font-semibold">
|
||||||
</a>
|
CalcForCardiac
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="navbar-end">
|
<div className="navbar-end">
|
||||||
<button className="btn btn-ghost btn-circle">
|
<button className="btn btn-ghost btn-circle">
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Calculator, Input, Interpretation } from "../types";
|
import { Calculator, Input, Interpretation, Values } from "../types";
|
||||||
|
|
||||||
const parameters:Input[] = [
|
const parameters:Input[] = [
|
||||||
{
|
{
|
||||||
id:"gender",
|
id:"gender",
|
||||||
type:"radio",
|
name:"Gender",
|
||||||
|
placeholder:"Enter your gender",
|
||||||
|
type:"select",
|
||||||
inputOptions:[
|
inputOptions:[
|
||||||
{
|
{
|
||||||
label:"Male",
|
label:"Male",
|
||||||
@@ -19,6 +21,8 @@ const parameters:Input[] = [
|
|||||||
{
|
{
|
||||||
id:"age",
|
id:"age",
|
||||||
type:"number",
|
type:"number",
|
||||||
|
name:"Age",
|
||||||
|
placeholder:"Enter your age",
|
||||||
min:18,
|
min:18,
|
||||||
max:95,
|
max:95,
|
||||||
required:true
|
required:true
|
||||||
@@ -26,6 +30,8 @@ const parameters:Input[] = [
|
|||||||
{
|
{
|
||||||
id:"creatinine",
|
id:"creatinine",
|
||||||
type:"number",
|
type:"number",
|
||||||
|
name:"Creatinine",
|
||||||
|
placeholder:"Enter your serum creatinine values",
|
||||||
min:0.2,
|
min:0.2,
|
||||||
max:20,
|
max:20,
|
||||||
required:true
|
required:true
|
||||||
@@ -33,11 +39,18 @@ const parameters:Input[] = [
|
|||||||
{
|
{
|
||||||
id:"weight",
|
id:"weight",
|
||||||
type:"number",
|
type:"number",
|
||||||
min:0,
|
name:"Weight",
|
||||||
|
placeholder:"Enter your weight in kilograms",
|
||||||
|
min:10,
|
||||||
|
max:100 ,
|
||||||
required:true
|
required:true
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
function calc_func(gender:"male" | "female", age:number, creatinine:number, weight:number):number{
|
function calc_func(values : Values):number{
|
||||||
|
const gender = values.gender as "male" | "female";
|
||||||
|
const age = values.age as number;
|
||||||
|
const weight = values.weight as number;
|
||||||
|
const creatinine = values.creatinine as number;
|
||||||
return gender === "male"
|
return gender === "male"
|
||||||
? ((140 - age) * weight)/(72 * creatinine)
|
? ((140 - age) * weight)/(72 * creatinine)
|
||||||
: (((140 - age) * weight)/(72 * creatinine)) * 0.85;
|
: (((140 - age) * weight)/(72 * creatinine)) * 0.85;
|
||||||
|
|||||||
10
src/app/utils/calculators/miscellaneous/test.ts
Normal file
10
src/app/utils/calculators/miscellaneous/test.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { CalculatorRegistry } from "../registry";
|
||||||
|
const calculator = CalculatorRegistry.miscellaneous.calculators[0].calc_func;
|
||||||
|
console.log(calculator(
|
||||||
|
{
|
||||||
|
gender:"male",
|
||||||
|
age:43,
|
||||||
|
creatinine:5,
|
||||||
|
weight:60
|
||||||
|
}
|
||||||
|
));
|
||||||
15
src/app/utils/calculators/registry.js
Normal file
15
src/app/utils/calculators/registry.js
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.CalculatorRegistry = void 0;
|
||||||
|
var cockcroft_gault_eq_1 = require("./miscellaneous/cockcroft-gault-eq");
|
||||||
|
exports.CalculatorRegistry = {
|
||||||
|
miscellaneous: {
|
||||||
|
id: "miscellaneous",
|
||||||
|
displayName: "Miscellaneous",
|
||||||
|
textColor: "#ccc",
|
||||||
|
svg: "",
|
||||||
|
calculators: [
|
||||||
|
cockcroft_gault_eq_1.cockcroftGault
|
||||||
|
]
|
||||||
|
}
|
||||||
|
};
|
||||||
2
src/app/utils/calculators/types.js
Normal file
2
src/app/utils/calculators/types.js
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
@@ -5,15 +5,18 @@ export interface Calculator {
|
|||||||
unit?:string,
|
unit?:string,
|
||||||
inputs:Input[],
|
inputs:Input[],
|
||||||
calc_func:Function,
|
calc_func:Function,
|
||||||
interpret_func:Function
|
interpret_func:Function,
|
||||||
|
customComponent?:React.FC
|
||||||
}
|
}
|
||||||
interface inputOptions {
|
interface inputOptions {
|
||||||
label:string,
|
label:string,
|
||||||
value:string | number | Date;
|
value:string | number ;
|
||||||
}
|
}
|
||||||
export interface Input{
|
export interface Input{
|
||||||
id:string,
|
id:string,
|
||||||
type: "number" | "text" | "radio",
|
name:string,
|
||||||
|
placeholder:string,
|
||||||
|
type: "number" | "text" | "select",
|
||||||
inputOptions?:inputOptions[],
|
inputOptions?:inputOptions[],
|
||||||
min?:number,
|
min?:number,
|
||||||
max?:number,
|
max?:number,
|
||||||
@@ -35,3 +38,5 @@ export interface Section {
|
|||||||
svg:string,
|
svg:string,
|
||||||
calculators:Calculator[]
|
calculators:Calculator[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Values = Record<string, string | number >;
|
||||||
|
|||||||
Reference in New Issue
Block a user