@finema/core 1.4.14 → 1.4.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/module.d.mts CHANGED
@@ -6,6 +6,7 @@ declare const core: {
6
6
  date_format: string;
7
7
  date_time_format: string;
8
8
  time_format: string;
9
+ is_thai_year: boolean;
9
10
  };
10
11
 
11
12
  declare const config_core: typeof core;
package/dist/module.d.ts CHANGED
@@ -6,6 +6,7 @@ declare const core: {
6
6
  date_format: string;
7
7
  date_time_format: string;
8
8
  time_format: string;
9
+ is_thai_year: boolean;
9
10
  };
10
11
 
11
12
  declare const config_core: typeof core;
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finema/core",
3
- "version": "1.4.14",
3
+ "version": "1.4.16",
4
4
  "configKey": "core",
5
5
  "compatibility": {
6
6
  "nuxt": "^3.7.4"
package/dist/module.mjs CHANGED
@@ -2,7 +2,7 @@ import { defineNuxtModule, createResolver, installModule, addPlugin, addComponen
2
2
  import 'lodash-es';
3
3
 
4
4
  const name = "@finema/core";
5
- const version = "1.4.14";
5
+ const version = "1.4.16";
6
6
 
7
7
  const colors = {
8
8
  black: "#20243E",
@@ -9,6 +9,7 @@
9
9
  :help="help"
10
10
  :error="errorMessage"
11
11
  :required="!!isRequired"
12
+ :ui="containerUi"
12
13
  >
13
14
  <slot />
14
15
  </UFormGroup>
@@ -1,83 +1,96 @@
1
1
  <template>
2
- <div class="fields space-y-4">
3
- <template v-for="(option, index) in options" :key="option.props.name + index + option.type">
4
- <div v-if="!option.isHide" :class="option.class">
5
- <FormInputStatic
6
- v-if="option.type === INPUT_TYPES.STATIC"
7
- :form="form"
8
- v-bind="option.props"
9
- v-on="option.on ?? {}"
10
- />
11
- <FormInputText
12
- v-else-if="option.type === INPUT_TYPES.TEXT"
13
- :form="form"
14
- v-bind="option.props"
15
- v-on="option.on ?? {}"
16
- />
17
- <FormInputText
18
- v-else-if="option.type === INPUT_TYPES.PASSWORD"
19
- type="password"
20
- :form="form"
21
- v-bind="option.props"
22
- v-on="option.on ?? {}"
23
- />
24
- <FormInputText
25
- v-else-if="option.type === INPUT_TYPES.EMAIL"
26
- type="email"
27
- :form="form"
28
- v-bind="option.props"
29
- v-on="option.on ?? {}"
30
- />
31
- <FormInputTextarea
32
- v-else-if="option.type === INPUT_TYPES.TEXTAREA"
33
- :form="form"
34
- v-bind="option.props"
35
- v-on="option.on ?? {}"
36
- />
37
- <FormInputToggle
38
- v-else-if="option.type === INPUT_TYPES.TOGGLE"
39
- :form="form"
40
- v-bind="option.props"
41
- v-on="option.on ?? {}"
42
- />
43
- <FormInputSelect
44
- v-else-if="option.type === INPUT_TYPES.SELECT"
45
- :form="form"
46
- v-bind="option.props"
47
- v-on="option.on ?? {}"
48
- />
49
- <FormInputRadio
50
- v-else-if="option.type === INPUT_TYPES.RADIO"
51
- :form="form"
52
- v-bind="option.props"
53
- v-on="option.on ?? {}"
54
- />
55
- <FormInputCheckbox
56
- v-else-if="option.type === INPUT_TYPES.CHECKBOX"
57
- :form="form"
58
- v-bind="option.props"
59
- v-on="option.on ?? {}"
60
- />
61
- <FormInputDateTime
62
- v-else-if="option.type === INPUT_TYPES.DATE_TIME"
63
- :form="form"
64
- v-bind="option.props"
65
- v-on="option.on ?? {}"
66
- />
67
- <FormInputDateTime
68
- v-else-if="option.type === INPUT_TYPES.DATE"
69
- :form="form"
70
- v-bind="option.props"
71
- :disabled-time="true"
72
- v-on="option.on ?? {}"
73
- />
74
- <FormInputUploadFileClassic
75
- v-else-if="option.type === INPUT_TYPES.UPLOAD_FILE_CLASSIC"
76
- :form="form"
77
- v-bind="option.props"
78
- v-on="option.on ?? {}"
79
- />
80
- </div>
2
+ <div :class="['fields', $props.class]">
3
+ <template
4
+ v-for="(option, index) in options.filter((item) => !item.isHide)"
5
+ :key="option.props.name + index + option.type"
6
+ >
7
+ <FormInputStatic
8
+ v-if="option.type === INPUT_TYPES.STATIC"
9
+ :class="option.class"
10
+ :form="form"
11
+ v-bind="getFieldBinding(option)"
12
+ v-on="option.on ?? {}"
13
+ />
14
+ <FormInputText
15
+ v-else-if="option.type === INPUT_TYPES.TEXT"
16
+ :class="option.class"
17
+ :form="form"
18
+ v-bind="getFieldBinding(option)"
19
+ v-on="option.on ?? {}"
20
+ />
21
+ <FormInputText
22
+ v-else-if="option.type === INPUT_TYPES.PASSWORD"
23
+ :class="option.class"
24
+ type="password"
25
+ :form="form"
26
+ v-bind="getFieldBinding(option)"
27
+ v-on="option.on ?? {}"
28
+ />
29
+ <FormInputText
30
+ v-else-if="option.type === INPUT_TYPES.EMAIL"
31
+ :class="option.class"
32
+ type="email"
33
+ :form="form"
34
+ v-bind="getFieldBinding(option)"
35
+ v-on="option.on ?? {}"
36
+ />
37
+ <FormInputTextarea
38
+ v-else-if="option.type === INPUT_TYPES.TEXTAREA"
39
+ :class="option.class"
40
+ :form="form"
41
+ v-bind="getFieldBinding(option)"
42
+ v-on="option.on ?? {}"
43
+ />
44
+ <FormInputToggle
45
+ v-else-if="option.type === INPUT_TYPES.TOGGLE"
46
+ :class="option.class"
47
+ :form="form"
48
+ v-bind="getFieldBinding(option)"
49
+ v-on="option.on ?? {}"
50
+ />
51
+ <FormInputSelect
52
+ v-else-if="option.type === INPUT_TYPES.SELECT"
53
+ :class="option.class"
54
+ :form="form"
55
+ v-bind="getFieldBinding(option)"
56
+ v-on="option.on ?? {}"
57
+ />
58
+ <FormInputRadio
59
+ v-else-if="option.type === INPUT_TYPES.RADIO"
60
+ :class="option.class"
61
+ :form="form"
62
+ v-bind="getFieldBinding(option)"
63
+ v-on="option.on ?? {}"
64
+ />
65
+ <FormInputCheckbox
66
+ v-else-if="option.type === INPUT_TYPES.CHECKBOX"
67
+ :class="option.class"
68
+ :form="form"
69
+ v-bind="getFieldBinding(option)"
70
+ v-on="option.on ?? {}"
71
+ />
72
+ <FormInputDateTime
73
+ v-else-if="option.type === INPUT_TYPES.DATE_TIME"
74
+ :class="option.class"
75
+ :form="form"
76
+ v-bind="getFieldBinding(option)"
77
+ v-on="option.on ?? {}"
78
+ />
79
+ <FormInputDateTime
80
+ v-else-if="option.type === INPUT_TYPES.DATE"
81
+ :class="option.class"
82
+ :form="form"
83
+ v-bind="getFieldBinding(option)"
84
+ :disabled-time="true"
85
+ v-on="option.on ?? {}"
86
+ />
87
+ <FormInputUploadFileClassic
88
+ v-else-if="option.type === INPUT_TYPES.UPLOAD_FILE_CLASSIC"
89
+ :class="option.class"
90
+ :form="form"
91
+ v-bind="getFieldBinding(option)"
92
+ v-on="option.on ?? {}"
93
+ />
81
94
  </template>
82
95
  </div>
83
96
  </template>
@@ -85,8 +98,32 @@
85
98
  import { type FormContext } from 'vee-validate'
86
99
  import { type IFormField, INPUT_TYPES } from '#core/components/Form/types'
87
100
 
88
- defineProps<{
89
- form?: FormContext
90
- options: IFormField[]
91
- }>()
101
+ const props = withDefaults(
102
+ defineProps<{
103
+ form?: FormContext
104
+ options: IFormField[]
105
+ orientation?: 'horizontal' | 'vertical'
106
+ class?: any
107
+ }>(),
108
+ {
109
+ class: 'space-y-4',
110
+ orientation: 'vertical',
111
+ }
112
+ )
113
+
114
+ const getFieldBinding = (field: IFormField) => {
115
+ if (props.orientation === 'horizontal') {
116
+ return {
117
+ ...field.props,
118
+ containerUi: {
119
+ ...field.props.containerUi,
120
+ wrapper:
121
+ 'lg:grid lg:grid-cols-3 lg:gap-4 lg:items-start ' + field.props.containerUi?.wrapper,
122
+ container: 'lg:col-span-2 ' + field.props.containerUi?.container,
123
+ },
124
+ }
125
+ }
126
+
127
+ return field.props
128
+ }
92
129
  </script>
@@ -33,19 +33,19 @@ export interface IFieldProps {
33
33
  size?: string;
34
34
  rules?: any;
35
35
  autoFocus?: boolean;
36
- class?: any;
37
- classInner?: any;
38
36
  placeholder?: string;
39
37
  isDisabled?: boolean;
40
38
  isReadonly?: boolean;
41
39
  isRequired?: boolean;
42
40
  help?: string;
43
41
  ui?: object | any;
42
+ containerUi?: object | any;
44
43
  }
45
44
  export interface IFormFieldBase<I extends INPUT_TYPES, P extends IFieldProps, O> {
46
45
  type: I;
47
46
  component?: Component;
48
47
  class?: any;
48
+ ui?: object | any;
49
49
  isHide?: boolean;
50
50
  props: P;
51
51
  on?: O;
@@ -15,11 +15,11 @@
15
15
  v-if="title"
16
16
  :class="[ui.header, { 'flex items-center justify-between': !isHideCloseBtn }]"
17
17
  >
18
- <h1 class="text-xl font-medium">{{ title }}</h1>
18
+ <h1 class="text-lg font-semibold">{{ title }}</h1>
19
19
  <Icon
20
20
  v-if="!isHideCloseBtn"
21
21
  name="i-heroicons-x-mark"
22
- class="h-6 w-6 cursor-pointer"
22
+ class="h-6 w-6 cursor-pointer opacity-50"
23
23
  @click="close"
24
24
  />
25
25
  </div>
@@ -31,7 +31,7 @@
31
31
  <Icon
32
32
  v-if="!isHideCloseBtn"
33
33
  name="i-heroicons-x-mark"
34
- class="h-6 w-6 cursor-pointer"
34
+ class="h-6 w-6 cursor-pointer opacity-50"
35
35
  @click="close"
36
36
  />
37
37
  </div>
@@ -4,4 +4,5 @@ export declare const core: {
4
4
  date_format: string;
5
5
  date_time_format: string;
6
6
  time_format: string;
7
+ is_thai_year: boolean;
7
8
  };
@@ -3,5 +3,6 @@ export const core = {
3
3
  default_primary_key: "id",
4
4
  date_format: "dd-MM-yyyy",
5
5
  date_time_format: "dd-MM-yyyy HH:mm",
6
- time_format: "HH:mm"
6
+ time_format: "HH:mm",
7
+ is_thai_year: false
7
8
  };
@@ -1,18 +1,20 @@
1
1
  import { modal as inheritModal } from "#ui/ui.config";
2
2
  export const modal = {
3
3
  ...inheritModal,
4
- header: "px-4 py-2 border-b",
5
- innerWrapper: "p-4",
4
+ header: "px-6 py-4 border-b",
5
+ innerWrapper: "px-6 py-4",
6
+ padding: "p-6",
7
+ margin: "my-0",
6
8
  size: {
7
- sm: "sm:max-w-sm",
8
- md: "sm:max-w-lg",
9
- lg: "sm:max-w-2xl",
10
- xl: "sm:max-w-4xl"
9
+ sm: "w-full lg:max-w-sm",
10
+ md: "w-full lg:max-w-lg",
11
+ lg: "w-full lg:max-w-2xl",
12
+ xl: "w-full lg:max-w-4xl"
11
13
  },
12
14
  position: {
13
- top: "flex min-h-full items-end sm:items-start justify-center text-center",
14
- center: "flex min-h-full items-end sm:items-center justify-center text-center",
15
- bottom: "flex min-h-full items-end sm:items-end justify-center text-center"
15
+ top: "flex min-h-full items-start justify-center text-center",
16
+ center: "flex min-h-full items-start lg:items-center justify-center text-center",
17
+ bottom: "flex min-h-full items-start lg:items-end justify-center text-center"
16
18
  },
17
19
  overlay: {
18
20
  background: "bg-gray-500/75 dark:bg-gray-800/75 backdrop-blur-sm"
@@ -1,4 +1,7 @@
1
1
  export declare class TimeHelper {
2
+ static thaiFormat: (dateStr: Date, formatStr: string) => string;
3
+ static displayDate: (time: string | Date) => string;
4
+ static displayDateTime: (time: string | Date) => string;
2
5
  static toUTC: (time: string | Date) => string;
3
6
  static toLocal: (time: string | Date) => string;
4
7
  static getCurrentDate: () => string;
@@ -1,9 +1,33 @@
1
- import { addHours, format, formatISO, isDate, isValid, parse, subHours } from "date-fns";
1
+ import { addHours, format, formatISO, isDate, isValid, parse, subHours, addYears } from "date-fns";
2
2
  import { useCoreConfig } from "#core/composables/useConfig";
3
3
  const dateFormat = useCoreConfig().date_format;
4
4
  const dateTimeFormat = useCoreConfig().date_time_format;
5
5
  const timeFormat = useCoreConfig().time_format;
6
+ const isThaiYear = useCoreConfig().is_thai_year;
6
7
  export class TimeHelper {
8
+ static thaiFormat = (dateStr, formatStr) => {
9
+ let newDateStr = dateStr;
10
+ if (isThaiYear) {
11
+ newDateStr = addYears(dateStr, 543);
12
+ }
13
+ return format(newDateStr, formatStr);
14
+ };
15
+ static displayDate = (time) => {
16
+ if (!time) {
17
+ return time;
18
+ }
19
+ const parsedTime = isDate(time) ? time : new Date(time);
20
+ const newTime = TimeHelper.thaiFormat(parsedTime, dateFormat);
21
+ return isValid(parsedTime) ? newTime : time;
22
+ };
23
+ static displayDateTime = (time) => {
24
+ if (!time) {
25
+ return time;
26
+ }
27
+ const parsedTime = isDate(time) ? time : new Date(time);
28
+ const newTime = TimeHelper.thaiFormat(parsedTime, dateTimeFormat);
29
+ return isValid(parsedTime) ? newTime : time;
30
+ };
7
31
  static toUTC = (time) => {
8
32
  if (!time) {
9
33
  return time;
@@ -4,7 +4,8 @@ vi.mock("#core/composables/useConfig", () => ({
4
4
  useCoreConfig: () => ({
5
5
  date_format: "yyyy-MM-dd",
6
6
  date_time_format: "yyyy-MM-dd HH:mm",
7
- time_format: "HH:mm"
7
+ time_format: "HH:mm",
8
+ is_thai_year: false
8
9
  })
9
10
  }));
10
11
  describe("TimeHelper", async () => {
@@ -20,6 +21,12 @@ describe("TimeHelper", async () => {
20
21
  const result = TimeHelper.toLocal(inputTime);
21
22
  assert.equal(result, expectedOutput);
22
23
  });
24
+ it("[thai year ]toLocal should convert time to local format", () => {
25
+ const inputTime = "2023-12-19 12:00";
26
+ const expectedOutput = "2023-12-19 19:00";
27
+ const result = TimeHelper.toLocal(inputTime);
28
+ assert.equal(result, expectedOutput);
29
+ });
23
30
  it("getCurrentDate should return the current date in yyyy-MM-dd format", () => {
24
31
  const expectedOutputRegex = /^\d{4}-\d{2}-\d{2}$/;
25
32
  const result = TimeHelper.getCurrentDate();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,30 @@
1
+ import { assert, describe, it, vi } from "vitest";
2
+ import { TimeHelper } from "./TimeHelper.mjs";
3
+ vi.mock("#core/composables/useConfig", () => ({
4
+ useCoreConfig: () => ({
5
+ date_format: "yyyy-MM-dd",
6
+ date_time_format: "yyyy-MM-dd HH:mm",
7
+ time_format: "HH:mm",
8
+ is_thai_year: true
9
+ })
10
+ }));
11
+ describe("TimeHelper", async () => {
12
+ it("displayDate", () => {
13
+ const inputTime = "2023-12-19 12:00";
14
+ const expectedOutput = "2566-12-19";
15
+ const result = TimeHelper.displayDate(inputTime);
16
+ assert.equal(result, expectedOutput);
17
+ });
18
+ it("displayDateTime", () => {
19
+ const inputTime = "2023-12-19 12:00";
20
+ const expectedOutput = "2566-12-19 12:00";
21
+ const result = TimeHelper.displayDateTime(inputTime);
22
+ assert.equal(result, expectedOutput);
23
+ });
24
+ it("displayDateTime - iso", () => {
25
+ const inputTime = "2023-01-16T22:00:00Z";
26
+ const expectedOutput = "2566-01-17 05:00";
27
+ const result = TimeHelper.displayDateTime(inputTime);
28
+ assert.equal(result, expectedOutput);
29
+ });
30
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finema/core",
3
- "version": "1.4.14",
3
+ "version": "1.4.16",
4
4
  "repository": "https://gitlab.finema.co/finema/ui-kit",
5
5
  "license": "MIT",
6
6
  "author": "Finema Dev Core Team",