Merge branch 'dev' of https://github.com/dikstub-rssa/simrs-fe into fe-specialist-intern-35
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Default settings for all files
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
# For Markdown files, don't trim trailing whitespace (karena kadang dipakai untuk line break)
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# For JSON, YAML, and config files
|
||||
[*.{json,yml,yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# For JS, TS, Vue files
|
||||
[*.{js,ts,vue}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
# For CSS, SCSS, PostCSS
|
||||
[*.{css,scss,pcss}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
@@ -0,0 +1 @@
|
||||
API_ORIGIN=
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"useTabs": false,
|
||||
"tabWidth": 2,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 120,
|
||||
"semi": false,
|
||||
"plugins": ["prettier-plugin-tailwindcss"]
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
# Nuxt Minimal Starter
|
||||
|
||||
Look at the [Nuxt documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||
|
||||
## Setup
|
||||
|
||||
Make sure to install dependencies:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm install
|
||||
|
||||
# pnpm
|
||||
pnpm install
|
||||
|
||||
# yarn
|
||||
yarn install
|
||||
|
||||
# bun
|
||||
bun install
|
||||
```
|
||||
|
||||
## Development Server
|
||||
|
||||
Start the development server on `http://localhost:3000`:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run dev
|
||||
|
||||
# pnpm
|
||||
pnpm dev
|
||||
|
||||
# yarn
|
||||
yarn dev
|
||||
|
||||
# bun
|
||||
bun run dev
|
||||
```
|
||||
|
||||
## Production
|
||||
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run build
|
||||
|
||||
# pnpm
|
||||
pnpm build
|
||||
|
||||
# yarn
|
||||
yarn build
|
||||
|
||||
# bun
|
||||
bun run build
|
||||
```
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
# npm
|
||||
npm run preview
|
||||
|
||||
# pnpm
|
||||
pnpm preview
|
||||
|
||||
# yarn
|
||||
yarn preview
|
||||
|
||||
# bun
|
||||
bun run preview
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||
@@ -2,4 +2,111 @@
|
||||
|
||||
RSSA - Front End
|
||||
|
||||
If you see this, the development is still not merged yet. Please check another branch.
|
||||
> [!IMPORTANT]
|
||||
> Read this following instructions before doing your job
|
||||
|
||||
## Framework Guide
|
||||
|
||||
- [Vue Style Guide](https://vuejs.org/style-guide)
|
||||
- [Nuxt Style Guide](https://nuxt.com/docs/4.x/guide)
|
||||
- [Shadcn Vue @radix-ui](https://radix.shadcn-vue.com/)
|
||||
|
||||
## Configuration
|
||||
|
||||
- `nuxt.config.ts`<br />Nuxt configuration file
|
||||
- `.env`<br />Some environment variables
|
||||
|
||||
## Directory Structure for `app/`
|
||||
|
||||
- `app.vue`: Main layout
|
||||
- `components` : Contains all reusable UI components.
|
||||
- `components/content` : Entry point for business logic and workflows. Pages or routes call these content components to handle API requests and process application logic
|
||||
- `components/app` : View-layer components that manage and present data. These are used within `content/` to render or handle specific parts of the UI, and return results back to the content
|
||||
- `components/pub` : Public/shared components used across different parts of the app.
|
||||
- `composables` : Contains reusable logic and utility functions (e.g. composables, hooks)..
|
||||
- `layouts` : Reusable UI layout patterns used across pages.
|
||||
- `models` : Contains data definitions or interfaces.
|
||||
- `schemas` : Contains JSON schemas used for validation.
|
||||
- `services` : Contains reusable API calls and business logic.
|
||||
|
||||
|
||||
## Directory Structure for `app/pages`
|
||||
|
||||
- `pages/auth` : Authentication related pages.
|
||||
- `pages/(features)` : Grouped feature modules that reflect specific business content or domains.
|
||||
|
||||
## Directory Structure for `server/`
|
||||
|
||||
- `server/api` : API or proxy requests
|
||||
|
||||
## Workflows
|
||||
|
||||
The basic development workflow follows these steps:
|
||||
|
||||
### Define Your Data in `models/`
|
||||
|
||||
- Create data definitions or interfaces.
|
||||
- These should represent the structure of the data used across your app.
|
||||
|
||||
### Build UI Components in `components/app`
|
||||
|
||||
- Create reusable UI and app specific components.
|
||||
- Keep components pure, avoid making HTTP requests directly within them.
|
||||
- They receive data via props and emit events upward.
|
||||
|
||||
### Business Logic in `components/content`
|
||||
|
||||
- This layer connects the UI with the logic (API calls, validations, navigation).
|
||||
- It composes components from `components/app/`, `components/pub/`, and other content.
|
||||
- Also responsible for managing state, side effects, and interactions.
|
||||
|
||||
### Create Pages in `pages/`
|
||||
|
||||
- Define permissions and guards for each page.
|
||||
- Pages load the appropriate content from `components/content/`.
|
||||
- They do not contain UI or logic directly, just route level layout or guards.
|
||||
|
||||
### Validation
|
||||
|
||||
- UI level validation in `components/app`. help users avoid mistakes before submitting.
|
||||
- Lightweight/instant validation related to UX.
|
||||
- Basic formatting (email regex, numeric-only, password length).
|
||||
- Showing error messages directly under the field.
|
||||
|
||||
- Business level validation in `components/flow`. cannot rely only on the UI, since it often requires server-side checks or rules that may change.
|
||||
- More complex validation rules tied to business logic.
|
||||
|
||||
## Code Conventions
|
||||
|
||||
- Under the script setup block, putting things in group with the following order:
|
||||
- Imports → all dependencies, sorted by external, alias (~), and relative imports.
|
||||
- Props & Emits → clearly define component inputs & outputs.
|
||||
- State & Computed → all ref, reactive, and computed variables grouped together.
|
||||
- Lifecycle Hooks → grouped by mounting → updating → unmounting order.
|
||||
- Functions → async first (fetching, API calls), then utility & event handlers.
|
||||
- Watchers → if needed, put them at the bottom.
|
||||
- Template → keep clean and minimal logic, use methods/computed instead of inline JS.
|
||||
- Declaration Naming
|
||||
- Uses PascalCase for `type` naming
|
||||
- Uses camelCase for `variable` and `const` naming
|
||||
- Underscore can be used to indicates that a variable has derived from an attribute of an object<br />
|
||||
for example: `person_name` indicates it is an attribute `name` from object `person`
|
||||
- Looping
|
||||
- Uses `i`, `j`, `k` as variable for `for` looping index
|
||||
- Uses `item` as object instantition for `forEach` loop callback
|
||||
- Uses `item` as object instantition for `v-for` loop callback in the template
|
||||
|
||||
## Git Workflows
|
||||
|
||||
The basic git workflow follows these steps:
|
||||
|
||||
1. Create a new branch on `dev`
|
||||
- branch name should be `feat/<feature-name>` or `fix/<bug-name>`
|
||||
2. Make your changes
|
||||
3. Commit your changes
|
||||
- commit msg format: `[type]: [description]`
|
||||
- `type` can be `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`
|
||||
- `description` should be a brief description of the changes
|
||||
- Example: `feat: add new feature`
|
||||
4. Push your changes to `dev`
|
||||
5. Create a pull request from `dev` to `main`
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
import { ConfigProvider } from 'radix-vue'
|
||||
|
||||
const useIdFunction = () => useId()
|
||||
|
||||
const textDirection = useTextDirection({ initialValue: 'ltr' })
|
||||
const dir = computed(() => (textDirection.value === 'rtl' ? 'rtl' : 'ltr'))
|
||||
|
||||
useHead({
|
||||
// as a string,
|
||||
// where `%s` is replaced with the title
|
||||
titleTemplate: '%s - RSSA',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ConfigProvider :use-id="useIdFunction" :dir="dir">
|
||||
<div vaul-drawer-wrapper class="relative">
|
||||
<NuxtLayout>
|
||||
<NuxtPage />
|
||||
</NuxtLayout>
|
||||
</div>
|
||||
|
||||
<Toaster />
|
||||
</ConfigProvider>
|
||||
</template>
|
||||
@@ -0,0 +1,340 @@
|
||||
/* SIMRS RSSA Design System - Pure CSS (No Tailwind) */
|
||||
|
||||
/* CSS Variables */
|
||||
:root {
|
||||
/* Medical Theme Colors */
|
||||
--background: 210 20% 98%;
|
||||
--foreground: 210 20% 15%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 210 20% 15%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 210 20% 15%;
|
||||
|
||||
/* Primary - Medical Green */
|
||||
--primary: 150 75% 35%;
|
||||
--primary-foreground: 0 0% 100%;
|
||||
--primary-hover: 150 75% 40%;
|
||||
|
||||
/* Secondary - Clean Blue */
|
||||
--secondary: 210 50% 96%;
|
||||
--secondary-foreground: 210 20% 20%;
|
||||
--muted: 210 25% 95%;
|
||||
--muted-foreground: 210 15% 50%;
|
||||
|
||||
/* Accent - Neutral Gray */
|
||||
--accent: 210 40% 96%;
|
||||
--accent-foreground: 222.2 84% 4.9%;
|
||||
--destructive: 0 75% 55%;
|
||||
--destructive-foreground: 0 0% 100%;
|
||||
--border: 210 20% 88%;
|
||||
--input: 210 20% 95%;
|
||||
--ring: 150 75% 35%;
|
||||
|
||||
/* Medical Status Colors */
|
||||
--success: 150 75% 40%;
|
||||
--success-foreground: 0 0% 100%;
|
||||
--warning: 45 95% 60%;
|
||||
--warning-foreground: 210 20% 15%;
|
||||
--info: 210 100% 50%;
|
||||
--info-foreground: 0 0% 100%;
|
||||
|
||||
/* Gradients */
|
||||
--gradient-primary: linear-gradient(135deg, hsl(150 75% 35%), hsl(150 75% 45%));
|
||||
--gradient-medical: linear-gradient(135deg, hsl(150 75% 35%), hsl(210 100% 50%));
|
||||
--gradient-subtle: linear-gradient(180deg, hsl(210 20% 98%), hsl(210 25% 95%));
|
||||
|
||||
/* Shadows */
|
||||
--shadow-medical: 0 4px 20px -4px hsl(150 75% 35% / 0.15);
|
||||
--shadow-card: 0 2px 10px -2px hsl(210 20% 15% / 0.1);
|
||||
--shadow-glow: 0 0 30px hsl(150 75% 35% / 0.2);
|
||||
|
||||
/* Transitions */
|
||||
--transition-smooth: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--transition-fast: all 0.15s ease-out;
|
||||
|
||||
/* Border Radius */
|
||||
--radius: 0.5rem;
|
||||
--radius-lg: var(--radius);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
|
||||
/* Sidebar */
|
||||
--sidebar-background: 0 0% 98%;
|
||||
--sidebar-foreground: 240 5.3% 26.1%;
|
||||
--sidebar-primary: 240 5.9% 10%;
|
||||
--sidebar-primary-foreground: 0 0% 98%;
|
||||
--sidebar-accent: 240 4.8% 95.9%;
|
||||
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||
--sidebar-border: 220 13% 91%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
/* .dark { */
|
||||
/* --background: 210 25% 8%; */
|
||||
/* --foreground: 210 20% 95%; */
|
||||
/* --card: 210 25% 10%; */
|
||||
/* --card-foreground: 210 20% 95%; */
|
||||
/* --popover: 210 25% 10%; */
|
||||
/* --popover-foreground: 210 20% 95%; */
|
||||
/* --primary: 150 75% 45%; */
|
||||
/* --primary-foreground: 0 0% 100%; */
|
||||
/* --primary-hover: 150 75% 50%; */
|
||||
/* --secondary: 210 25% 15%; */
|
||||
/* --secondary-foreground: 210 20% 90%; */
|
||||
/* --muted: 210 25% 15%; */
|
||||
/* --muted-foreground: 210 15% 65%; */
|
||||
/* --accent: 210 100% 55%; */
|
||||
/* --accent-foreground: 0 0% 100%; */
|
||||
/* --destructive: 0 75% 60%; */
|
||||
/* --destructive-foreground: 0 0% 100%; */
|
||||
/* --border: 210 25% 20%; */
|
||||
/* --input: 210 25% 15%; */
|
||||
/* --ring: 150 75% 45%; */
|
||||
/* --success: 150 75% 50%; */
|
||||
/* --warning: 45 95% 65%; */
|
||||
/* --info: 210 100% 60%; */
|
||||
/* --gradient-primary: linear-gradient(135deg, hsl(150 75% 45%), hsl(150 75% 55%)); */
|
||||
/* --gradient-medical: linear-gradient(135deg, hsl(150 75% 45%), hsl(210 100% 55%)); */
|
||||
/* --gradient-subtle: linear-gradient(180deg, hsl(210 25% 8%), hsl(210 25% 12%)); */
|
||||
/* --sidebar-background: 240 5.9% 10%; */
|
||||
/* --sidebar-foreground: 240 4.8% 95.9%; */
|
||||
/* --sidebar-primary: 224.3 76.3% 48%; */
|
||||
/* --sidebar-primary-foreground: 0 0% 100%; */
|
||||
/* --sidebar-accent: 240 3.7% 15.9%; */
|
||||
/* --sidebar-accent-foreground: 240 4.8% 95.9%; */
|
||||
/* --sidebar-border: 240 3.7% 15.9%; */
|
||||
/* --sidebar-ring: 217.2 91.2% 59.8%; */
|
||||
}
|
||||
|
||||
/* Keyframes for Animations */
|
||||
@keyframes accordion-down {
|
||||
from {
|
||||
height: 0;
|
||||
}
|
||||
to {
|
||||
height: var(--radix-accordion-content-height);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes accordion-up {
|
||||
from {
|
||||
height: var(--radix-accordion-content-height);
|
||||
}
|
||||
to {
|
||||
height: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translateY(100%);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulseMedical {
|
||||
0%,
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 hsl(var(--primary) / 0.4);
|
||||
}
|
||||
50% {
|
||||
box-shadow: 0 0 0 10px hsl(var(--primary) / 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Base Styles */
|
||||
* {
|
||||
border-color: hsl(var(--border));
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: hsl(var(--background));
|
||||
color: hsl(var(--foreground));
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Container */
|
||||
.container {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: 0 2rem;
|
||||
}
|
||||
|
||||
@media (min-width: 1400px) {
|
||||
.container {
|
||||
max-width: 1400px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Color Classes */
|
||||
.bg-background {
|
||||
background-color: hsl(var(--background));
|
||||
}
|
||||
.bg-foreground {
|
||||
background-color: hsl(var(--foreground));
|
||||
}
|
||||
.bg-card {
|
||||
background-color: hsl(var(--card));
|
||||
}
|
||||
.bg-primary {
|
||||
background-color: hsl(var(--primary));
|
||||
}
|
||||
.bg-secondary {
|
||||
background-color: hsl(var(--secondary));
|
||||
}
|
||||
.bg-accent {
|
||||
background-color: hsl(var(--accent));
|
||||
}
|
||||
.bg-destructive {
|
||||
background-color: hsl(var(--destructive));
|
||||
}
|
||||
.bg-muted {
|
||||
background-color: hsl(var(--muted));
|
||||
}
|
||||
.bg-success {
|
||||
background-color: hsl(var(--success));
|
||||
}
|
||||
.bg-warning {
|
||||
background-color: hsl(var(--warning));
|
||||
}
|
||||
.bg-info {
|
||||
background-color: hsl(var(--info));
|
||||
}
|
||||
|
||||
.text-background {
|
||||
color: hsl(var(--background));
|
||||
}
|
||||
.text-foreground {
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
.text-card {
|
||||
color: hsl(var(--card));
|
||||
}
|
||||
.text-primary {
|
||||
color: hsl(var(--primary));
|
||||
}
|
||||
.text-secondary {
|
||||
color: hsl(var(--secondary));
|
||||
}
|
||||
.text-accent {
|
||||
color: hsl(var(--accent));
|
||||
}
|
||||
.text-destructive {
|
||||
color: hsl(var(--destructive));
|
||||
}
|
||||
.text-muted {
|
||||
color: hsl(var(--muted));
|
||||
}
|
||||
.text-success {
|
||||
color: hsl(var(--success));
|
||||
}
|
||||
.text-warning {
|
||||
color: hsl(var(--warning));
|
||||
}
|
||||
.text-info {
|
||||
color: hsl(var(--info));
|
||||
}
|
||||
|
||||
.text-primary-foreground {
|
||||
color: hsl(var(--primary-foreground));
|
||||
}
|
||||
.text-secondary-foreground {
|
||||
color: hsl(var(--secondary-foreground));
|
||||
}
|
||||
.text-accent-foreground {
|
||||
color: hsl(var(--accent-foreground));
|
||||
}
|
||||
.text-destructive-foreground {
|
||||
color: hsl(var(--destructive-foreground));
|
||||
}
|
||||
.text-muted-foreground {
|
||||
color: hsl(var(--muted-foreground));
|
||||
}
|
||||
.text-success-foreground {
|
||||
color: hsl(var(--success-foreground));
|
||||
}
|
||||
.text-warning-foreground {
|
||||
color: hsl(var(--warning-foreground));
|
||||
}
|
||||
.text-info-foreground {
|
||||
color: hsl(var(--info-foreground));
|
||||
}
|
||||
|
||||
.border-primary {
|
||||
border-color: hsl(var(--primary));
|
||||
}
|
||||
.border-secondary {
|
||||
border-color: hsl(var(--secondary));
|
||||
}
|
||||
.border-accent {
|
||||
border-color: hsl(var(--accent));
|
||||
}
|
||||
.border-destructive {
|
||||
border-color: hsl(var(--destructive));
|
||||
}
|
||||
.border-input {
|
||||
border-color: hsl(var(--input));
|
||||
}
|
||||
|
||||
/* Sidebar Colors */
|
||||
.bg-sidebar {
|
||||
background-color: hsl(var(--sidebar-background));
|
||||
}
|
||||
.text-sidebar {
|
||||
color: hsl(var(--sidebar-foreground));
|
||||
}
|
||||
.bg-sidebar-primary {
|
||||
background-color: hsl(var(--sidebar-primary));
|
||||
}
|
||||
.text-sidebar-primary {
|
||||
color: hsl(var(--sidebar-primary));
|
||||
}
|
||||
.bg-sidebar-accent {
|
||||
background-color: hsl(var(--sidebar-accent));
|
||||
}
|
||||
.text-sidebar-accent {
|
||||
color: hsl(var(--sidebar-accent));
|
||||
}
|
||||
.border-sidebar {
|
||||
border-color: hsl(var(--sidebar-border));
|
||||
}
|
||||
|
||||
/* Background Images */
|
||||
.bg-gradient-medical {
|
||||
background-image: var(--gradient-medical);
|
||||
}
|
||||
.bg-gradient-primary {
|
||||
background-image: var(--gradient-primary);
|
||||
}
|
||||
.bg-gradient-subtle {
|
||||
background-image: var(--gradient-subtle);
|
||||
}
|
||||
|
||||
/* Border Radius */
|
||||
.rounded-sm {
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
/* Form Error Styling */
|
||||
.field-error-info {
|
||||
@apply text-xs ml-1;
|
||||
color: hsl(var(--destructive));
|
||||
/* font-size: 0.875rem; */
|
||||
margin-top: 0.25rem;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
/* .rounded-md { border-radius: var */
|
||||
@@ -0,0 +1,74 @@
|
||||
<script setup lang="ts">
|
||||
import type { z } from 'zod'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { Loader2 } from 'lucide-vue-next'
|
||||
import { useForm } from 'vee-validate'
|
||||
|
||||
interface Props {
|
||||
schema: z.ZodSchema<any>
|
||||
isLoading: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [data: any]
|
||||
}>()
|
||||
|
||||
const { handleSubmit, defineField, errors, meta } = useForm({
|
||||
validationSchema: toTypedSchema(props.schema),
|
||||
initialValues: {
|
||||
name: '',
|
||||
password: '',
|
||||
},
|
||||
})
|
||||
|
||||
const [name, nameAttrs] = defineField('name')
|
||||
const [password, passwordAttrs] = defineField('password')
|
||||
|
||||
const onSubmit = handleSubmit(async (values) => {
|
||||
try {
|
||||
await emit('submit', values)
|
||||
} catch (error) {
|
||||
console.error('Submission failed:', error)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="grid gap-6" @submit="onSubmit">
|
||||
<div class="grid gap-2">
|
||||
<Label for="name">Username</Label>
|
||||
<Input
|
||||
id="name"
|
||||
v-model="name"
|
||||
v-bind="nameAttrs"
|
||||
:disabled="isLoading"
|
||||
:class="{ 'border-red-500': errors.name }"
|
||||
/>
|
||||
<span v-if="errors.name" class="text-sm text-red-500">
|
||||
{{ errors.name }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<Label for="password">Password</Label>
|
||||
<Input
|
||||
id="password"
|
||||
v-model="password"
|
||||
v-bind="passwordAttrs"
|
||||
type="password"
|
||||
:disabled="isLoading"
|
||||
:class="{ 'border-red-500': errors.password }"
|
||||
/>
|
||||
<span v-if="errors.password" class="text-sm text-red-500">
|
||||
{{ errors.password }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<Button type="submit" class="w-full" :disabled="isLoading || !meta.valid">
|
||||
<Loader2 v-if="isLoading" class="mr-2 h-4 w-4 animate-spin" />
|
||||
Login
|
||||
</Button>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,125 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import Combobox from '~/components/pub/custom-ui/form/combobox.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
interface DivisionFormData {
|
||||
name: string
|
||||
code: string
|
||||
parentId: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
division: {
|
||||
msg: {
|
||||
placeholder: string
|
||||
search: string
|
||||
empty: string
|
||||
}
|
||||
items: {
|
||||
value: string
|
||||
label: string
|
||||
code: string
|
||||
}[]
|
||||
}
|
||||
schema: any
|
||||
initialValues?: Partial<DivisionFormData>
|
||||
errors?: FormErrors
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'submit': [values: DivisionFormData, resetForm: () => void]
|
||||
'cancel': [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const formSchema = toTypedSchema(props.schema)
|
||||
|
||||
// Form submission handler
|
||||
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
|
||||
const formData: DivisionFormData = {
|
||||
name: values.name || '',
|
||||
code: values.code || '',
|
||||
parentId: values.parentId || '',
|
||||
}
|
||||
emit('submit', formData, resetForm)
|
||||
}
|
||||
|
||||
// Form cancel handler
|
||||
function onCancelForm({ resetForm }: { resetForm: () => void }) {
|
||||
emit('cancel', resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Form
|
||||
v-slot="{ handleSubmit, resetForm }" as="" keep-values :validation-schema="formSchema"
|
||||
:initial-values="initialValues"
|
||||
>
|
||||
<form id="entry-form" @submit="handleSubmit($event, (values) => onSubmitForm(values, { resetForm }))">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<FieldGroup>
|
||||
<Label label-for="name">Nama</Label>
|
||||
<Field id="name" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="name">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="name" type="text" placeholder="Masukkan nama divisi" autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<FieldGroup>
|
||||
<Label label-for="code">Kode</Label>
|
||||
<Field id="code" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="code">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input id="code" type="text" placeholder="Masukkan kode divisi" autocomplete="off" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="parentId">Kelompok</Label>
|
||||
<Field id="parentId" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="parentId">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox
|
||||
id="parentId" v-bind="componentField" :items="props.division.items"
|
||||
:placeholder="props.division.msg.placeholder" :search-placeholder="props.division.msg.search"
|
||||
:empty-message="props.division.msg.empty"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end gap-2 mt-4">
|
||||
<Button type="button" variant="outline" @click="onCancelForm({ resetForm })">
|
||||
Batal
|
||||
</Button>
|
||||
<Button type="submit">
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</template>
|
||||
@@ -0,0 +1,86 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue'))
|
||||
|
||||
export const cols: Col[] = [
|
||||
{ width: 100 },
|
||||
{ },
|
||||
{ },
|
||||
{ },
|
||||
{ width: 50 },
|
||||
]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Id' },
|
||||
{ label: 'Nama' },
|
||||
{ label: 'Kode' },
|
||||
{ label: 'Kelompok' },
|
||||
{ label: '' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = [
|
||||
'id',
|
||||
'firstName',
|
||||
'cellphone',
|
||||
'birth_place',
|
||||
'action',
|
||||
]
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim()
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
inPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
outPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
props: {
|
||||
size: 'sm',
|
||||
},
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<script setup lang="ts">
|
||||
import type { PaginationMeta } from '~/components/pub/custom-ui/pagination/pagination.type'
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
interface Props {
|
||||
data: any[]
|
||||
paginationMeta?: PaginationMeta
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
pageChange: [page: number]
|
||||
}>()
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
emit('pageChange', page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<PubBaseDataTable
|
||||
:rows="data" :cols="cols" :header="header" :keys="keys" :func-parsed="funcParsed"
|
||||
:func-html="funcHtml" :func-component="funcComponent" :skeleton-size="paginationMeta?.pageSize"
|
||||
/>
|
||||
|
||||
<template v-if="paginationMeta">
|
||||
<div v-if="paginationMeta.totalPage > 1">
|
||||
<PubCustomUiPagination :pagination-meta="paginationMeta" @page-change="handlePageChange" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,48 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
|
||||
const items = [
|
||||
{ value: 'doctor', label: 'Dokter' },
|
||||
{ value: 'nurse', label: 'Perawat' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-2 border-b border-b-slate-300 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup :column="2">
|
||||
<Label>No. IHS</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>No. SIP</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Unit</Label>
|
||||
<Field>
|
||||
<Select v-model="data.type" :items="items" placeholder="Pilih jenis" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,114 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
|
||||
|
||||
const _doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [
|
||||
{ width: 100 },
|
||||
{ width: 250 },
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 120 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Kode JKN' },
|
||||
{ label: 'Nama' },
|
||||
{ label: 'No KTP' },
|
||||
{ label: 'No SIP' },
|
||||
{ label: 'No IHS' },
|
||||
{ label: 'Telpon' },
|
||||
{ label: 'Fee Ranap' },
|
||||
{ label: 'Fee Rajal' },
|
||||
{ label: 'Status' },
|
||||
{ label: '' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = [
|
||||
'bpjs_code',
|
||||
'name',
|
||||
'identity_number',
|
||||
'sip_no',
|
||||
'ihs_number',
|
||||
'phone',
|
||||
'inPatient_itemPrice',
|
||||
'outPatient_itemPrice',
|
||||
'status',
|
||||
'action',
|
||||
]
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim()
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
inPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
outPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
status(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: statusBadge,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,49 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any; items: any[] }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-5 border-b border-b-slate-300 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Nomor Induk Pegawai</Label>
|
||||
<Field>
|
||||
<Input v-model="data.number" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Status</Label>
|
||||
<Field>
|
||||
<Select v-model="data.type" :items="items" placeholder="Pilih jenis" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Position</Label>
|
||||
<Field>
|
||||
<Select v-model="data.type" :items="items" placeholder="Pilih jenis" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Divisi</Label>
|
||||
<Field>
|
||||
<Select v-model="data.type" :items="items" placeholder="Pilih jenis" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,109 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [
|
||||
{ width: 100 },
|
||||
{ width: 250 },
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{ width: 50 },
|
||||
]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Kode JKN' },
|
||||
{ label: 'Nama' },
|
||||
{ label: 'No KTP' },
|
||||
{ label: 'No SIP' },
|
||||
{ label: 'No IHS' },
|
||||
{ label: 'Telpon' },
|
||||
{ label: 'Fee Ranap' },
|
||||
{ label: 'Fee Rajal' },
|
||||
{ label: 'Status' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = [
|
||||
'bpjs_code',
|
||||
'name',
|
||||
'identity_number',
|
||||
'sip_no',
|
||||
'ihs_number',
|
||||
'phone',
|
||||
'inPatient_itemPrice',
|
||||
'outPatient_itemPrice',
|
||||
'status',
|
||||
'action',
|
||||
]
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
console.log(rec)
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim()
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
inPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
outPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
status: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return doctorStatus[recX.status_code as keyof typeof doctorStatus]
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,148 @@
|
||||
<script setup lang="ts">
|
||||
// types
|
||||
import type z from 'zod'
|
||||
import type { MaterialFormData } from '~/schemas/material'
|
||||
// helpers
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { useForm } from 'vee-validate'
|
||||
// components
|
||||
|
||||
interface Props {
|
||||
schema: z.ZodSchema<any>
|
||||
uoms: any[]
|
||||
items: any[]
|
||||
}
|
||||
|
||||
const isLoading = ref(false)
|
||||
const props = defineProps<Props>()
|
||||
const emit = defineEmits<{
|
||||
submit: [values: MaterialFormData, resetForm: () => void]
|
||||
cancel: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const { handleSubmit, defineField, errors } = useForm({
|
||||
validationSchema: toTypedSchema(props.schema),
|
||||
initialValues: {
|
||||
code: '',
|
||||
name: '',
|
||||
uom_code: '',
|
||||
item_id: '',
|
||||
stock: 0,
|
||||
} as Partial<MaterialFormData>,
|
||||
})
|
||||
|
||||
const [code, codeAttrs] = defineField('code')
|
||||
const [name, nameAttrs] = defineField('name')
|
||||
const [uom, uomAttrs] = defineField('uom_code')
|
||||
const [item, itemAttrs] = defineField('item_id')
|
||||
const [stock, stockAttrs] = defineField('stock')
|
||||
|
||||
const resetForm = () => {
|
||||
code.value = ''
|
||||
name.value = ''
|
||||
uom.value = ''
|
||||
item.value = ''
|
||||
stock.value = 0
|
||||
}
|
||||
|
||||
// Form submission handler
|
||||
function onSubmitForm(values: any) {
|
||||
const formData: MaterialFormData = {
|
||||
name: values.name || '',
|
||||
code: values.code || '',
|
||||
uom_code: values.uom_code || '',
|
||||
item_id: values.item_id || '',
|
||||
stock: values.stock || 0,
|
||||
}
|
||||
emit('submit', formData, resetForm)
|
||||
}
|
||||
|
||||
// Form cancel handler
|
||||
function onCancelForm() {
|
||||
emit('cancel', resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="grid gap-2" @submit="handleSubmit(onSubmitForm)">
|
||||
<div class="grid gap-2">
|
||||
<label for="code">Kode</label>
|
||||
<Input
|
||||
id="code"
|
||||
v-model="code"
|
||||
v-bind="codeAttrs"
|
||||
:disabled="isLoading"
|
||||
:class="{ 'border-red-500': errors.code }"
|
||||
/>
|
||||
<span v-if="errors.code" class="text-sm text-red-500">
|
||||
{{ errors.code }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<label for="name">Nama</label>
|
||||
<Input
|
||||
id="name"
|
||||
v-model="name"
|
||||
v-bind="nameAttrs"
|
||||
:disabled="isLoading"
|
||||
:class="{ 'border-red-500': errors.name }"
|
||||
/>
|
||||
<span v-if="errors.name" class="text-sm text-red-500">
|
||||
{{ errors.name }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<label for="uom">Satuan</label>
|
||||
<Select
|
||||
id="uom"
|
||||
v-model="uom"
|
||||
icon-name="i-lucide-chevron-down"
|
||||
placeholder="Pilih satuan"
|
||||
v-bind="uomAttrs"
|
||||
:items="uoms"
|
||||
:disabled="isLoading"
|
||||
:class="{ 'border-red-500': errors.uom_code }"
|
||||
/>
|
||||
<span v-if="errors.uom_code" class="text-sm text-red-500">
|
||||
{{ errors.uom_code }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<label for="item">Item</label>
|
||||
<Select
|
||||
id="item"
|
||||
v-model="item"
|
||||
icon-name="i-lucide-chevron-down"
|
||||
placeholder="Pilih item"
|
||||
v-bind="itemAttrs"
|
||||
:items="items"
|
||||
:disabled="isLoading"
|
||||
:class="{ 'border-red-500': errors.item_id }"
|
||||
/>
|
||||
<span v-if="errors.item_id" class="text-sm text-red-500">
|
||||
{{ errors.item_id }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<label for="stock">Stok</label>
|
||||
<Input
|
||||
id="stock"
|
||||
v-model="stock"
|
||||
type="number"
|
||||
v-bind="stockAttrs"
|
||||
:disabled="isLoading"
|
||||
:class="{ 'border-red-500': errors.stock }"
|
||||
/>
|
||||
<span v-if="errors.stock" class="text-sm text-red-500">
|
||||
{{ errors.stock }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="my-2 flex justify-end gap-2 py-2">
|
||||
<Button variant="secondary" class="w-[120px]" @click="onCancelForm"> Kembali </Button>
|
||||
<Button type="submit" class="w-[120px]">
|
||||
<Loader2 v-if="isLoading" class="mr-2 h-4 w-4 animate-spin" />
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,51 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
|
||||
export const cols: Col[] = [{ width: 100 }, { width: 250 }, { width: 100 }, { width: 100 }, { width: 100 }, { width: 50 }]
|
||||
|
||||
export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Stok' }, { label: 'Item' }, { label: 'Satuan' }]]
|
||||
|
||||
export const keys = ['code', 'name', 'stock', 'item_id', 'uom_code', 'action']
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: Record<string, (row: any, ...args: any[]) => any> = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.name}`.trim()
|
||||
},
|
||||
item_id: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return recX.item_id
|
||||
},
|
||||
uom_code: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return recX.uom_code
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: Record<string, (row: any, ...args: any[]) => any> = {}
|
||||
@@ -0,0 +1,38 @@
|
||||
<script setup lang="ts">
|
||||
import type { PaginationMeta } from '~/components/pub/custom-ui/pagination/pagination.type'
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
interface Props {
|
||||
data: any[]
|
||||
paginationMeta?: PaginationMeta
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
pageChange: [page: number]
|
||||
}>()
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
emit('pageChange', page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
<template v-if="paginationMeta">
|
||||
<div v-if="paginationMeta.totalPage > 1">
|
||||
<PubCustomUiPagination :pagination-meta="paginationMeta" @page-change="handlePageChange" />
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,124 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
import Select from '~/components/pub/custom-ui/form/select.vue'
|
||||
|
||||
interface InstallationFormData {
|
||||
name: string
|
||||
code: string
|
||||
encounterClassCode: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
installation: {
|
||||
msg: {
|
||||
placeholder: string
|
||||
}
|
||||
items: {
|
||||
value: string
|
||||
label: string
|
||||
code: string
|
||||
}[]
|
||||
}
|
||||
schema: any
|
||||
initialValues?: Partial<InstallationFormData>
|
||||
errors?: FormErrors
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
'submit': [values: InstallationFormData, resetForm: () => void]
|
||||
'cancel': [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const formSchema = toTypedSchema(props.schema)
|
||||
|
||||
// Form submission handler
|
||||
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
|
||||
const formData: InstallationFormData = {
|
||||
name: values.name || '',
|
||||
code: values.code || '',
|
||||
encounterClassCode: values.encounterClassCode || '',
|
||||
}
|
||||
emit('submit', formData, resetForm)
|
||||
}
|
||||
|
||||
// Form cancel handler
|
||||
function onCancelForm({ resetForm }: { resetForm: () => void }) {
|
||||
emit('cancel', resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Form
|
||||
v-slot="{ handleSubmit, resetForm }" as="" keep-values :validation-schema="formSchema"
|
||||
:initial-values="initialValues"
|
||||
>
|
||||
<form id="entry-form" @submit="handleSubmit($event, (values) => onSubmitForm(values, { resetForm }))">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<FieldGroup>
|
||||
<Label label-for="name">Nama</Label>
|
||||
<Field id="name" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="name">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="name" type="text" placeholder="Masukkan nama instalasi" autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<FieldGroup>
|
||||
<Label label-for="code">Kode</Label>
|
||||
<Field id="code" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="code">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input id="code" type="text" placeholder="Masukkan kode instalasi" autocomplete="off" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<FieldGroup>
|
||||
<Label label-for="parentId">Encounter Class</Label>
|
||||
<Field id="encounterClassCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="encounterClassCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select
|
||||
v-bind="componentField"
|
||||
:items="installation.items"
|
||||
:placeholder="installation.msg.placeholder"
|
||||
/>
|
||||
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end gap-2 mt-4">
|
||||
<Button type="button" variant="outline" @click="onCancelForm({ resetForm })">
|
||||
Batal
|
||||
</Button>
|
||||
<Button type="submit">
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</template>
|
||||
@@ -0,0 +1,68 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-ud.vue'))
|
||||
|
||||
export const cols: Col[] = [{ width: 100 }, {}, {}, {}, { width: 50 }]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[{ label: 'Id' }, { label: 'Nama' }, { label: 'Kode' }, { label: 'Encounter Class' }, { label: '' }],
|
||||
]
|
||||
|
||||
export const keys = ['id', 'name', 'cellphone', 'religion_code', 'action']
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.firstName} ${recX.lastName || ''}`.trim()
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
inPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
outPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
props: {
|
||||
size: 'sm',
|
||||
},
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import type { PaginationMeta } from '~/components/pub/custom-ui/pagination/pagination.type'
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
interface Props {
|
||||
data: any[]
|
||||
paginationMeta?: PaginationMeta
|
||||
}
|
||||
|
||||
defineProps<Props>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
pageChange: [page: number]
|
||||
}>()
|
||||
|
||||
function handlePageChange(page: number) {
|
||||
emit('pageChange', page)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="space-y-4">
|
||||
<PubBaseDataTable
|
||||
:rows="data" :cols="cols" :header="header" :keys="keys" :func-parsed="funcParsed"
|
||||
:func-html="funcHtml" :func-component="funcComponent" :skeleton-size="paginationMeta?.pageSize"
|
||||
/>
|
||||
|
||||
<!-- Data info and pagination -->
|
||||
<template v-if="paginationMeta">
|
||||
<div v-if="paginationMeta.totalPage > 1">
|
||||
<PubCustomUiPagination :pagination-meta="paginationMeta" @page-change="handlePageChange" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,50 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
|
||||
const items = [
|
||||
{ value: '1', label: 'item 1' },
|
||||
{ value: '2', label: 'item 2' },
|
||||
{ value: '3', label: 'item 3' },
|
||||
{ value: '4', label: 'item 4' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup>
|
||||
<Label>Items</Label>
|
||||
<Field>
|
||||
<Select :items="items" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label>Perusahaan Insuransi</Label>
|
||||
<Field>
|
||||
<Select :items="items" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label>Harga</Label>
|
||||
<Field>
|
||||
<Input v-model="data.price" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,46 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
|
||||
const _doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [{}, {}, { width: 50 }]
|
||||
|
||||
export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Aksi' }]]
|
||||
|
||||
export const keys = ['code', 'name', 'action']
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,68 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
|
||||
const items = [
|
||||
{ value: '1', label: 'item 1' },
|
||||
{ value: '2', label: 'item 2' },
|
||||
{ value: '3', label: 'item 3' },
|
||||
{ value: '4', label: 'item 4' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup>
|
||||
<Label>Nama</Label>
|
||||
<Field>
|
||||
<Input v-model="data.name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label>Kode</Label>
|
||||
<Field>
|
||||
<Input v-model="data.code" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label>Item Group</Label>
|
||||
<Field>
|
||||
<Select :items="items" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label>UOM</Label>
|
||||
<Field>
|
||||
<Select :items="items" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label>Infra</Label>
|
||||
<Field>
|
||||
<Select :items="items" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label>Harga</Label>
|
||||
<Field>
|
||||
<Input v-model="data.price" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,46 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
|
||||
const _doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [{}, {}, { width: 50 }]
|
||||
|
||||
export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Aksi' }]]
|
||||
|
||||
export const keys = ['code', 'name', 'action']
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-2 border-b border-b-slate-300 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup>
|
||||
<Label>No. IHS</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,114 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
|
||||
|
||||
const _doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [
|
||||
{ width: 100 },
|
||||
{ width: 250 },
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 120 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Kode JKN' },
|
||||
{ label: 'Nama' },
|
||||
{ label: 'No KTP' },
|
||||
{ label: 'No SIP' },
|
||||
{ label: 'No IHS' },
|
||||
{ label: 'Telpon' },
|
||||
{ label: 'Fee Ranap' },
|
||||
{ label: 'Fee Rajal' },
|
||||
{ label: 'Status' },
|
||||
{ label: '' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = [
|
||||
'bpjs_code',
|
||||
'name',
|
||||
'identity_number',
|
||||
'sip_no',
|
||||
'ihs_number',
|
||||
'phone',
|
||||
'inPatient_itemPrice',
|
||||
'outPatient_itemPrice',
|
||||
'status',
|
||||
'action',
|
||||
]
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim()
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
inPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
outPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
status(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: statusBadge,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup>
|
||||
<Label>Nama</Label>
|
||||
<Field>
|
||||
<Input v-model="data.name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label>Kode</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,46 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
|
||||
const _doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [{}, {}, { width: 50 }]
|
||||
|
||||
export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Aksi' }]]
|
||||
|
||||
export const keys = ['code', 'name', 'action']
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,37 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup>
|
||||
<Label>Nama</Label>
|
||||
<Field>
|
||||
<Input v-model="data.name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label>Kode</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,46 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
|
||||
const _doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [{}, {}, { width: 50 }]
|
||||
|
||||
export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Aksi' }]]
|
||||
|
||||
export const keys = ['code', 'name', 'action']
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,80 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
|
||||
const items = [
|
||||
{ value: '1', label: 'item 1' },
|
||||
{ value: '2', label: 'item 2' },
|
||||
{ value: '3', label: 'item 3' },
|
||||
{ value: '4', label: 'item 4' },
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Nama</Label>
|
||||
<Field>
|
||||
<Input type="text" name="identity_number" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Kode</Label>
|
||||
<Field name="sip_number">
|
||||
<Input type="text" name="sip_no" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Metode Pemberian</Label>
|
||||
<Field name="phone">
|
||||
<Select :items="items" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Bentuk Sediaan</Label>
|
||||
<Field>
|
||||
<Select :items="items" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Dosis</Label>
|
||||
<Field>
|
||||
<Input type="number" name="outPatient_rate" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Infra</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Stock</Label>
|
||||
<Field>
|
||||
<Input type="number" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="2">
|
||||
<Label>Status</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,67 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
|
||||
export const cols: Col[] = [{}, {}, {}, {}, {}, {}, { width: 50 }]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Kode' },
|
||||
{ label: 'Name' },
|
||||
{ label: 'Kategori' },
|
||||
{ label: 'Golongan' },
|
||||
{ label: 'Metode Pemberian' },
|
||||
{ label: 'Bentuk' },
|
||||
{ label: 'Stok' },
|
||||
{ label: 'Aksi' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = ['code', 'name', 'category', 'group', 'method', 'unit', 'total', 'action']
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
cateogry: (rec: unknown): unknown => {
|
||||
return (rec as SmallDetailDto).medicineCategory?.name || '-'
|
||||
},
|
||||
group: (rec: unknown): unknown => {
|
||||
return (rec as SmallDetailDto).medicineGroup?.name || '-'
|
||||
},
|
||||
method: (rec: unknown): unknown => {
|
||||
return (rec as SmallDetailDto).medicineMethod?.name || '-'
|
||||
},
|
||||
unit: (rec: unknown): unknown => {
|
||||
return (rec as SmallDetailDto).medicineUnit?.name || '-'
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action: (rec: unknown, idx: number): RecComponent => {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
// (_rec) {
|
||||
// return '-'
|
||||
// },
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-2 border-b border-b-slate-300 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup>
|
||||
<Label>No. IHS</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,114 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
|
||||
|
||||
const _doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [
|
||||
{ width: 100 },
|
||||
{ width: 250 },
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 120 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Kode JKN' },
|
||||
{ label: 'Nama' },
|
||||
{ label: 'No KTP' },
|
||||
{ label: 'No SIP' },
|
||||
{ label: 'No IHS' },
|
||||
{ label: 'Telpon' },
|
||||
{ label: 'Fee Ranap' },
|
||||
{ label: 'Fee Rajal' },
|
||||
{ label: 'Status' },
|
||||
{ label: '' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = [
|
||||
'bpjs_code',
|
||||
'name',
|
||||
'identity_number',
|
||||
'sip_no',
|
||||
'ihs_number',
|
||||
'phone',
|
||||
'inPatient_itemPrice',
|
||||
'outPatient_itemPrice',
|
||||
'status',
|
||||
'action',
|
||||
]
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim()
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
inPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
outPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
status(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: statusBadge,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-2 border-b border-b-slate-300 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup>
|
||||
<Label>No. IHS</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,114 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
|
||||
|
||||
const _doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [
|
||||
{ width: 100 },
|
||||
{ width: 250 },
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 120 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Kode JKN' },
|
||||
{ label: 'Nama' },
|
||||
{ label: 'No KTP' },
|
||||
{ label: 'No SIP' },
|
||||
{ label: 'No IHS' },
|
||||
{ label: 'Telpon' },
|
||||
{ label: 'Fee Ranap' },
|
||||
{ label: 'Fee Rajal' },
|
||||
{ label: 'Status' },
|
||||
{ label: '' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = [
|
||||
'bpjs_code',
|
||||
'name',
|
||||
'identity_number',
|
||||
'sip_no',
|
||||
'ihs_number',
|
||||
'phone',
|
||||
'inPatient_itemPrice',
|
||||
'outPatient_itemPrice',
|
||||
'status',
|
||||
'action',
|
||||
]
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim()
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
inPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
outPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
status(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: statusBadge,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,43 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
import Action from '~/components/pub/custom-ui/nav-footer/ba-dr-su.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<Block>
|
||||
<FieldGroup :column="3">
|
||||
<Label>Nama</Label>
|
||||
<Field>
|
||||
<Input type="text" name="name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="3">
|
||||
<Label>Nama</Label>
|
||||
<Field>
|
||||
<Input type="text" name="name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="3">
|
||||
<Label>Nomor RM</Label>
|
||||
<Field>
|
||||
<Input type="text" name="name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label dynamic>Alamat</Label>
|
||||
<Field>
|
||||
<Input type="text" name="name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
<Action />
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,131 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
|
||||
|
||||
export const cols: Col[] = [
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 120 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{ width: 50 },
|
||||
]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Nama' },
|
||||
{ label: 'Rekam Medis' },
|
||||
{ label: 'KTP' },
|
||||
{ label: 'Tgl Lahir' },
|
||||
{ label: 'Umur' },
|
||||
{ label: 'JK' },
|
||||
{ label: 'Pendidikan' },
|
||||
{ label: 'Status' },
|
||||
{ label: '' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = [
|
||||
'name',
|
||||
'medicalRecord_number',
|
||||
'identity_number',
|
||||
'birth_date',
|
||||
'patient_age',
|
||||
'gender',
|
||||
'education',
|
||||
'status',
|
||||
'action',
|
||||
]
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.firstName} ${recX.middleName || ''} ${recX.lastName || ''}`
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
birth_date: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (typeof recX.birth_date == 'object' && recX.birth_date) {
|
||||
return (recX.birth_date as Date).toLocaleDateString()
|
||||
} else if (typeof recX.birth_date == 'string') {
|
||||
return (recX.birth_date as string).substring(0, 10)
|
||||
}
|
||||
return recX.birth_date
|
||||
},
|
||||
patient_age: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return recX.birth_date?.split('T')[0]
|
||||
},
|
||||
gender: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (typeof recX?.gender_code !== 'number' && recX?.gender_code !== '') {
|
||||
return 'Tidak Diketahui'
|
||||
}
|
||||
return recX.gender_code
|
||||
},
|
||||
education: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (typeof recX.education_code == 'number' && recX.education_code >= 0) {
|
||||
return recX.education_code
|
||||
} else if (typeof recX.education_code) {
|
||||
return recX.education_code
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
status(rec, idx) {
|
||||
if (rec.status === null) {
|
||||
rec.status_code = 0
|
||||
}
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: statusBadge,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,170 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import Combobox from '~/components/pub/custom-ui/form/combobox.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
import { educationCodes, genderCodes, occupationCodes, religionCodes } from '~/lib/constants'
|
||||
import { mapToComboboxOptList } from '~/lib/utils'
|
||||
|
||||
interface DivisionFormData {
|
||||
name: string
|
||||
code: string
|
||||
parentId: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
division: {
|
||||
msg: {
|
||||
placeholder: string
|
||||
search: string
|
||||
empty: string
|
||||
}
|
||||
}
|
||||
items: {
|
||||
value: string
|
||||
label: string
|
||||
code: string
|
||||
}[]
|
||||
schema: any
|
||||
initialValues?: Partial<DivisionFormData>
|
||||
errors?: FormErrors
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [values: DivisionFormData, resetForm: () => void]
|
||||
cancel: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const educationOpts = mapToComboboxOptList(educationCodes)
|
||||
const occupationOpts = mapToComboboxOptList(occupationCodes)
|
||||
const religionOpts = mapToComboboxOptList(religionCodes)
|
||||
const genderOpts = mapToComboboxOptList(genderCodes)
|
||||
|
||||
const formSchema = toTypedSchema(props.schema)
|
||||
|
||||
// Form submission handler
|
||||
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
|
||||
const formData: DivisionFormData = {
|
||||
name: values.name || '',
|
||||
code: values.code || '',
|
||||
parentId: values.parentId || '',
|
||||
}
|
||||
emit('submit', formData, resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Form
|
||||
v-slot="{ handleSubmit, resetForm }"
|
||||
as=""
|
||||
keep-values
|
||||
:validation-schema="formSchema"
|
||||
:initial-values="initialValues"
|
||||
>
|
||||
<form id="entry-form" @submit="handleSubmit($event, (values) => onSubmitForm(values, { resetForm }))">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<!-- LocationType -->
|
||||
<FieldGroup>
|
||||
<Label label-for="locationType">Jenis Alamat</Label>
|
||||
<Field id="locationType" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="locationType">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select id="locationType" v-bind="componentField" :items="genderOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Address -->
|
||||
<FieldGroup>
|
||||
<Label label-for="address">Alamat</Label>
|
||||
<Field id="address" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="address">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="address"
|
||||
type="text"
|
||||
placeholder="Masukkan alamat lengkap"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Rt -->
|
||||
<FieldGroup>
|
||||
<Label label-for="rt">RT</Label>
|
||||
<Field id="rt" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="rt">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="rt"
|
||||
type="text"
|
||||
maxlength="2"
|
||||
placeholder="01"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Rw -->
|
||||
<FieldGroup>
|
||||
<Label label-for="rw">RW</Label>
|
||||
<Field id="rw" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="rw">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="rw"
|
||||
type="text"
|
||||
maxlength="2"
|
||||
placeholder="01"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Village_Code -->
|
||||
<FieldGroup>
|
||||
<Label label-for="villageCode">Desa/Kelurahan</Label>
|
||||
<Field id="villageCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="villageCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox id="villageCode" v-bind="componentField" :items="genderOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</template>
|
||||
@@ -0,0 +1,111 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import Combobox from '~/components/pub/custom-ui/form/combobox.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
import { educationCodes, genderCodes, occupationCodes, religionCodes } from '~/lib/constants'
|
||||
import { mapToComboboxOptList } from '~/lib/utils'
|
||||
|
||||
interface DivisionFormData {
|
||||
name: string
|
||||
code: string
|
||||
parentId: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
division: {
|
||||
msg: {
|
||||
placeholder: string
|
||||
search: string
|
||||
empty: string
|
||||
}
|
||||
}
|
||||
items: {
|
||||
value: string
|
||||
label: string
|
||||
code: string
|
||||
}[]
|
||||
schema: any
|
||||
initialValues?: Partial<DivisionFormData>
|
||||
errors?: FormErrors
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [values: DivisionFormData, resetForm: () => void]
|
||||
cancel: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const educationOpts = mapToComboboxOptList(educationCodes)
|
||||
const occupationOpts = mapToComboboxOptList(occupationCodes)
|
||||
const religionOpts = mapToComboboxOptList(religionCodes)
|
||||
const genderOpts = mapToComboboxOptList(genderCodes)
|
||||
|
||||
const formSchema = toTypedSchema(props.schema)
|
||||
|
||||
// Form submission handler
|
||||
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
|
||||
const formData: DivisionFormData = {
|
||||
name: values.name || '',
|
||||
code: values.code || '',
|
||||
parentId: values.parentId || '',
|
||||
}
|
||||
emit('submit', formData, resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Form
|
||||
v-slot="{ handleSubmit, resetForm }"
|
||||
as=""
|
||||
keep-values
|
||||
:validation-schema="formSchema"
|
||||
:initial-values="initialValues"
|
||||
>
|
||||
<form id="entry-form" @submit="handleSubmit($event, (values) => onSubmitForm(values, { resetForm }))">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<!-- LocationType -->
|
||||
<FieldGroup>
|
||||
<Label label-for="type">Tipe</Label>
|
||||
<Field id="type" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="type">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select id="type" v-bind="componentField" :items="genderOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Address -->
|
||||
<FieldGroup>
|
||||
<Label label-for="value">Value</Label>
|
||||
<Field id="value" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="value">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="value"
|
||||
type="text"
|
||||
placeholder="Masukkan alamat lengkap"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</template>
|
||||
@@ -0,0 +1,234 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import Combobox from '~/components/pub/custom-ui/form/combobox.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
import { educationCodes, genderCodes, occupationCodes, religionCodes, relationshipCodes } from '~/lib/constants'
|
||||
import { mapToComboboxOptList } from '~/lib/utils'
|
||||
|
||||
interface DivisionFormData {
|
||||
name: string
|
||||
code: string
|
||||
parentId: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
division: {
|
||||
msg: {
|
||||
placeholder: string
|
||||
search: string
|
||||
empty: string
|
||||
}
|
||||
}
|
||||
items: {
|
||||
value: string
|
||||
label: string
|
||||
code: string
|
||||
}[]
|
||||
schema: any
|
||||
initialValues?: Partial<DivisionFormData>
|
||||
errors?: FormErrors
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [values: DivisionFormData, resetForm: () => void]
|
||||
cancel: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const relationshipOpts = mapToComboboxOptList(relationshipCodes)
|
||||
const educationOpts = mapToComboboxOptList(educationCodes)
|
||||
const occupationOpts = mapToComboboxOptList(occupationCodes)
|
||||
const genderOpts = mapToComboboxOptList(genderCodes)
|
||||
|
||||
const formSchema = toTypedSchema(props.schema)
|
||||
|
||||
// Form submission handler
|
||||
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
|
||||
const formData: DivisionFormData = {
|
||||
name: values.name || '',
|
||||
code: values.code || '',
|
||||
parentId: values.parentId || '',
|
||||
}
|
||||
emit('submit', formData, resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Form
|
||||
v-slot="{ handleSubmit, resetForm }"
|
||||
as=""
|
||||
keep-values
|
||||
:validation-schema="formSchema"
|
||||
:initial-values="initialValues"
|
||||
>
|
||||
<form id="entry-form" @submit="handleSubmit($event, (values) => onSubmitForm(values, { resetForm }))">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<!-- Relationship_Code -->
|
||||
<FieldGroup>
|
||||
<Label label-for="relationshipCode">Hubungan</Label>
|
||||
<Field id="relationshipCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="relationshipCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select id="relationshipCode" v-bind="componentField" :items="relationshipOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Name -->
|
||||
<FieldGroup>
|
||||
<Label label-for="relativeName">Nama</Label>
|
||||
<Field id="relativeName" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="relativeName">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="relativeName"
|
||||
type="text"
|
||||
placeholder="Masukkan nama kerabat"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Address -->
|
||||
<FieldGroup>
|
||||
<Label label-for="relativeAddress">Alamat</Label>
|
||||
<Field id="relativeAddress" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="relativeAddress">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="relativeAddress"
|
||||
type="text"
|
||||
placeholder="Alamat kerabat"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Village_Code -->
|
||||
<FieldGroup>
|
||||
<Label label-for="relativeVillageCode">Desa/Kelurahan</Label>
|
||||
<Field id="relativeVillageCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="relativeVillageCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox id="relativeVillageCode" v-bind="componentField" :items="genderOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Gender_Code -->
|
||||
<FieldGroup>
|
||||
<Label label-for="relativeGender">Jenis Kelamin</Label>
|
||||
<Field id="relativeGender" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="relativeGender">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select id="relativeGender" v-bind="componentField" :items="genderOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- PhoneNumber -->
|
||||
<FieldGroup>
|
||||
<Label label-for="phoneNumber">Nomor Telepon</Label>
|
||||
<Field id="phoneNumber" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="phoneNumber">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="phoneNumber"
|
||||
type="text"
|
||||
placeholder="0812xxxxxx"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Education_Code -->
|
||||
<FieldGroup>
|
||||
<Label label-for="relativeEducation">Pendidikan</Label>
|
||||
<Field id="relativeEducation" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="relativeEducation">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select id="relativeEducation" v-bind="componentField" :items="educationOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Occupation_Code -->
|
||||
<FieldGroup>
|
||||
<Label label-for="relativeOccupationCode">Pekerjaan</Label>
|
||||
<Field id="relativeOccupationCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="relativeOccupationCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Select id="relativeOccupationCode" v-bind="componentField" :items="occupationOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Occupation_Name -->
|
||||
<FieldGroup>
|
||||
<Label label-for="relativeOccupationName">Nama Pekerjaan</Label>
|
||||
<Field id="relativeOccupationName" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="relativeOccupationName">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="relativeOccupationName"
|
||||
type="text"
|
||||
placeholder="Contoh: Guru, Dokter, Petani"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</template>
|
||||
@@ -0,0 +1,340 @@
|
||||
<script setup lang="ts">
|
||||
import type { FormErrors } from '~/types/error'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import Combobox from '~/components/pub/custom-ui/form/combobox.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
import { educationCodes, genderCodes, occupationCodes, religionCodes } from '~/lib/constants'
|
||||
import { mapToComboboxOptList } from '~/lib/utils'
|
||||
|
||||
interface DivisionFormData {
|
||||
name: string
|
||||
code: string
|
||||
parentId: string
|
||||
}
|
||||
|
||||
const props = defineProps<{
|
||||
division: {
|
||||
msg: {
|
||||
placeholder: string
|
||||
search: string
|
||||
empty: string
|
||||
}
|
||||
}
|
||||
items: {
|
||||
value: string
|
||||
label: string
|
||||
code: string
|
||||
}[]
|
||||
schema: any
|
||||
initialValues?: Partial<DivisionFormData>
|
||||
errors?: FormErrors
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
submit: [values: DivisionFormData, resetForm: () => void]
|
||||
cancel: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const educationOpts = mapToComboboxOptList(educationCodes)
|
||||
const occupationOpts = mapToComboboxOptList(occupationCodes)
|
||||
const religionOpts = mapToComboboxOptList(religionCodes)
|
||||
const genderOpts = mapToComboboxOptList(genderCodes)
|
||||
|
||||
const formSchema = toTypedSchema(props.schema)
|
||||
|
||||
// Form submission handler
|
||||
function onSubmitForm(values: any, { resetForm }: { resetForm: () => void }) {
|
||||
const formData: DivisionFormData = {
|
||||
name: values.name || '',
|
||||
code: values.code || '',
|
||||
parentId: values.parentId || '',
|
||||
}
|
||||
emit('submit', formData, resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Form
|
||||
v-slot="{ handleSubmit, resetForm }"
|
||||
as=""
|
||||
keep-values
|
||||
:validation-schema="formSchema"
|
||||
:initial-values="initialValues"
|
||||
>
|
||||
<form id="entry-form" @submit="handleSubmit($event, (values) => onSubmitForm(values, { resetForm }))">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup>
|
||||
<Label label-for="residentIdentityNumber">KTP</Label>
|
||||
<Field id="residentIdentityNumber" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="residentIdentityNumber">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="residentIdentityNumber"
|
||||
type="text"
|
||||
maxlength="16"
|
||||
placeholder="Nomor KTP"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- FrontTitle -->
|
||||
<FieldGroup :column="3">
|
||||
<Label label-for="frontTitle">Gelar Depan</Label>
|
||||
<Field id="frontTitle" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="frontTitle">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="frontTitle"
|
||||
type="text"
|
||||
placeholder="Dr., Ir., dll"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<FieldGroup :column="3">
|
||||
<Label label-for="name" position="dynamic">Nama</Label>
|
||||
<Field id="name" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="name">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="name"
|
||||
type="text"
|
||||
placeholder="Nama lengkap"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- EndTitle -->
|
||||
<FieldGroup :column="3">
|
||||
<Label label-for="endTitle" position="dynamic">Gelar Belakang</Label>
|
||||
<Field id="endTitle" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="endTitle">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="endTitle"
|
||||
type="text"
|
||||
placeholder="S.Kom, M.Kes, dll"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- BirthDate -->
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="birthDate">Tanggal Lahir</Label>
|
||||
<Field id="birthDate" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="birthDate">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input id="birthDate" type="date" v-bind="componentField" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- BirthRegency_Code -->
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="birthRegencyCode">Tempat Lahir</Label>
|
||||
<Field id="birthRegencyCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="birthRegencyCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox id="parentId" v-bind="componentField" :items="educationOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Gender_Code -->
|
||||
<FieldGroup>
|
||||
<Label label-for="genderCode">Jenis Kelamin</Label>
|
||||
<Field id="genderCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="genderCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox id="genderCode" v-bind="componentField" :items="genderOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- PassportNumber -->
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="passportNumber">Paspor</Label>
|
||||
<Field id="passportNumber" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="passportNumber">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="passportNumber"
|
||||
type="text"
|
||||
placeholder="Nomor Paspor"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- DrivingLicenseNumber -->
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="drivingLicenseNumber">SIM</Label>
|
||||
<Field id="drivingLicenseNumber" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="drivingLicenseNumber">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="drivingLicenseNumber"
|
||||
type="text"
|
||||
placeholder="Nomor SIM"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Religion_Code -->
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="religionCode">Agama</Label>
|
||||
<Field id="religionCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="religionCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox id="religionCode" v-bind="componentField" :items="religionOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="ethnicCode">Suku</Label>
|
||||
<Field id="ethnicCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="ethnicCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox id="ethnicCode" v-bind="componentField" :items="occupationOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Language_Code -->
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="languageCode">Bahasa</Label>
|
||||
<Field id="languageCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="languageCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox id="parentId" v-bind="componentField" :items="educationOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Education_Code -->
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="educationCode">Pendidikan</Label>
|
||||
<Field id="educationCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="educationCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox id="educationCode" v-bind="componentField" :items="educationOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Occupation_Code -->
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="occupationCode">Pekerjaan</Label>
|
||||
<Field id="occupationCode" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="occupationCode">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Combobox id="occupationCode" v-bind="componentField" :items="occupationOpts" />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
|
||||
<!-- Occupation_Name -->
|
||||
<FieldGroup :column="2">
|
||||
<Label label-for="occupationName">Detail Pekerjaan</Label>
|
||||
<Field id="occupationName" :errors="errors">
|
||||
<FormField v-slot="{ componentField }" name="occupationName">
|
||||
<FormItem>
|
||||
<FormControl>
|
||||
<Input
|
||||
id="occupationName"
|
||||
type="text"
|
||||
placeholder="Contoh: Guru SMP, Petani"
|
||||
autocomplete="off"
|
||||
v-bind="componentField"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
</FormField>
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</template>
|
||||
@@ -0,0 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/custom-ui/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/custom-ui/form/field-group.vue'
|
||||
import Field from '~/components/pub/custom-ui/form/field.vue'
|
||||
import Label from '~/components/pub/custom-ui/form/label.vue'
|
||||
|
||||
const props = defineProps<{ modelValue: any }>()
|
||||
const emit = defineEmits(['update:modelValue', 'event'])
|
||||
|
||||
const data = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-2 border-b border-b-slate-300 text-lg xl:text-xl">
|
||||
<div class="flex flex-col justify-between">
|
||||
<Block>
|
||||
<FieldGroup :column="2">
|
||||
<Label>No. IHS</Label>
|
||||
<Field>
|
||||
<Input />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,114 @@
|
||||
import type {
|
||||
Col,
|
||||
KeyLabel,
|
||||
RecComponent,
|
||||
RecStrFuncComponent,
|
||||
RecStrFuncUnknown,
|
||||
Th,
|
||||
} from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
const statusBadge = defineAsyncComponent(() => import('./status-badge.vue'))
|
||||
|
||||
const _doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
export const cols: Col[] = [
|
||||
{ width: 100 },
|
||||
{ width: 250 },
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 120 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{},
|
||||
]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Kode JKN' },
|
||||
{ label: 'Nama' },
|
||||
{ label: 'No KTP' },
|
||||
{ label: 'No SIP' },
|
||||
{ label: 'No IHS' },
|
||||
{ label: 'Telpon' },
|
||||
{ label: 'Fee Ranap' },
|
||||
{ label: 'Fee Rajal' },
|
||||
{ label: 'Status' },
|
||||
{ label: '' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = [
|
||||
'bpjs_code',
|
||||
'name',
|
||||
'identity_number',
|
||||
'sip_no',
|
||||
'ihs_number',
|
||||
'phone',
|
||||
'inPatient_itemPrice',
|
||||
'outPatient_itemPrice',
|
||||
'status',
|
||||
'action',
|
||||
]
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.frontTitle} ${recX.name} ${recX.endTitle}`.trim()
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
inPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.inPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
outPatient_itemPrice: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return Number(recX.outPatient_itemPrice.price).toLocaleString('id-ID')
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
status(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: statusBadge,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import { Badge } from '~/components/pub/ui/badge'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const doctorStatus = {
|
||||
0: 'Tidak Aktif',
|
||||
1: 'Aktif',
|
||||
}
|
||||
|
||||
const statusText = computed(() => {
|
||||
return doctorStatus[props.rec.status_code as keyof typeof doctorStatus]
|
||||
})
|
||||
|
||||
const badgeVariant = computed(() => {
|
||||
return props.rec.status_code === 1 ? 'default' : 'destructive'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex justify-center">
|
||||
<Badge :variant="badgeVariant">
|
||||
{{ statusText }}
|
||||
</Badge>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,47 @@
|
||||
<script setup lang="ts">
|
||||
import Block from '~/components/pub/form/block.vue'
|
||||
import FieldGroup from '~/components/pub/form/field-group.vue'
|
||||
import Field from '~/components/pub/form/field.vue'
|
||||
import Label from '~/components/pub/form/label.vue'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form id="entry-form">
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<Icon name="i-lucide-user" class="me-2" />
|
||||
<span class="font-semibold">Tambah</span> Pasien
|
||||
</div>
|
||||
|
||||
<div class="mb-5 border-b border-b-slate-300 pb-3 text-lg xl:text-xl">
|
||||
<Block>
|
||||
<FieldGroup :column="3">
|
||||
<Label>Nama</Label>
|
||||
<Field>
|
||||
<Input type="text" name="name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="3">
|
||||
<Label>Nama</Label>
|
||||
<Field>
|
||||
<Input type="text" name="name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup :column="3">
|
||||
<Label>Nomor RM</Label>
|
||||
<Field>
|
||||
<Input type="text" name="name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
<FieldGroup>
|
||||
<Label dynamic>Alamat</Label>
|
||||
<Field>
|
||||
<Input type="text" name="name" />
|
||||
</Field>
|
||||
</FieldGroup>
|
||||
</Block>
|
||||
</div>
|
||||
<div class="my-2 flex justify-end py-2">
|
||||
<PubNavFooterCsd />
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -0,0 +1,112 @@
|
||||
import type { Col, KeyLabel, RecComponent, RecStrFuncComponent, RecStrFuncUnknown, Th } from '~/components/pub/custom-ui/data/types'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
|
||||
type SmallDetailDto = any
|
||||
|
||||
const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue'))
|
||||
|
||||
export const cols: Col[] = [
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 120 },
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{ width: 100 },
|
||||
{ width: 100 },
|
||||
{},
|
||||
{ width: 50 },
|
||||
]
|
||||
|
||||
export const header: Th[][] = [
|
||||
[
|
||||
{ label: 'Nama' },
|
||||
{ label: 'Rekam Medis' },
|
||||
{ label: 'KTP' },
|
||||
{ label: 'Tgl Lahir' },
|
||||
{ label: 'Umur' },
|
||||
{ label: 'JK' },
|
||||
{ label: 'Pendidikan' },
|
||||
{ label: 'Status' },
|
||||
{ label: '' },
|
||||
],
|
||||
]
|
||||
|
||||
export const keys = [
|
||||
'name',
|
||||
'medicalRecord_number',
|
||||
'identity_number',
|
||||
'birth_date',
|
||||
'patient_age',
|
||||
'gender',
|
||||
'education',
|
||||
'status',
|
||||
'action',
|
||||
]
|
||||
|
||||
export const delKeyNames: KeyLabel[] = [
|
||||
{ key: 'code', label: 'Kode' },
|
||||
{ key: 'name', label: 'Nama' },
|
||||
]
|
||||
|
||||
export const funcParsed: RecStrFuncUnknown = {
|
||||
name: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return `${recX.firstName} ${recX.middleName || ''} ${recX.lastName || ''}`
|
||||
},
|
||||
identity_number: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (recX.identity_number?.substring(0, 5) === 'BLANK') {
|
||||
return '(TANPA NIK)'
|
||||
}
|
||||
return recX.identity_number
|
||||
},
|
||||
birth_date: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (typeof recX.birth_date == 'object' && recX.birth_date) {
|
||||
return (recX.birth_date as Date).toLocaleDateString()
|
||||
} else if (typeof recX.birth_date == 'string') {
|
||||
return (recX.birth_date as string).substring(0, 10)
|
||||
}
|
||||
return recX.birth_date
|
||||
},
|
||||
patient_age: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
return recX.birth_date?.split('T')[0]
|
||||
},
|
||||
gender: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (typeof recX?.gender_code !== 'number' && recX?.gender_code !== '') {
|
||||
return 'Tidak Diketahui'
|
||||
}
|
||||
return recX.gender_code
|
||||
},
|
||||
education: (rec: unknown): unknown => {
|
||||
const recX = rec as SmallDetailDto
|
||||
if (typeof recX.education_code == 'number' && recX.education_code >= 0) {
|
||||
return recX.education_code
|
||||
} else if (typeof recX.education_code) {
|
||||
return recX.education_code
|
||||
}
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
|
||||
export const funcComponent: RecStrFuncComponent = {
|
||||
action(rec, idx) {
|
||||
const res: RecComponent = {
|
||||
idx,
|
||||
rec: rec as object,
|
||||
component: action,
|
||||
}
|
||||
return res
|
||||
},
|
||||
}
|
||||
|
||||
export const funcHtml: RecStrFuncUnknown = {
|
||||
patient_address(_rec) {
|
||||
return '-'
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { cols, funcComponent, funcHtml, funcParsed, header, keys } from './list-cfg'
|
||||
|
||||
defineProps<{
|
||||
data: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PubBaseDataTable
|
||||
:rows="data"
|
||||
:cols="cols"
|
||||
:header="header"
|
||||
:keys="keys"
|
||||
:func-parsed="funcParsed"
|
||||
:func-html="funcHtml"
|
||||
:func-component="funcComponent"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,13 @@
|
||||
<script setup lang="ts">
|
||||
const props = defineProps<{
|
||||
rec: any
|
||||
idx?: number
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col justify-center">
|
||||
<p class="font-semibold text-sm">{{ props.rec.patient.name }}</p>
|
||||
<p class="text-xs text-muted-foreground">{{ props.rec.patient.mrn }}</p>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,29 @@
|
||||
<script setup lang="ts">
|
||||
import Badge from './badge.vue'
|
||||
import { rowStatus } from './list-cfg'
|
||||
|
||||
const props = defineProps<{
|
||||
rec: { status: number }
|
||||
idx?: number
|
||||
}>()
|
||||
|
||||
const variants = {
|
||||
0: 'error',
|
||||
1: 'warning',
|
||||
2: 'info',
|
||||
} as const
|
||||
|
||||
const statusText = computed(() => {
|
||||
return rowStatus[props.rec.status as keyof typeof rowStatus]
|
||||
})
|
||||
|
||||
const badgeStatus = computed((): 'error' | 'warning' | 'success' | 'info' => {
|
||||
return variants[props.rec.status as keyof typeof variants] ?? 'info'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex">
|
||||
<Badge :status="badgeStatus" :text="statusText" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import { cva } from 'class-variance-authority'
|
||||
import { cn } from '~/lib/utils'
|
||||
|
||||
interface BadgeProps {
|
||||
status: 'success' | 'info' | 'warning' | 'error'
|
||||
text: string
|
||||
}
|
||||
|
||||
const props = defineProps<BadgeProps>()
|
||||
|
||||
const badgeVariants = cva(
|
||||
'inline-flex items-center rounded-md 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: {
|
||||
success: 'rounded-full border-transparent bg-green-500 text-white hover:bg-green-600',
|
||||
info: 'rounded-full border-transparent bg-blue-500 text-white hover:bg-blue-600',
|
||||
warning: 'rounded-full border-transparent bg-yellow-500 text-white hover:bg-yellow-600',
|
||||
error: 'rounded-full border-transparent bg-red-500 text-white hover:bg-red-600',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'info',
|
||||
},
|
||||
},
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex">
|
||||
<div :class="cn(badgeVariants({ variant: props.status }))">
|
||||
{{ props.text }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user