12 Commits

Author SHA1 Message Date
a309559b93 Merge branch 'master' into merge_mstr_tableComponent 2023-11-16 13:36:42 +07:00
b836e66af7 memecah komponen data table dan dropdown shadcnui 2023-11-16 12:17:48 +07:00
a08e51049d memperbaiki asset svg & pemanggilan asset di file 2023-11-16 11:46:32 +07:00
sindhu
32ac16abc8 delete front_end_portserver_old 2023-11-16 09:10:14 +07:00
sindhu
226aceb1dc Merge branch 'sindhu/storybook_component' 2023-11-16 09:07:41 +07:00
d5ac090054 Perbaikan Icon Component dan stories 2023-11-14 09:09:52 +07:00
adecf76a25 perbaikan storybook dataTable Component 2023-11-13 23:07:42 +07:00
6be45eeb88 add new stories and compoennt data table portserver 2023-11-13 15:18:03 +07:00
sindhu
766541b19b storybook fix props card instrument 2023-11-10 17:06:52 +07:00
sindhu
4257c560c9 instrument box component & stories 2023-11-09 19:02:51 +07:00
sindhu
1d6ad9c875 card instrument main 2023-11-08 13:40:32 +07:00
sindhu
afa3c02d99 storybook and shadcn integrate 2023-11-07 09:34:30 +07:00
62 changed files with 3709 additions and 15429 deletions

View File

@@ -7,6 +7,7 @@ const config: StorybookConfig = {
"@storybook/addon-essentials", "@storybook/addon-essentials",
"@storybook/addon-onboarding", "@storybook/addon-onboarding",
"@storybook/addon-interactions", "@storybook/addon-interactions",
"@storybook/addon-styling-webpack"
], ],
framework: { framework: {
name: "@storybook/react-vite", name: "@storybook/react-vite",

View File

@@ -1,4 +1,5 @@
import type { Preview } from "@storybook/react"; import type { Preview } from "@storybook/react";
import "../app/global.css";
const preview: Preview = { const preview: Preview = {
parameters: { parameters: {

View File

@@ -0,0 +1,60 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 20 14.3% 4.1%;
--card: 0 0% 100%;
--card-foreground: 20 14.3% 4.1%;
--popover: 0 0% 100%;
--popover-foreground: 20 14.3% 4.1%;
--primary: 24.6 95% 53.1%;
--primary-foreground: 60 9.1% 97.8%;
--secondary: 60 4.8% 95.9%;
--secondary-foreground: 24 9.8% 10%;
--muted: 60 4.8% 95.9%;
--muted-foreground: 25 5.3% 44.7%;
--accent: 60 4.8% 95.9%;
--accent-foreground: 24 9.8% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 60 9.1% 97.8%;
--border: 20 5.9% 90%;
--input: 20 5.9% 90%;
--ring: 24.6 95% 53.1%;
--radius: 0.5rem;
}
.dark {
--background: 20 14.3% 4.1%;
--foreground: 60 9.1% 97.8%;
--card: 20 14.3% 4.1%;
--card-foreground: 60 9.1% 97.8%;
--popover: 20 14.3% 4.1%;
--popover-foreground: 60 9.1% 97.8%;
--primary: 20.5 90.2% 48.2%;
--primary-foreground: 60 9.1% 97.8%;
--secondary: 12 6.5% 15.1%;
--secondary-foreground: 60 9.1% 97.8%;
--muted: 12 6.5% 15.1%;
--muted-foreground: 24 5.4% 63.9%;
--accent: 12 6.5% 15.1%;
--accent-foreground: 60 9.1% 97.8%;
--destructive: 0 72.2% 50.6%;
--destructive-foreground: 60 9.1% 97.8%;
--border: 12 6.5% 15.1%;
--input: 12 6.5% 15.1%;
--ring: 20.5 90.2% 48.2%;
}
}
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

View File

@@ -0,0 +1,16 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "default",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.js",
"css": "app/global.css",
"baseColor": "slate",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -12,18 +12,32 @@
"build-storybook": "storybook build" "build-storybook": "storybook build"
}, },
"dependencies": { "dependencies": {
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dropdown-menu": "^2.0.6",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-slot": "^1.0.2",
"@tanstack/react-table": "^8.10.7",
"class-variance-authority": "^0.7.0",
"clsx": "^2.0.0",
"date-fns": "^2.30.0",
"lucide-react": "^0.292.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-dom": "^18.2.0" "react-dom": "^18.2.0",
"tailwind-merge": "^2.0.0",
"tailwindcss-animate": "^1.0.7"
}, },
"devDependencies": { "devDependencies": {
"@storybook/addon-essentials": "^7.5.2", "@storybook/addon-essentials": "7.5.3",
"@storybook/addon-interactions": "^7.5.2", "@storybook/addon-interactions": "7.5.3",
"@storybook/addon-links": "^7.5.2", "@storybook/addon-links": "7.5.3",
"@storybook/addon-onboarding": "^1.0.8", "@storybook/addon-onboarding": "1.0.8",
"@storybook/blocks": "^7.5.2", "@storybook/addon-styling-webpack": "0.0.5",
"@storybook/react": "^7.5.2", "@storybook/blocks": "7.5.3",
"@storybook/react-vite": "^7.5.2", "@storybook/react": "7.5.3",
"@storybook/testing-library": "^0.2.2", "@storybook/react-vite": "7.5.3",
"@storybook/testing-library": "0.2.2",
"@types/node": "^20.8.10",
"@types/react": "^18.2.15", "@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7", "@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
@@ -35,7 +49,7 @@
"eslint-plugin-react-refresh": "^0.4.3", "eslint-plugin-react-refresh": "^0.4.3",
"eslint-plugin-storybook": "^0.6.15", "eslint-plugin-storybook": "^0.6.15",
"postcss": "^8.4.31", "postcss": "^8.4.31",
"storybook": "^7.5.2", "storybook": "7.5.3",
"tailwindcss": "^3.3.5", "tailwindcss": "^3.3.5",
"typescript": "^5.0.2", "typescript": "^5.0.2",
"vite": "^4.4.5" "vite": "^4.4.5"

View File

@@ -1,7 +1,9 @@
import { useState } from 'react' import { useState } from 'react'
import reactLogo from './assets/react.svg' import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg' import viteLogo from '/vite.svg'
import './App.css' // IMPORT BUAT CSS SHADCN
import '../app/global.css'
import { Button } from "@/components/ui/button"
function App() { function App() {
const [count, setCount] = useState(0) const [count, setCount] = useState(0)
@@ -28,9 +30,8 @@ function App() {
<p className="read-the-docs"> <p className="read-the-docs">
Click on the Vite and React logos to learn more Click on the Vite and React logos to learn more
</p> </p>
<h1 className="text-3xl font-bold underline"> <Button>ORANGE</Button>
INI TAILWIND CSS <Button variant="destructive">DESTRUCTIVE</Button>
</h1>
</> </>
) )
} }

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Icon/cog">
<path id="Icon" fill-rule="evenodd" clip-rule="evenodd" d="M9.19148 2.53673C8.88826 1.28772 7.11194 1.28772 6.80872 2.53673C6.61285 3.34357 5.68846 3.72646 4.97943 3.29445C3.88184 2.62567 2.6258 3.88172 3.29457 4.97931C3.72659 5.68833 3.34369 6.61272 2.53685 6.8086C1.28785 7.11182 1.28785 8.88813 2.53685 9.19135C3.34369 9.38723 3.72659 10.3116 3.29457 11.0206C2.6258 12.1182 3.88184 13.3743 4.97943 12.7055C5.68846 12.2735 6.61285 12.6564 6.80872 13.4632C7.11194 14.7122 8.88826 14.7122 9.19148 13.4632C9.38735 12.6564 10.3117 12.2735 11.0208 12.7055C12.1184 13.3743 13.3744 12.1182 12.7056 11.0206C12.2736 10.3116 12.6565 9.38723 13.4633 9.19135C14.7123 8.88813 14.7123 7.11182 13.4633 6.8086C12.6565 6.61272 12.2736 5.68833 12.7056 4.97931C13.3744 3.88172 12.1184 2.62568 11.0208 3.29445C10.3117 3.72646 9.38735 3.34357 9.19148 2.53673ZM8.0001 10.4C9.32558 10.4 10.4001 9.32546 10.4001 7.99998C10.4001 6.67449 9.32558 5.59998 8.0001 5.59998C6.67461 5.59998 5.6001 6.67449 5.6001 7.99998C5.6001 9.32546 6.67461 10.4 8.0001 10.4Z" fill="#637381"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,9 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Icon/dots-vertical">
<g id="Icon">
<path d="M7.9999 4.79998C7.11625 4.79998 6.3999 4.08363 6.3999 3.19998C6.3999 2.31632 7.11625 1.59998 7.9999 1.59998C8.88356 1.59998 9.5999 2.31632 9.5999 3.19998C9.5999 4.08363 8.88356 4.79998 7.9999 4.79998Z" fill="#424242"/>
<path d="M7.9999 9.59998C7.11625 9.59998 6.3999 8.88363 6.3999 7.99998C6.3999 7.11632 7.11625 6.39998 7.9999 6.39998C8.88356 6.39998 9.5999 7.11632 9.5999 7.99998C9.5999 8.88363 8.88356 9.59998 7.9999 9.59998Z" fill="#424242"/>
<path d="M7.9999 14.4C7.11625 14.4 6.3999 13.6836 6.3999 12.8C6.3999 11.9163 7.11625 11.2 7.9999 11.2C8.88356 11.2 9.5999 11.9163 9.5999 12.8C9.5999 13.6836 8.88356 14.4 7.9999 14.4Z" fill="#424242"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 812 B

View File

@@ -0,0 +1,89 @@
import '../../../../app/global.css'
import {
Card,
CardContent,
CardHeader,
CardTitle,
} from "@/components/ui/card"
import { Rs232PropertyView } from './Rs232PropertyView';
import { IpClientPropertyView } from './IpClientPropertyView';
import { IpServerPropertyView } from './IpServerPropertyView';
import { RowIndicatorv1 } from './RowIndicatorv1';
import { IpClientType, IpServerType, Rs232Type, UdpClientType, UdpServerType, } from '../models/InstrumentModel';
interface CardProps {
titleAlat?: string,
type?: string,
lampu?: boolean,
online?: boolean,
typeDetail: Rs232Type | IpClientType | IpServerType | UdpClientType | UdpServerType
onClick?: () => void;
}
/**
* Primary UI component for user interaction
*/
export const CardInstrument = ({
...props
}: CardProps) => {
return (
<>
<Card className="w-60 mx-auto rounded-lg overflow-hidden border-black border-solid">
<CardHeader className='bg-orange-500'>
<CardTitle>
<div className='flex justify-between'>
<div className='mx-2'>
<span className='text-white font-inter font-semibold text-base'>{props.titleAlat}
</span>
</div>
<div>
<svg
className='mt-2'
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.19148 2.53673C8.88826 1.28772 7.11194 1.28772 6.80872 2.53673C6.61285 3.34357 5.68846 3.72646 4.97943 3.29445C3.88184 2.62567 2.6258 3.88172 3.29457 4.97931C3.72659 5.68833 3.34369 6.61272 2.53685 6.8086C1.28785 7.11182 1.28785 8.88813 2.53685 9.19135C3.34369 9.38723 3.72659 10.3116 3.29457 11.0206C2.6258 12.1182 3.88184 13.3743 4.97943 12.7055C5.68846 12.2735 6.61285 12.6564 6.80872 13.4632C7.11194 14.7122 8.88826 14.7122 9.19148 13.4632C9.38735 12.6564 10.3117 12.2735 11.0208 12.7055C12.1184 13.3743 13.3744 12.1182 12.7056 11.0206C12.2736 10.3116 12.6565 9.38723 13.4633 9.19135C14.7123 8.88813 14.7123 7.11182 13.4633 6.8086C12.6565 6.61272 12.2736 5.68833 12.7056 4.97931C13.3744 3.88172 12.1184 2.62568 11.0208 3.29445C10.3117 3.72646 9.38735 3.34357 9.19148 2.53673ZM8.0001 10.4C9.32558 10.4 10.4001 9.32546 10.4001 7.99998C10.4001 6.67449 9.32558 5.59998 8.0001 5.59998C6.67461 5.59998 5.6001 6.67449 5.6001 7.99998C5.6001 9.32546 6.67461 10.4 8.0001 10.4Z" fill="#F5F5F5" />
</svg>
</div>
</div>
</CardTitle>
</CardHeader>
<CardContent>
{/* ROW 1 & 2 START */}
<RowIndicatorv1
lampu={props.lampu}
type={props.type}
online={props.online}
blink={false}
/>
{/* ROW 1 & 2 END */}
{/* ROW 3 */}
{
props.type == 'rs232' ? (<Rs232PropertyView
type={props.type}
valueSpeed={(props.typeDetail as Rs232Type).speedValue}
valueBaud='8'
valueDataBit={(props.typeDetail as Rs232Type).dataBitValue}
valueStopBit={(props.typeDetail as Rs232Type).stopBitValue}
/>) : ''
}
{
props.type == 'ipclient' ? (<IpClientPropertyView
type={props.type}
valueHost={(props.typeDetail as IpClientType).hostValue}
valuePort={(props.typeDetail as IpClientType).portValue}
/>) : ''
}
{
props.type == 'ipserver' ? (<IpServerPropertyView
type={props.type}
valueListeningPort={(props.typeDetail as IpServerType).listeningPortValue}
/>) : ''
}
</CardContent>
</Card>
</>
);
};

View File

@@ -0,0 +1,28 @@
import '../../../../app/global.css'
import { RowLabelValue } from './RowLabelValue';
interface IpClientPropertyViewProps {
type?: string,
valueHost:string,
valuePort:string,
onClick?: () => void;
}
export const IpClientPropertyView = ({
...props
}: IpClientPropertyViewProps) => {
return (
<>
{/* IpClient START */}
<RowLabelValue
label='Host'
value={props.valueHost}
/>
<RowLabelValue
label='Port'
value={props.valuePort}
/>
{/* IpClient END */}
</>
);
};

View File

@@ -0,0 +1,23 @@
import '../../../../app/global.css'
import { RowLabelValue } from './RowLabelValue';
interface IpServerPropertyViewProps {
type?: string,
valueListeningPort:string,
onClick?: () => void;
}
export const IpServerPropertyView = ({
...props
}: IpServerPropertyViewProps) => {
return (
<>
{/* IpServer START */}
<RowLabelValue
label='Listening Port'
value={props.valueListeningPort}
/>
{/* IpServer END */}
</>
);
};

View File

@@ -0,0 +1,43 @@
import '../../../../app/global.css'
import { StatusTransferv1 } from './StatusTransferv1';
import { StatusOnlinev1 } from './StatusOnlinev1';
import { TypeCardv1 } from './TypeCardv1';
interface RowIndicatorv1Props {
lampu?: boolean,
type?: string;
online?: boolean;
blink?:boolean;
onClick?: () => void;
}
/**
* Primary UI component for user interaction
*/
export const RowIndicatorv1 = ({
...props
}: RowIndicatorv1Props) => {
return (
<>
<div className='flex justify-between mt-2 mb-3'>
{/* LAMP START */}
<StatusTransferv1
isTransferCard={props.lampu}
/>
{/* LAMP END */}
{/* Type Badge START*/}
<TypeCardv1
titleType={props.type}
/>
{/* Type Badge END */}
{/* ONLINE / OFFLINE START */}
<StatusOnlinev1
isOnlineCard={props.online}
/>
{/* ONLINE / OFFLINE END */}
</div>
</>
);
};

View File

@@ -0,0 +1,29 @@
import '../../../../app/global.css'
interface RowLabelValueProps {
label: string;
value: string;
onClick?: () => void;
}
/**
* Primary UI component for user interaction
*/
export const RowLabelValue = ({
...props
}: RowLabelValueProps) => {
return (
<>
<div className="grid grid-cols-2 gap-4">
<div>
<span className="text-inter text-sm font-normal">
{props.label}
</span>
</div>
<div>
<span className="text-inter text-sm font-normal text-left">{props.value}</span>
</div>
</div>
</>
);
};

View File

@@ -0,0 +1,44 @@
import '../../../../app/global.css'
import { RowLabelValue } from './RowLabelValue';
interface Rs232PropertyViewProps {
type?: string,
valueSpeed:string,
valueBaud:string,
valueDataBit:string,
valueStopBit:string
onClick?: () => void;
}
export const Rs232PropertyView = ({
...props
}: Rs232PropertyViewProps) => {
return (
<>
{/* RS232 START */}
<RowLabelValue
label='Speed'
value={props.valueSpeed}
/>
<RowLabelValue
label='Baud'
value={props.valueBaud}
/>
<RowLabelValue
label='Data Bit'
value={props.valueDataBit}
/>
<RowLabelValue
label='Stop Bit'
value={props.valueStopBit}
/>
{/* RS232 END */}
</>
);
};

View File

@@ -0,0 +1,34 @@
import '../../../../app/global.css'
import { StatusTransferv1 } from './StatusTransferv1';
import { StatusOnlinev1 } from './StatusOnlinev1';
interface StatusCardProps {
isOnline?: boolean;
isTransferCard?:boolean;
onClick?: () => void;
}
/**
* Primary UI component for user interaction
*/
export const StatusCardv1 = ({
...props
}: StatusCardProps) => {
return (
<>
<div className='flex justify-between mt-2 mb-2'>
{/* LAMP START */}
<StatusTransferv1
isTransferCard={props.isTransferCard}
/>
{/* LAMP END */}
{/* ONLINE / OFFLINE START */}
<StatusOnlinev1
isOnlineCard={props.isOnline}
/>
{/* ONLINE / OFFLINE END */}
</div>
</>
);
};

View File

@@ -0,0 +1,44 @@
import '../../../../app/global.css'
interface StatusOnlinev1Props {
isOnlineCard?: boolean,
onClick?: () => void;
}
/**
* Primary UI component for user interaction
*/
export const StatusOnlinev1 = ({
...props
}: StatusOnlinev1Props) => {
return (
<>
{/* ONLINE/OFFLINE START */}
{
props.isOnlineCard == true
? (
<>
<div>
</div>
<div className='flex justify-between'>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M8.25 15C12.116 15 15.25 11.866 15.25 8C15.25 4.13401 12.116 1 8.25 1C4.38401 1 1.25 4.13401 1.25 8C1.25 11.866 4.38401 15 8.25 15Z" fill="#1B9828" />
</svg>
</div>
</>
)
: <>
<div>
</div>
<div className='flex justify-between'>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M8.25 15C12.116 15 15.25 11.866 15.25 8C15.25 4.13401 12.116 1 8.25 1C4.38401 1 1.25 4.13401 1.25 8C1.25 11.866 4.38401 15 8.25 15Z" fill="#BA1A1A" />
</svg>
</div>
</>
}
{/* ONLINE/OFFLINE END */}
</>
);
};

View File

@@ -0,0 +1,41 @@
import '../../../../app/global.css'
interface StatusTransferv1Props {
isTransferCard?: boolean,
onClick?: () => void;
}
/**
* Primary UI component for user interaction
*/
export const StatusTransferv1 = ({
...props
}: StatusTransferv1Props) => {
return (
<>
{/* TRANSFER CARD START */}
{
props.isTransferCard == true
? (
<>
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="none">
<g clip-path="url(#clip0_39_14671)">
<path d="M2.66658 7.33337C2.8365 7.33356 2.99993 7.39863 3.12349 7.51527C3.24705 7.63192 3.3214 7.79134 3.33136 7.96097C3.34132 8.1306 3.28613 8.29763 3.17707 8.42793C3.06801 8.55823 2.91331 8.64197 2.74458 8.66204L2.66658 8.66671H1.99991C1.82999 8.66652 1.66656 8.60145 1.543 8.48481C1.41944 8.36816 1.34509 8.20874 1.33513 8.03911C1.32517 7.86948 1.38036 7.70245 1.48942 7.57215C1.59848 7.44185 1.75318 7.35811 1.92191 7.33804L1.99991 7.33337H2.66658ZM7.99991 1.33337C8.1632 1.3334 8.3208 1.39334 8.44283 1.50185C8.56485 1.61036 8.64281 1.75987 8.66191 1.92204L8.66658 2.00004V2.66671C8.66639 2.83663 8.60133 3.00006 8.48468 3.12362C8.36803 3.24718 8.20861 3.32153 8.03898 3.33149C7.86935 3.34145 7.70233 3.28626 7.57202 3.1772C7.44172 3.06814 7.35798 2.91344 7.33791 2.74471L7.33325 2.66671V2.00004C7.33325 1.82323 7.40348 1.65366 7.52851 1.52864C7.65353 1.40361 7.8231 1.33337 7.99991 1.33337ZM13.9999 7.33337C14.1698 7.33356 14.3333 7.39863 14.4568 7.51527C14.5804 7.63192 14.6547 7.79134 14.6647 7.96097C14.6747 8.1306 14.6195 8.29763 14.5104 8.42793C14.4013 8.55823 14.2466 8.64197 14.0779 8.66204L13.9999 8.66671H13.3332C13.1633 8.66652 12.9999 8.60145 12.8763 8.48481C12.7528 8.36816 12.6784 8.20874 12.6685 8.03911C12.6585 7.86948 12.7137 7.70245 12.8228 7.57215C12.9318 7.44185 13.0865 7.35811 13.2552 7.33804L13.3332 7.33337H13.9999ZM3.26191 3.26204C3.37671 3.14726 3.52944 3.0783 3.69146 3.06811C3.85348 3.05793 4.01364 3.10721 4.14191 3.20671L4.20458 3.26204L4.67125 3.72871C4.79081 3.84868 4.86023 4.00966 4.8654 4.17896C4.87057 4.34826 4.8111 4.51318 4.69908 4.64023C4.58706 4.76727 4.43088 4.84691 4.26226 4.86297C4.09365 4.87904 3.92524 4.83032 3.79125 4.72671L3.72858 4.67137L3.26191 4.20471C3.13693 4.07969 3.06672 3.91015 3.06672 3.73337C3.06672 3.5566 3.13693 3.38706 3.26191 3.26204ZM11.7952 3.26204C11.9152 3.14248 12.0762 3.07306 12.2455 3.06789C12.4148 3.06272 12.5797 3.12218 12.7068 3.23421C12.8338 3.34623 12.9135 3.50241 12.9295 3.67102C12.9456 3.83964 12.8969 4.00805 12.7932 4.14204L12.7379 4.20471L12.2712 4.67137C12.1513 4.79094 11.9903 4.86036 11.821 4.86553C11.6517 4.8707 11.4868 4.81123 11.3597 4.69921C11.2327 4.58719 11.153 4.43101 11.137 4.26239C11.1209 4.09378 11.1696 3.92537 11.2732 3.79137L11.3286 3.72871L11.7952 3.26204ZM9.33325 12C9.51006 12 9.67963 12.0703 9.80465 12.1953C9.92967 12.3203 9.99991 12.4899 9.99991 12.6667C9.99991 13.1971 9.7892 13.7058 9.41413 14.0809C9.03905 14.456 8.53035 14.6667 7.99991 14.6667C7.46948 14.6667 6.96077 14.456 6.5857 14.0809C6.21063 13.7058 5.99991 13.1971 5.99991 12.6667C5.99993 12.5034 6.05988 12.3458 6.16839 12.2238C6.2769 12.1018 6.42641 12.0238 6.58858 12.0047L6.66658 12H9.33325ZM7.99991 4.00004C8.83944 4.00004 9.65769 4.26419 10.3388 4.75507C11.0198 5.24595 11.5292 5.93868 11.7946 6.73513C12.0601 7.53158 12.0683 8.39137 11.818 9.19271C11.5676 9.99405 11.0715 10.6963 10.3999 11.2C10.308 11.2691 10.1999 11.3132 10.0859 11.328L9.99991 11.3334H5.99991C5.85567 11.3334 5.71531 11.2866 5.59991 11.2C4.92829 10.6963 4.43218 9.99405 4.18186 9.19271C3.93154 8.39137 3.9397 7.53158 4.20518 6.73513C4.47066 5.93868 4.98001 5.24595 5.66107 4.75507C6.34213 4.26419 7.16038 4.00004 7.99991 4.00004Z" fill="#FFBC11" />
</g>
<defs>
<clipPath id="clip0_39_14671">
<rect width="16" height="16" fill="white" />
</clipPath>
</defs>
</svg>
</div>
</>
)
: <div></div>
}
{/* TRANSFER CARD END */}
</>
);
};

View File

@@ -0,0 +1,21 @@
import '../../../../app/global.css'
interface TypeCardv1Props {
titleType?: string;
onClick?: () => void;
}
/**
* Primary UI component for user interaction
*/
export const TypeCardv1 = ({
...props
}: TypeCardv1Props) => {
return (
<>
<span className="inline-block mb-2 bg-teal-400 bg-opacity-25 text-teal-400 px-2 py-1 rounded-md text-center font-public-sans text-xs font-bold">
{props.titleType}
</span>
</>
);
};

View File

@@ -0,0 +1,74 @@
[
{
"idInstrument":"1",
"namaInstrument":"Mindray BC800",
"type":"rs232",
"instrumentTypeDetail":[
{
"label":"speed",
"value":"800"
},
{
"label":"baudRate",
"value":"8"
},
{
"label":"dataBit",
"value":"N"
},
{
"label":"stopBit",
"value":"1"
}
]
},
{
"idInstrument":"2",
"namaInstrument":"Mindray BC240",
"type":"rs232",
"instrumentTypeDetail":[
{
"label":"speed",
"value":"800"
},
{
"label":"baudRate",
"value":"8"
},
{
"label":"dataBit",
"value":"N"
},
{
"label":"stopBit",
"value":"1"
}
]
},
{
"idInstrument":"3",
"namaInstrument":"Mindray BC800",
"type":"ipclient",
"instrumentTypeDetail":[
{
"label":"host",
"value":"192.168.10.10"
},
{
"label":"port",
"value":"5001"
}
]
},
{
"idInstrument":"4",
"namaInstrument":"Mindray BC240",
"type":"ipserver",
"instrumentTypeDetail":[
{
"label":"listeningPort",
"value":"8001"
}
]
}
]

View File

@@ -0,0 +1,44 @@
import '../../../../app/global.css'
import { CardInstrument } from '../cardInstrument/CardInstrument';
import { InstrumentType } from '../models/InstrumentModel';
interface InstrumentBoxProps {
totalCard?: number;
dataInstrumentType: InstrumentType[];
onClick?: () => void;
}
/**
* Primary UI component for user interaction
*/
export const InstrumentBox = ({
...props
}: InstrumentBoxProps) => {
let col = 2;
let showData = [];
if (props.totalCard != undefined && props.totalCard > 0) {
for (let index = 0; index < props.totalCard; index++) {
showData.push([
<CardInstrument
lampu={true}
online={true}
titleAlat={props.dataInstrumentType[index].title}
type={props.dataInstrumentType[index].type}
typeDetail={props.dataInstrumentType[index].data}
/>
]);
}
}
return (
<>
<div className={`grid grid-cols-${col} gap-10`}>
{ showData }
</div>
</>
);
};

View File

@@ -0,0 +1,24 @@
import { ColumnDef } from "@tanstack/react-table";
export type PortServerData = {
id : string;
info : string;
date : Date;
type : 'status' | 'result' | 'query';
}
export type HeaderTableProps = {
data: PortServerData[];
columns: ColumnDef<PortServerData>[];
}
export type DropDownComponentProps = {
label: string ;
type : string ;
}
export type TableBodyProps = {
data: PortServerData[]; // Sesuaikan dengan tipe data sebenarnya
columns: ColumnDef<PortServerData>[]; // Sesuaikan dengan tipe data sebenarnya
}

View File

@@ -0,0 +1,43 @@
// export type InstrumentTypeDetail = {
// label: string;
// value: string;
// };
// export type InstrumentModel = {
// idInstrument: string;
// namaInstrument: string;
// type:string;
// instrumentTypeDetail: InstrumentTypeDetail[]
// };
export type Rs232Type = {
speedValue: string,
dataBitValue: string,
parityValue: string,
stopBitValue: string,
};
export type IpClientType = {
hostValue: string,
portValue: string,
};
export type IpServerType = {
listeningPortValue: string,
};
export type UdpClientType = {
hostValue: string,
portValue: string,
};
export type UdpServerType = {
listeningPortValue: string,
};
export type InstrumentType = {
engine: string,
type: string,
title: string,
data: Rs232Type | IpClientType | IpServerType | UdpClientType | UdpServerType
};

View File

@@ -0,0 +1,33 @@
import { Meta, StoryObj } from "@storybook/react";
import { PortServerData } from "@/components/main/model/TableModel";
import { TableBodyComponent } from "../tableComponent/BodyTableComponent";
import { columns } from "../tableComponent/columns";
const data:PortServerData[] = [
{ id: "1", info: "Info 1", date: new Date("2023-10-30 15:26:04"), type: 'status' },
{ id: "2", info: "Info 2", date: new Date("2023-10-30 15:26:04"), type: 'result' },
{ id: "3", info: "Info 3", date: new Date("2023-10-30 15:26:04"), type: 'query' }
];
const meta = {
title: 'Component/Table/Body',
component: TableBodyComponent,
args: {
data: data,
columns: columns,
},
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
} satisfies Meta<typeof TableBodyComponent>
export default meta;
type Story = StoryObj<typeof meta>
export const PortServerBodyTables = (args: Story ) => {
return (
<TableBodyComponent data={data} columns={columns} {...args} />
)
}

View File

@@ -0,0 +1,33 @@
import { Meta, StoryObj} from "@storybook/react";
import { DataTableDemo, columns, data } from "../tableComponent/DataTable";
import DataTable from "../tableComponent/newDataTable";
const meta = {
title: 'Component/Table',
component: DataTableDemo,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
args: {
data: data,
columns: columns,
},
argTypes: {
},
} satisfies Meta<typeof DataTableDemo>
export default meta;
type Story = StoryObj<typeof meta>
export const Datable = (args:Story) => {
return(
<DataTableDemo data={data} columns={columns} {...args} />
)
}
export const DataTable2 = (args: Story) => {
return (
<DataTable data={data} columns={columns} {...args}/>
)
}

View File

@@ -0,0 +1,66 @@
import { Meta, StoryObj } from '@storybook/react';
import { DropDownMenuComponent } from '../tableComponent/DropDownMenuComponent';
const meta = {
title: 'Component/Table/DropdownOption',
component: DropDownMenuComponent,
argTypes:{
label: {
options: ["cog", "dot",],
control: { type: 'radio' },
},
type: {
options: ['status','query','result','head'],
control: {type: 'radio'},
},
},
tags: ['autodocs'],
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
} satisfies Meta<typeof DropDownMenuComponent>;
export default meta
type Story = StoryObj<typeof meta>
export const CogDropDown = () => {
return(
<DropDownMenuComponent
label= "cog"
type= "head"
/>
)
}
export const DotDropDownStatus = (args: Story) => {
return(
<DropDownMenuComponent
label= "dot"
type= "status"
{...args}
/>
)
}
export const DotDropDownQuery = (args: Story) => {
return(
<DropDownMenuComponent
label= "dot"
type= "query"
{...args}
/>
)
}
export const DotDropDownResult = (args: Story) => {
return(
<DropDownMenuComponent
label= "dot"
type= "result"
{...args}
/>
)
}

View File

@@ -0,0 +1,34 @@
import { Meta, StoryObj } from "@storybook/react";
import { PortServerData } from "@/components/main/model/TableModel";
import { TableHeaderComponent } from "../tableComponent/HeaderTableComponent";
import { columns } from "../tableComponent/columns";
const data:PortServerData[] = [
{ id: "1", info: "Info 1", date: new Date("2023-10-30 15:26:04"), type: 'status' },
{ id: "2", info: "Info 2", date: new Date("2023-10-30 15:26:04"), type: 'result' },
{ id: "3", info: "Info 3", date: new Date("2023-10-30 15:26:04"), type: 'query' }
];
const meta = {
title: 'Component/Table/Header',
component: TableHeaderComponent,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
args: {
data: data,
columns: columns
}
} satisfies Meta<typeof TableHeaderComponent>
export default meta;
type Story = StoryObj<typeof meta>
export const PortServerHeadTables = (args: Story) => {
return (
<TableHeaderComponent data={data} columns={columns} {...args}/>
)
}

View File

@@ -0,0 +1,35 @@
import { Meta, StoryObj } from "@storybook/react";
import { Icon } from "../tableComponent/IconComponent";
const meta = {
title: 'Component/Table/Icon',
component: Icon,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
tags: ['autodocs'],
argTypes: {
type: {
options: ['cog', 'dot'],
control: { type: 'radio' },
},
},
} satisfies Meta<typeof Icon>
export default meta;
type Story = StoryObj<typeof meta>
export const CogIcon = (args:Story) => {
return (
<Icon type='cog' {...args} />
)
}
export const DotIcon = (args:Story) => {
return (
<Icon type='dot' {...args} />
)
}

View File

@@ -0,0 +1,43 @@
import { TableBody, TableRow, TableCell } from '@/components/ui/table';
import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
import { TableBodyProps } from '@/components/main/model/TableModel';
export const TableBodyComponent = ({ data, columns }:TableBodyProps) => {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
})
return (
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)
}
</TableBody>
)
};

View File

@@ -0,0 +1,250 @@
"use client"
import * as React from "react"
import {
ColumnDef,
ColumnFiltersState,
SortingState,
VisibilityState,
flexRender,
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table"
import { DateDisplay } from "./DateDisplay"
import { CogIcon, DotIcon } from "../stories/Icon.stories"
import "../../../../app/global.css"
export const data: PortServer[] = [
{
id: "m5gr84i9",
info: "800 Cobas Status",
date: new Date("2023-10-30 15:26:04"),
type: "status",
},
{
id: "3u1reuv4",
info: "Incoming 800 Cobas Result",
date: new Date("2023-10-30 15:26:04"),
type: "result",
},
{
id: "derv1ws0",
info: "Incoming 800 Cobas Query",
date: new Date("2023-10-30 15:26:04"),
type: "query",
}
]
export type PortServer = {
id: string
info: string
date: Date
type : 'status' | 'result' | 'query'
}
export const columns: ColumnDef<PortServer>[] = [
{
accessorKey: "date",
header: "Date",
cell: ({ row }) => {
const date = new Date(row.getValue("date"))
return(
<div className="text-[#637381] bg-[#919EAB29] rounded-md border-4 border-[#919EAB29]">
<DateDisplay date={date}/>
</div>
)
}
},
{
accessorKey: "info",
header: "Info",
cell: ({ row }) => (
<div className="capitalize">{row.getValue("info")}</div>
),
},
{
id: "actions",
header:() => {
return(
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<CogIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" >
<DropdownMenuItem
onClick={() => {}}
>
<span>Change Password</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
},
enableHiding: false,
cell: ({ row }) => {
const type = row.original
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
<DotIcon />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{
type.type?.toLowerCase() == 'status' ? (
<DropdownMenuItem
onClick={() => {}}
>
Info
</DropdownMenuItem>
) : ''
}
{
type.type?.toLowerCase() == 'result' ? (
<>
<DropdownMenuItem onClick={() => {}} >
Raw Data
</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}}>
Result
</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}}>
Export
</DropdownMenuItem>
</>
) : ''
}
{
type.type?.toLowerCase() == 'query' ? (
<>
<DropdownMenuItem onClick={() => {}}>
Raw Data
</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}}>
Query Response
</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}}>
Export
</DropdownMenuItem>
</>
) : ''
}
</DropdownMenuContent>
</DropdownMenu>
)}
},
]
export interface DataTableProps {
data: PortServer[]; // Properti untuk data tabel
columns: ColumnDef<PortServer>[];
}
export const DataTableDemo = ({
data,
columns,
}: DataTableProps) => {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
[]
)
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({})
const [rowSelection, setRowSelection] = React.useState({})
const table = useReactTable({
data,
columns,
onSortingChange: setSorting,
onColumnFiltersChange: setColumnFilters,
getCoreRowModel: getCoreRowModel(),
getPaginationRowModel: getPaginationRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
onColumnVisibilityChange: setColumnVisibility,
onRowSelectionChange: setRowSelection,
state: {
sorting,
columnFilters,
columnVisibility,
rowSelection,
},
})
return (
<div className="w-full">
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => {
return (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
header.getContext()
)}
</TableHead>
)
})}
</TableRow>
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(
cell.column.columnDef.cell,
cell.getContext()
)}
</TableCell>
))}
</TableRow>
))
) : (
<TableRow>
<TableCell
colSpan={columns.length}
className="h-24 text-center"
>
No results.
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
</div>
</div>
)
}

View File

@@ -0,0 +1,18 @@
// DateDisplay.tsx
interface DateDisplayProps {
date: Date;
}
export const DateDisplay = ({ date }: DateDisplayProps) => {
const formattedDate = new Intl.DateTimeFormat("id-ID", {
day: "2-digit",
month: "short",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}).format(date);
return <label>{formattedDate}</label>;
};

View File

@@ -0,0 +1,51 @@
import { DropDownComponentProps } from "@/components/main/model/TableModel";
import { CogIcon, DotIcon } from "../stories/Icon.stories"
import { Button } from "@/components/ui/button"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
export const DropDownMenuComponent = ({label, type}:DropDownComponentProps) => {
return (
<>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="h-8 w-8 p-0">
{label.toLowerCase() === 'cog' && (
<CogIcon />
)}
{label.toLowerCase() === 'dot' && (
<DotIcon />
)}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{type.toLowerCase() === 'status' && (
<DropdownMenuItem
onClick={() => {}}
>
Info
</DropdownMenuItem>
)}
{type.toLowerCase() === 'result' && (
<>
<DropdownMenuItem onClick={() => {}} >Raw Data</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}}>Result</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}}>Export</DropdownMenuItem>
</>
)}
{type.toLowerCase() === 'query' && (
<>
<DropdownMenuItem onClick={() => {}}>Raw Data</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}}>Query Response</DropdownMenuItem>
<DropdownMenuItem onClick={() => {}}>Export</DropdownMenuItem>
</>
)}
{type.toLowerCase() === 'head' && (
<DropdownMenuItem onClick={() => {}}>Change Password</DropdownMenuItem>
)}
</DropdownMenuContent>
</DropdownMenu>
</>
);
};

View File

@@ -0,0 +1,31 @@
import { HeaderTableProps } from "@/components/main/model/TableModel";
import { TableHeader, TableRow, TableHead } from "@/components/ui/table";
import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
export const TableHeaderComponent = ({ data, columns }:HeaderTableProps) => {
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
})
return (
<TableHeader>
{table.getHeaderGroups().map((headerGroup: any) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header: any) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(
header.column.columnDef.header,
typeof header.getContext === 'function' ? header.getContext() : {}
)}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
)
};

View File

@@ -0,0 +1,16 @@
import cog from "@/assets/cog.svg"
import dot from "@/assets/dots-vertical.svg"
interface IconProps {
type ?: "cog" | "dot";
}
export const Icon = ({
...props
}:IconProps) => {
return(
<img
src={props.type?.toLowerCase() === 'cog' ? cog : props.type?.toLowerCase() === 'dot' ? dot : '' }
/>
)
}

View File

@@ -0,0 +1,41 @@
import { PortServerData } from "@/components/main/model/TableModel"
import { ColumnDef } from "@tanstack/react-table"
import { DateDisplay } from "./DateDisplay"
import { CogDropDown } from "../stories/DropDownMenu.stories"
import { DropDownMenuComponent } from "./DropDownMenuComponent"
export const columns: ColumnDef<PortServerData>[] = [
{
accessorKey: "date",
header: "Date",
cell: ({ row }) => {
const date = new Date(row.getValue("date"))
return(
<div className="text-[#637381] bg-[#919EAB29] rounded-md border-4 border-[#919EAB29]">
<DateDisplay date={date}/>
</div>
)
}
},
{
accessorKey: "info",
header: "Info",
cell: ({ row }) => (
<div className="capitalize">{row.getValue("info")}</div>
),
},
{
id: "actions",
header:() => {
return(
<CogDropDown />
)
},
enableHiding: false,
cell: ({ row }) => {
const type = row.original
return (
<DropDownMenuComponent label="dot" type={type.type}/>
)}
},
]

View File

@@ -0,0 +1,26 @@
import { Table} from "@/components/ui/table";
import { TableBodyComponent } from "./BodyTableComponent";
import { TableHeaderComponent } from "./HeaderTableComponent";
import { PortServerData } from "@/components/main/model/TableModel";
import { ColumnDef } from "@tanstack/react-table";
interface DataTableprops {
data: PortServerData[];
columns: ColumnDef<PortServerData>[];
}
const DataTable = ({data, columns }:DataTableprops) => {
return (
<div className="w-full">
<div className="rounded-md border">
<Table>
<TableHeaderComponent data={data} columns={columns} />
<TableBodyComponent data={data} columns={columns} />
</Table>
</div>
</div>
);
};
export default DataTable;

View File

@@ -0,0 +1,36 @@
import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const badgeVariants = cva(
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
{
variants: {
variant: {
default:
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
secondary:
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
destructive:
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
outline: "text-foreground",
},
},
defaultVariants: {
variant: "default",
},
}
)
export interface BadgeProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof badgeVariants> {}
function Badge({ className, variant, ...props }: BadgeProps) {
return (
<div className={cn(badgeVariants({ variant }), className)} {...props} />
)
}
export { Badge, badgeVariants }

View File

@@ -0,0 +1,56 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button, buttonVariants }

View File

@@ -0,0 +1,79 @@
import * as React from "react"
import { cn } from "@/lib/utils"
const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-lg border bg-card text-card-foreground shadow-sm",
className
)}
{...props}
/>
))
Card.displayName = "Card"
const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
))
CardHeader.displayName = "CardHeader"
const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn(
"text-2xl font-semibold leading-none tracking-tight",
className
)}
{...props}
/>
))
CardTitle.displayName = "CardTitle"
const CardDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
CardDescription.displayName = "CardDescription"
const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
))
CardContent.displayName = "CardContent"
const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
))
CardFooter.displayName = "CardFooter"
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }

View File

@@ -0,0 +1,198 @@
import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import { Check, ChevronRight, Circle } from "lucide-react"
import { cn } from "@/lib/utils"
const DropdownMenu = DropdownMenuPrimitive.Root
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
const DropdownMenuGroup = DropdownMenuPrimitive.Group
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
const DropdownMenuSub = DropdownMenuPrimitive.Sub
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean
}
>(({ className, inset, children, ...props }, ref) => (
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
inset && "pl-8",
className
)}
{...props}
>
{children}
<ChevronRight className="ml-auto h-4 w-4" />
</DropdownMenuPrimitive.SubTrigger>
))
DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.displayName
const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
/>
))
DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.displayName
const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
))
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className
)}
{...props}
/>
))
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => (
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
checked={checked}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
))
DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.displayName
const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
))
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Label
ref={ref}
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className
)}
{...props}
/>
))
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
))
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
const DropdownMenuShortcut = ({
className,
...props
}: React.HTMLAttributes<HTMLSpanElement>) => {
return (
<span
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
{...props}
/>
)
}
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
export {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuGroup,
DropdownMenuPortal,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
}

View File

@@ -0,0 +1,24 @@
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const labelVariants = cva(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)
const Label = React.forwardRef<
React.ElementRef<typeof LabelPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
VariantProps<typeof labelVariants>
>(({ className, ...props }, ref) => (
<LabelPrimitive.Root
ref={ref}
className={cn(labelVariants(), className)}
{...props}
/>
))
Label.displayName = LabelPrimitive.Root.displayName
export { Label }

View File

@@ -0,0 +1,114 @@
import * as React from "react"
import { cn } from "@/lib/utils"
const Table = React.forwardRef<
HTMLTableElement,
React.HTMLAttributes<HTMLTableElement>
>(({ className, ...props }, ref) => (
<div className="relative w-full overflow-auto">
<table
ref={ref}
className={cn("w-full caption-bottom text-sm", className)}
{...props}
/>
</div>
))
Table.displayName = "Table"
const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
))
TableHeader.displayName = "TableHeader"
const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tbody
ref={ref}
className={cn("[&_tr:last-child]:border-0", className)}
{...props}
/>
))
TableBody.displayName = "TableBody"
const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(({ className, ...props }, ref) => (
<tfoot
ref={ref}
className={cn("bg-primary font-medium text-primary-foreground", className)}
{...props}
/>
))
TableFooter.displayName = "TableFooter"
const TableRow = React.forwardRef<
HTMLTableRowElement,
React.HTMLAttributes<HTMLTableRowElement>
>(({ className, ...props }, ref) => (
<tr
ref={ref}
className={cn(
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
className
)}
{...props}
/>
))
TableRow.displayName = "TableRow"
const TableHead = React.forwardRef<
HTMLTableCellElement,
React.ThHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<th
ref={ref}
className={cn(
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
className
)}
{...props}
/>
))
TableHead.displayName = "TableHead"
const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(({ className, ...props }, ref) => (
<td
ref={ref}
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
{...props}
/>
))
TableCell.displayName = "TableCell"
const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(({ className, ...props }, ref) => (
<caption
ref={ref}
className={cn("mt-4 text-sm text-muted-foreground", className)}
{...props}
/>
))
TableCaption.displayName = "TableCaption"
export {
Table,
TableHeader,
TableBody,
TableFooter,
TableHead,
TableRow,
TableCell,
TableCaption,
}

View File

@@ -1,7 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
:root { :root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5; line-height: 1.5;

View File

@@ -0,0 +1,6 @@
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

View File

@@ -2,6 +2,7 @@ import React from 'react'
import ReactDOM from 'react-dom/client' import ReactDOM from 'react-dom/client'
import App from './App.tsx' import App from './App.tsx'
import './index.css' import './index.css'
import '../app/global.css'
ReactDOM.createRoot(document.getElementById('root')!).render( ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode> <React.StrictMode>

View File

@@ -1,27 +0,0 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Header } from './Header';
const meta = {
title: 'Example/Header',
component: Header,
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
parameters: {
// More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
layout: 'fullscreen',
},
} satisfies Meta<typeof Header>;
export default meta;
type Story = StoryObj<typeof meta>;
export const LoggedIn: Story = {
args: {
user: {
name: 'Jane Doe',
},
},
};
export const LoggedOut: Story = {};

View File

@@ -1,29 +0,0 @@
import type { Meta, StoryObj } from '@storybook/react';
import { within, userEvent } from '@storybook/testing-library';
import { Page } from './Page';
const meta = {
title: 'Example/Page',
component: Page,
parameters: {
// More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
layout: 'fullscreen',
},
} satisfies Meta<typeof Page>;
export default meta;
type Story = StoryObj<typeof meta>;
export const LoggedOut: Story = {};
// More on interaction testing: https://storybook.js.org/docs/react/writing-tests/interaction-testing
export const LoggedIn: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const loginButton = await canvas.getByRole('button', {
name: /Log in/i,
});
await userEvent.click(loginButton);
},
};

View File

@@ -0,0 +1,149 @@
import type { Meta, StoryObj } from '@storybook/react';
import { CardInstrument } from '../../components/main/cardInstrument/CardInstrument';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Card',
component: CardInstrument,
parameters: {
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof CardInstrument>;
export default meta;
type Story = StoryObj<typeof meta>;
// Rs 232 Cobas Online NoTransfer
export const rs232CobasOnlineNoTransfer: Story = {
args: {
titleAlat: 'COBAS 800',
type: 'rs232',
lampu: true,
online: true,
typeDetail: {
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
};
// Rs 232 Cobas Online Transfer
export const rs232CobasOnlineTransfer: Story = {
args: {
titleAlat: 'COBAS 800',
type: 'rs232',
lampu: false,
online: true,
typeDetail: {
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
};
// Rs 232 Cobas Offline Transfer
export const rs232CobasOfflineTransfer: Story = {
args: {
titleAlat: 'COBAS 800',
type: 'rs232',
lampu: false,
online: false,
typeDetail: {
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
};
// Ipclient Mindray Online No Transfer
export const ipclientMindrayBC800OnlineNoTransfer: Story = {
args: {
titleAlat: 'Mindray BC800',
type: 'ipclient',
lampu: true,
online: true,
typeDetail: {
hostValue: "192.168.10.10",
portValue: "5001"
}
},
};
// Ipclient Mindray Online Transfer
export const ipclientMindrayBC800OnlineTransfer: Story = {
args: {
titleAlat: 'Mindray BC800',
type: 'ipclient',
lampu: false,
online: true,
typeDetail: {
hostValue: "192.168.10.10",
portValue: "5001"
}
},
};
// Ip Client Offline Transfer
export const ipclientMindrayBC800OfflineTransfer: Story = {
args: {
titleAlat: 'Mindray BC800',
type: 'ipclient',
lampu: false,
online: false,
typeDetail: {
hostValue: "192.168.10.10",
portValue: "5001"
}
},
};
// Ip Server Mindray Online No Transfer
export const ipserverMindrayBC240OnlineNoTransfer: Story = {
args: {
titleAlat: 'Mindray BC240',
type: 'ipserver',
lampu: true,
online: true,
typeDetail: {
listeningPortValue:"8001"
}
},
};
// Ip Server Mindray Online Transfer
export const ipserverMindrayBC240OnlineTransfer: Story = {
args: {
titleAlat: 'Mindray BC240',
type: 'ipserver',
lampu: false,
online: true,
typeDetail:{
listeningPortValue:"8001"
}
},
};
// Ip Server Offline Transfer
export const ipserverMindrayBC240OfflineTransfer: Story = {
args: {
titleAlat: 'Mindray BC240',
type: 'ipserver',
lampu: false,
online: false,
typeDetail:{
listeningPortValue:"8001"
}
},
};

View File

@@ -0,0 +1,28 @@
import type { Meta, StoryObj } from '@storybook/react';
import { IpClientPropertyView } from '../../components/main/cardInstrument/IpClientPropertyView';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Ipclient',
component: IpClientPropertyView,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof IpClientPropertyView>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Ipclient: Story = {
args: {
type:''
},
};

View File

@@ -0,0 +1,28 @@
import type { Meta, StoryObj } from '@storybook/react';
import { IpServerPropertyView } from '../../components/main/cardInstrument/IpServerPropertyView';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Ipserver',
component: IpServerPropertyView,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof IpServerPropertyView>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Ipclient: Story = {
args: {
type:''
},
};

View File

@@ -0,0 +1,29 @@
import type { Meta, StoryObj } from '@storybook/react';
import { RowLabelValue } from '../../components/main/cardInstrument/RowLabelValue';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Row Label Value',
component: RowLabelValue,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof RowLabelValue>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Initial: Story = {
args: {
label:'',
value:''
},
};

View File

@@ -0,0 +1,28 @@
import { RowIndicatorv1 } from '@/components/main/cardInstrument/Rowindicatorv1';
import type { Meta, StoryObj } from '@storybook/react';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Row Indicator',
component: RowIndicatorv1,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof RowIndicatorv1>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Initial: Story = {
args: {
type:''
},
};

View File

@@ -0,0 +1,28 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Rs232PropertyView } from '../../components/main/cardInstrument/Rs232PropertyView';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Rs232',
component: Rs232PropertyView,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof Rs232PropertyView>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Rs232: Story = {
args: {
type:''
},
};

View File

@@ -0,0 +1,28 @@
import { StatusCardv1 } from '@/components/main/cardInstrument/StatusCardv1';
import type { Meta, StoryObj } from '@storybook/react';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Status card',
component: StatusCardv1,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof StatusCardv1>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Initial: Story = {
args: {
isOnline:false
},
};

View File

@@ -1,11 +1,10 @@
import { StatusOnlinev1 } from '@/components/main/cardInstrument/StatusOnlinev1';
import type { Meta, StoryObj } from '@storybook/react'; import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = { const meta = {
title: 'Example/Button', title: 'Component/Main/Status Online',
component: Button, component: StatusOnlinev1,
parameters: { parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered', layout: 'centered',
@@ -14,37 +13,22 @@ const meta = {
tags: ['autodocs'], tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes // More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: { argTypes: {
backgroundColor: { control: 'color' }, // backgroundColor: { control: 'color' },
}, },
} satisfies Meta<typeof Button>; } satisfies Meta<typeof StatusOnlinev1>;
export default meta; export default meta;
type Story = StoryObj<typeof meta>; type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Primary: Story = { export const StatusOnline: Story = {
args: { args: {
primary: true, isOnlineCard:true
label: 'Button',
}, },
}; };
export const Secondary: Story = { export const StatusOffline: Story = {
args: { args: {
label: 'Button', isOnlineCard:false
},
};
export const Large: Story = {
args: {
size: 'large',
label: 'Button',
},
};
export const Small: Story = {
args: {
size: 'small',
label: 'Button',
}, },
}; };

View File

@@ -0,0 +1,34 @@
import { StatusTransferv1 } from '@/components/main/cardInstrument/StatusTransferv1';
import type { Meta, StoryObj } from '@storybook/react';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Status Transfer',
component: StatusTransferv1,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof StatusTransferv1>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const StatusTransferTrue: Story = {
args: {
isTransferCard:true
},
};
export const StatusTransferFalse: Story = {
args: {
isTransferCard:false
},
};

View File

@@ -0,0 +1,28 @@
import { TypeCardv1 } from '@/components/main/cardInstrument/TypeCardv1';
import type { Meta, StoryObj } from '@storybook/react';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Type Card',
component: TypeCardv1,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof TypeCardv1>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Initial: Story = {
args: {
titleType:''
},
};

View File

@@ -0,0 +1,162 @@
import { InstrumentBox } from '@/components/main/instrumentBox/InstrumentBox';
import type { Meta, StoryObj } from '@storybook/react';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Component/Main/Instrument Box',
component: InstrumentBox,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {
// backgroundColor: { control: 'color' },
},
} satisfies Meta<typeof InstrumentBox>;
export default meta;
type Story = StoryObj<typeof meta>;
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
// Instrument 1 Alat
export const Instrument1Alat: Story = {
args: {
totalCard:1,
dataInstrumentType:[
{
engine:'astm',
title:'Cobas800',
type:'rs232',
data:{
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
],
},
};
// Instrument 2 Alat
export const Instrument2Alat: Story = {
args: {
totalCard:2,
dataInstrumentType:[
{
engine:'astm',
title:'Cobas800',
type:'rs232',
data:{
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
{
engine:'astm',
title:'Axsym 100',
type:'rs232',
data:{
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
],
},
};
// Instrument 3 Alat
export const Instrument3Alat: Story = {
args: {
totalCard:3,
dataInstrumentType:[
{
engine:'astm',
title:'Cobas800',
type:'rs232',
data:{
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
{
engine:'astm',
title:'Axsym 100',
type:'rs232',
data:{
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
{
engine:'mindray',
title:'Mindray BC800',
type:'ipclient',
data:{
hostValue:"192.168.10.10",
portValue:"5001"
}
},
],
},
};
// Instrument 4 Alat
export const Instrument4Alat: Story = {
args: {
totalCard:4,
dataInstrumentType:[
{
engine:'astm',
title:'Cobas800',
type:'rs232',
data:{
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
{
engine:'astm',
title:'Axsym 100',
type:'rs232',
data:{
speedValue: '800',
dataBitValue: 'N',
parityValue: '',
stopBitValue: '1'
}
},
{
engine:'mindray',
title:'Mindray BC800',
type:'ipclient',
data:{
hostValue:"192.168.10.10",
portValue:"5001"
}
},
{
engine:'mindray',
title:'Mindray BC240',
type:'ipserver',
data:{
listeningPortValue:"8001"
}
},
],
},
};

View File

@@ -1,12 +1,76 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
export default { module.exports = {
darkMode: ["class"],
content: [ content: [
"./index.html", './pages/**/*.{ts,tsx}',
"./src/**/*.{js,ts,jsx,tsx}", './components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./src/**/*.{ts,tsx}',
], ],
theme: { theme: {
extend: {}, container: {
center: true,
padding: "2rem",
screens: {
"2xl": "1400px",
}, },
plugins: [], },
extend: {
colors: {
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
popover: {
DEFAULT: "hsl(var(--popover))",
foreground: "hsl(var(--popover-foreground))",
},
card: {
DEFAULT: "hsl(var(--card))",
foreground: "hsl(var(--card-foreground))",
},
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
keyframes: {
"accordion-down": {
from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
},
},
plugins: [require("tailwindcss-animate")],
} }

View File

@@ -18,7 +18,14 @@
"strict": true, "strict": true,
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"noFallthroughCasesInSwitch": true "noFallthroughCasesInSwitch": true,
"baseUrl": ".",
"paths": {
"@/*": [
"./src/*"
]
}
}, },
"include": ["src"], "include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }] "references": [{ "path": "./tsconfig.node.json" }]

View File

@@ -1,7 +1,13 @@
import path from "path"
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
}) })

File diff suppressed because it is too large Load Diff