diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..05e5a39
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,485 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = crlf
+indent_size = 4
+indent_style = space
+insert_final_newline = false
+max_line_length = 120
+tab_width = 4
+ij_continuation_indent_size = 4
+ij_formatter_off_tag = @formatter:off
+ij_formatter_on_tag = @formatter:on
+ij_formatter_tags_enabled = true
+ij_smart_tabs = false
+ij_visual_guides = none
+ij_wrap_on_typing = false
+
+[*.css]
+ij_css_align_closing_brace_with_properties = false
+ij_css_blank_lines_around_nested_selector = 1
+ij_css_blank_lines_between_blocks = 1
+ij_css_block_comment_add_space = false
+ij_css_brace_placement = end_of_line
+ij_css_enforce_quotes_on_format = false
+ij_css_hex_color_long_format = false
+ij_css_hex_color_lower_case = false
+ij_css_hex_color_short_format = false
+ij_css_hex_color_upper_case = false
+ij_css_keep_blank_lines_in_code = 2
+ij_css_keep_indents_on_empty_lines = false
+ij_css_keep_single_line_blocks = false
+ij_css_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow
+ij_css_space_after_colon = true
+ij_css_space_before_opening_brace = true
+ij_css_use_double_quotes = true
+ij_css_value_alignment = do_not_align
+
+[*.sass]
+indent_size = 2
+ij_sass_align_closing_brace_with_properties = false
+ij_sass_blank_lines_around_nested_selector = 1
+ij_sass_blank_lines_between_blocks = 1
+ij_sass_brace_placement = 0
+ij_sass_enforce_quotes_on_format = false
+ij_sass_hex_color_long_format = false
+ij_sass_hex_color_lower_case = false
+ij_sass_hex_color_short_format = false
+ij_sass_hex_color_upper_case = false
+ij_sass_keep_blank_lines_in_code = 2
+ij_sass_keep_indents_on_empty_lines = false
+ij_sass_keep_single_line_blocks = false
+ij_sass_line_comment_add_space = false
+ij_sass_line_comment_at_first_column = false
+ij_sass_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow
+ij_sass_space_after_colon = true
+ij_sass_space_before_opening_brace = true
+ij_sass_use_double_quotes = true
+ij_sass_value_alignment = 0
+
+[*.scss]
+indent_size = 2
+ij_scss_align_closing_brace_with_properties = false
+ij_scss_blank_lines_around_nested_selector = 1
+ij_scss_blank_lines_between_blocks = 1
+ij_scss_block_comment_add_space = false
+ij_scss_brace_placement = 0
+ij_scss_enforce_quotes_on_format = false
+ij_scss_hex_color_long_format = false
+ij_scss_hex_color_lower_case = false
+ij_scss_hex_color_short_format = false
+ij_scss_hex_color_upper_case = false
+ij_scss_keep_blank_lines_in_code = 2
+ij_scss_keep_indents_on_empty_lines = false
+ij_scss_keep_single_line_blocks = false
+ij_scss_line_comment_add_space = false
+ij_scss_line_comment_at_first_column = false
+ij_scss_properties_order = font, font-family, font-size, font-weight, font-style, font-variant, font-size-adjust, font-stretch, line-height, position, z-index, top, right, bottom, left, display, visibility, float, clear, overflow, overflow-x, overflow-y, clip, zoom, align-content, align-items, align-self, flex, flex-flow, flex-basis, flex-direction, flex-grow, flex-shrink, flex-wrap, justify-content, order, box-sizing, width, min-width, max-width, height, min-height, max-height, margin, margin-top, margin-right, margin-bottom, margin-left, padding, padding-top, padding-right, padding-bottom, padding-left, table-layout, empty-cells, caption-side, border-spacing, border-collapse, list-style, list-style-position, list-style-type, list-style-image, content, quotes, counter-reset, counter-increment, resize, cursor, user-select, nav-index, nav-up, nav-right, nav-down, nav-left, transition, transition-delay, transition-timing-function, transition-duration, transition-property, transform, transform-origin, animation, animation-name, animation-duration, animation-play-state, animation-timing-function, animation-delay, animation-iteration-count, animation-direction, text-align, text-align-last, vertical-align, white-space, text-decoration, text-emphasis, text-emphasis-color, text-emphasis-style, text-emphasis-position, text-indent, text-justify, letter-spacing, word-spacing, text-outline, text-transform, text-wrap, text-overflow, text-overflow-ellipsis, text-overflow-mode, word-wrap, word-break, tab-size, hyphens, pointer-events, opacity, color, border, border-width, border-style, border-color, border-top, border-top-width, border-top-style, border-top-color, border-right, border-right-width, border-right-style, border-right-color, border-bottom, border-bottom-width, border-bottom-style, border-bottom-color, border-left, border-left-width, border-left-style, border-left-color, border-radius, border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-image, border-image-source, border-image-slice, border-image-width, border-image-outset, border-image-repeat, outline, outline-width, outline-style, outline-color, outline-offset, background, background-color, background-image, background-repeat, background-attachment, background-position, background-position-x, background-position-y, background-clip, background-origin, background-size, box-decoration-break, box-shadow, text-shadow
+ij_scss_space_after_colon = true
+ij_scss_space_before_opening_brace = true
+ij_scss_use_double_quotes = true
+ij_scss_value_alignment = 0
+
+[{*.ats,*.cts,*.mts,*.ts}]
+ij_continuation_indent_size = 4
+ij_typescript_align_imports = false
+ij_typescript_align_multiline_array_initializer_expression = false
+ij_typescript_align_multiline_binary_operation = false
+ij_typescript_align_multiline_chained_methods = false
+ij_typescript_align_multiline_extends_list = false
+ij_typescript_align_multiline_for = true
+ij_typescript_align_multiline_parameters = true
+ij_typescript_align_multiline_parameters_in_calls = false
+ij_typescript_align_multiline_ternary_operation = false
+ij_typescript_align_object_properties = 0
+ij_typescript_align_union_types = false
+ij_typescript_align_var_statements = 0
+ij_typescript_array_initializer_new_line_after_left_brace = false
+ij_typescript_array_initializer_right_brace_on_new_line = false
+ij_typescript_array_initializer_wrap = off
+ij_typescript_assignment_wrap = off
+ij_typescript_binary_operation_sign_on_next_line = false
+ij_typescript_binary_operation_wrap = off
+ij_typescript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/**
+ij_typescript_blank_lines_after_imports = 1
+ij_typescript_blank_lines_around_class = 1
+ij_typescript_blank_lines_around_field = 0
+ij_typescript_blank_lines_around_field_in_interface = 0
+ij_typescript_blank_lines_around_function = 1
+ij_typescript_blank_lines_around_method = 1
+ij_typescript_blank_lines_around_method_in_interface = 1
+ij_typescript_block_brace_style = end_of_line
+ij_typescript_block_comment_add_space = false
+ij_typescript_block_comment_at_first_column = true
+ij_typescript_call_parameters_new_line_after_left_paren = false
+ij_typescript_call_parameters_right_paren_on_new_line = false
+ij_typescript_call_parameters_wrap = off
+ij_typescript_catch_on_new_line = false
+ij_typescript_chained_call_dot_on_new_line = true
+ij_typescript_class_brace_style = end_of_line
+ij_typescript_comma_on_new_line = false
+ij_typescript_do_while_brace_force = never
+ij_typescript_else_on_new_line = false
+ij_typescript_enforce_trailing_comma = keep
+ij_typescript_enum_constants_wrap = on_every_item
+ij_typescript_extends_keyword_wrap = off
+ij_typescript_extends_list_wrap = off
+ij_typescript_field_prefix = _
+ij_typescript_file_name_style = relaxed
+ij_typescript_finally_on_new_line = false
+ij_typescript_for_brace_force = never
+ij_typescript_for_statement_new_line_after_left_paren = false
+ij_typescript_for_statement_right_paren_on_new_line = false
+ij_typescript_for_statement_wrap = off
+ij_typescript_force_quote_style = false
+ij_typescript_force_semicolon_style = false
+ij_typescript_function_expression_brace_style = end_of_line
+ij_typescript_if_brace_force = never
+ij_typescript_import_merge_members = global
+ij_typescript_import_prefer_absolute_path = global
+ij_typescript_import_sort_members = true
+ij_typescript_import_sort_module_name = false
+ij_typescript_import_use_node_resolution = true
+ij_typescript_imports_wrap = on_every_item
+ij_typescript_indent_case_from_switch = true
+ij_typescript_indent_chained_calls = true
+ij_typescript_indent_package_children = 0
+ij_typescript_jsdoc_include_types = false
+ij_typescript_jsx_attribute_value = braces
+ij_typescript_keep_blank_lines_in_code = 2
+ij_typescript_keep_first_column_comment = true
+ij_typescript_keep_indents_on_empty_lines = false
+ij_typescript_keep_line_breaks = true
+ij_typescript_keep_simple_blocks_in_one_line = false
+ij_typescript_keep_simple_methods_in_one_line = false
+ij_typescript_line_comment_add_space = true
+ij_typescript_line_comment_at_first_column = false
+ij_typescript_method_brace_style = end_of_line
+ij_typescript_method_call_chain_wrap = off
+ij_typescript_method_parameters_new_line_after_left_paren = false
+ij_typescript_method_parameters_right_paren_on_new_line = false
+ij_typescript_method_parameters_wrap = off
+ij_typescript_object_literal_wrap = on_every_item
+ij_typescript_object_types_wrap = on_every_item
+ij_typescript_parentheses_expression_new_line_after_left_paren = false
+ij_typescript_parentheses_expression_right_paren_on_new_line = false
+ij_typescript_place_assignment_sign_on_next_line = false
+ij_typescript_prefer_as_type_cast = false
+ij_typescript_prefer_explicit_types_function_expression_returns = false
+ij_typescript_prefer_explicit_types_function_returns = false
+ij_typescript_prefer_explicit_types_vars_fields = false
+ij_typescript_prefer_parameters_wrap = false
+ij_typescript_reformat_c_style_comments = false
+ij_typescript_space_after_colon = true
+ij_typescript_space_after_comma = true
+ij_typescript_space_after_dots_in_rest_parameter = false
+ij_typescript_space_after_generator_mult = true
+ij_typescript_space_after_property_colon = true
+ij_typescript_space_after_quest = true
+ij_typescript_space_after_type_colon = true
+ij_typescript_space_after_unary_not = false
+ij_typescript_space_before_async_arrow_lparen = true
+ij_typescript_space_before_catch_keyword = true
+ij_typescript_space_before_catch_left_brace = true
+ij_typescript_space_before_catch_parentheses = true
+ij_typescript_space_before_class_lbrace = true
+ij_typescript_space_before_class_left_brace = true
+ij_typescript_space_before_colon = true
+ij_typescript_space_before_comma = false
+ij_typescript_space_before_do_left_brace = true
+ij_typescript_space_before_else_keyword = true
+ij_typescript_space_before_else_left_brace = true
+ij_typescript_space_before_finally_keyword = true
+ij_typescript_space_before_finally_left_brace = true
+ij_typescript_space_before_for_left_brace = true
+ij_typescript_space_before_for_parentheses = true
+ij_typescript_space_before_for_semicolon = false
+ij_typescript_space_before_function_left_parenth = true
+ij_typescript_space_before_generator_mult = false
+ij_typescript_space_before_if_left_brace = true
+ij_typescript_space_before_if_parentheses = true
+ij_typescript_space_before_method_call_parentheses = false
+ij_typescript_space_before_method_left_brace = true
+ij_typescript_space_before_method_parentheses = false
+ij_typescript_space_before_property_colon = false
+ij_typescript_space_before_quest = true
+ij_typescript_space_before_switch_left_brace = true
+ij_typescript_space_before_switch_parentheses = true
+ij_typescript_space_before_try_left_brace = true
+ij_typescript_space_before_type_colon = false
+ij_typescript_space_before_unary_not = false
+ij_typescript_space_before_while_keyword = true
+ij_typescript_space_before_while_left_brace = true
+ij_typescript_space_before_while_parentheses = true
+ij_typescript_spaces_around_additive_operators = true
+ij_typescript_spaces_around_arrow_function_operator = true
+ij_typescript_spaces_around_assignment_operators = true
+ij_typescript_spaces_around_bitwise_operators = true
+ij_typescript_spaces_around_equality_operators = true
+ij_typescript_spaces_around_logical_operators = true
+ij_typescript_spaces_around_multiplicative_operators = true
+ij_typescript_spaces_around_relational_operators = true
+ij_typescript_spaces_around_shift_operators = true
+ij_typescript_spaces_around_unary_operator = false
+ij_typescript_spaces_within_array_initializer_brackets = false
+ij_typescript_spaces_within_brackets = false
+ij_typescript_spaces_within_catch_parentheses = false
+ij_typescript_spaces_within_for_parentheses = false
+ij_typescript_spaces_within_if_parentheses = false
+ij_typescript_spaces_within_imports = false
+ij_typescript_spaces_within_interpolation_expressions = false
+ij_typescript_spaces_within_method_call_parentheses = false
+ij_typescript_spaces_within_method_parentheses = false
+ij_typescript_spaces_within_object_literal_braces = false
+ij_typescript_spaces_within_object_type_braces = true
+ij_typescript_spaces_within_parentheses = false
+ij_typescript_spaces_within_switch_parentheses = false
+ij_typescript_spaces_within_type_assertion = false
+ij_typescript_spaces_within_union_types = true
+ij_typescript_spaces_within_while_parentheses = false
+ij_typescript_special_else_if_treatment = true
+ij_typescript_ternary_operation_signs_on_next_line = false
+ij_typescript_ternary_operation_wrap = off
+ij_typescript_union_types_wrap = on_every_item
+ij_typescript_use_chained_calls_group_indents = false
+ij_typescript_use_double_quotes = true
+ij_typescript_use_explicit_js_extension = auto
+ij_typescript_use_path_mapping = always
+ij_typescript_use_public_modifier = false
+ij_typescript_use_semicolon_after_statement = true
+ij_typescript_var_declaration_wrap = normal
+ij_typescript_while_brace_force = never
+ij_typescript_while_on_new_line = false
+ij_typescript_wrap_comments = false
+
+[{*.cjs,*.js}]
+ij_continuation_indent_size = 4
+ij_javascript_align_imports = false
+ij_javascript_align_multiline_array_initializer_expression = false
+ij_javascript_align_multiline_binary_operation = false
+ij_javascript_align_multiline_chained_methods = false
+ij_javascript_align_multiline_extends_list = false
+ij_javascript_align_multiline_for = true
+ij_javascript_align_multiline_parameters = true
+ij_javascript_align_multiline_parameters_in_calls = false
+ij_javascript_align_multiline_ternary_operation = false
+ij_javascript_align_object_properties = 0
+ij_javascript_align_union_types = false
+ij_javascript_align_var_statements = 0
+ij_javascript_array_initializer_new_line_after_left_brace = false
+ij_javascript_array_initializer_right_brace_on_new_line = false
+ij_javascript_array_initializer_wrap = off
+ij_javascript_assignment_wrap = off
+ij_javascript_binary_operation_sign_on_next_line = false
+ij_javascript_binary_operation_wrap = off
+ij_javascript_blacklist_imports = rxjs/Rx, node_modules/**, **/node_modules/**, @angular/material, @angular/material/typings/**
+ij_javascript_blank_lines_after_imports = 1
+ij_javascript_blank_lines_around_class = 1
+ij_javascript_blank_lines_around_field = 0
+ij_javascript_blank_lines_around_function = 1
+ij_javascript_blank_lines_around_method = 1
+ij_javascript_block_brace_style = end_of_line
+ij_javascript_block_comment_add_space = false
+ij_javascript_block_comment_at_first_column = true
+ij_javascript_call_parameters_new_line_after_left_paren = false
+ij_javascript_call_parameters_right_paren_on_new_line = false
+ij_javascript_call_parameters_wrap = off
+ij_javascript_catch_on_new_line = false
+ij_javascript_chained_call_dot_on_new_line = true
+ij_javascript_class_brace_style = end_of_line
+ij_javascript_comma_on_new_line = false
+ij_javascript_do_while_brace_force = never
+ij_javascript_else_on_new_line = false
+ij_javascript_enforce_trailing_comma = keep
+ij_javascript_extends_keyword_wrap = off
+ij_javascript_extends_list_wrap = off
+ij_javascript_field_prefix = _
+ij_javascript_file_name_style = relaxed
+ij_javascript_finally_on_new_line = false
+ij_javascript_for_brace_force = never
+ij_javascript_for_statement_new_line_after_left_paren = false
+ij_javascript_for_statement_right_paren_on_new_line = false
+ij_javascript_for_statement_wrap = off
+ij_javascript_force_quote_style = false
+ij_javascript_force_semicolon_style = false
+ij_javascript_function_expression_brace_style = end_of_line
+ij_javascript_if_brace_force = never
+ij_javascript_import_merge_members = global
+ij_javascript_import_prefer_absolute_path = global
+ij_javascript_import_sort_members = true
+ij_javascript_import_sort_module_name = false
+ij_javascript_import_use_node_resolution = true
+ij_javascript_imports_wrap = on_every_item
+ij_javascript_indent_case_from_switch = true
+ij_javascript_indent_chained_calls = true
+ij_javascript_indent_package_children = 0
+ij_javascript_jsx_attribute_value = braces
+ij_javascript_keep_blank_lines_in_code = 2
+ij_javascript_keep_first_column_comment = true
+ij_javascript_keep_indents_on_empty_lines = false
+ij_javascript_keep_line_breaks = true
+ij_javascript_keep_simple_blocks_in_one_line = false
+ij_javascript_keep_simple_methods_in_one_line = false
+ij_javascript_line_comment_add_space = true
+ij_javascript_line_comment_at_first_column = false
+ij_javascript_method_brace_style = end_of_line
+ij_javascript_method_call_chain_wrap = off
+ij_javascript_method_parameters_new_line_after_left_paren = false
+ij_javascript_method_parameters_right_paren_on_new_line = false
+ij_javascript_method_parameters_wrap = off
+ij_javascript_object_literal_wrap = on_every_item
+ij_javascript_object_types_wrap = on_every_item
+ij_javascript_parentheses_expression_new_line_after_left_paren = false
+ij_javascript_parentheses_expression_right_paren_on_new_line = false
+ij_javascript_place_assignment_sign_on_next_line = false
+ij_javascript_prefer_as_type_cast = false
+ij_javascript_prefer_explicit_types_function_expression_returns = false
+ij_javascript_prefer_explicit_types_function_returns = false
+ij_javascript_prefer_explicit_types_vars_fields = false
+ij_javascript_prefer_parameters_wrap = false
+ij_javascript_reformat_c_style_comments = false
+ij_javascript_space_after_colon = true
+ij_javascript_space_after_comma = true
+ij_javascript_space_after_dots_in_rest_parameter = false
+ij_javascript_space_after_generator_mult = true
+ij_javascript_space_after_property_colon = true
+ij_javascript_space_after_quest = true
+ij_javascript_space_after_type_colon = true
+ij_javascript_space_after_unary_not = false
+ij_javascript_space_before_async_arrow_lparen = true
+ij_javascript_space_before_catch_keyword = true
+ij_javascript_space_before_catch_left_brace = true
+ij_javascript_space_before_catch_parentheses = true
+ij_javascript_space_before_class_lbrace = true
+ij_javascript_space_before_class_left_brace = true
+ij_javascript_space_before_colon = true
+ij_javascript_space_before_comma = false
+ij_javascript_space_before_do_left_brace = true
+ij_javascript_space_before_else_keyword = true
+ij_javascript_space_before_else_left_brace = true
+ij_javascript_space_before_finally_keyword = true
+ij_javascript_space_before_finally_left_brace = true
+ij_javascript_space_before_for_left_brace = true
+ij_javascript_space_before_for_parentheses = true
+ij_javascript_space_before_for_semicolon = false
+ij_javascript_space_before_function_left_parenth = true
+ij_javascript_space_before_generator_mult = false
+ij_javascript_space_before_if_left_brace = true
+ij_javascript_space_before_if_parentheses = true
+ij_javascript_space_before_method_call_parentheses = false
+ij_javascript_space_before_method_left_brace = true
+ij_javascript_space_before_method_parentheses = false
+ij_javascript_space_before_property_colon = false
+ij_javascript_space_before_quest = true
+ij_javascript_space_before_switch_left_brace = true
+ij_javascript_space_before_switch_parentheses = true
+ij_javascript_space_before_try_left_brace = true
+ij_javascript_space_before_type_colon = false
+ij_javascript_space_before_unary_not = false
+ij_javascript_space_before_while_keyword = true
+ij_javascript_space_before_while_left_brace = true
+ij_javascript_space_before_while_parentheses = true
+ij_javascript_spaces_around_additive_operators = true
+ij_javascript_spaces_around_arrow_function_operator = true
+ij_javascript_spaces_around_assignment_operators = true
+ij_javascript_spaces_around_bitwise_operators = true
+ij_javascript_spaces_around_equality_operators = true
+ij_javascript_spaces_around_logical_operators = true
+ij_javascript_spaces_around_multiplicative_operators = true
+ij_javascript_spaces_around_relational_operators = true
+ij_javascript_spaces_around_shift_operators = true
+ij_javascript_spaces_around_unary_operator = false
+ij_javascript_spaces_within_array_initializer_brackets = false
+ij_javascript_spaces_within_brackets = false
+ij_javascript_spaces_within_catch_parentheses = false
+ij_javascript_spaces_within_for_parentheses = false
+ij_javascript_spaces_within_if_parentheses = false
+ij_javascript_spaces_within_imports = false
+ij_javascript_spaces_within_interpolation_expressions = false
+ij_javascript_spaces_within_method_call_parentheses = false
+ij_javascript_spaces_within_method_parentheses = false
+ij_javascript_spaces_within_object_literal_braces = false
+ij_javascript_spaces_within_object_type_braces = true
+ij_javascript_spaces_within_parentheses = false
+ij_javascript_spaces_within_switch_parentheses = false
+ij_javascript_spaces_within_type_assertion = false
+ij_javascript_spaces_within_union_types = true
+ij_javascript_spaces_within_while_parentheses = false
+ij_javascript_special_else_if_treatment = true
+ij_javascript_ternary_operation_signs_on_next_line = false
+ij_javascript_ternary_operation_wrap = off
+ij_javascript_union_types_wrap = on_every_item
+ij_javascript_use_chained_calls_group_indents = false
+ij_javascript_use_double_quotes = true
+ij_javascript_use_explicit_js_extension = auto
+ij_javascript_use_path_mapping = always
+ij_javascript_use_public_modifier = false
+ij_javascript_use_semicolon_after_statement = true
+ij_javascript_var_declaration_wrap = normal
+ij_javascript_while_brace_force = never
+ij_javascript_while_on_new_line = false
+ij_javascript_wrap_comments = false
+
+[{*.har,*.jsb2,*.jsb3,*.json,.babelrc,.eslintrc,.prettierrc,.stylelintrc,bowerrc,jest.config}]
+indent_size = 2
+ij_json_array_wrapping = split_into_lines
+ij_json_keep_blank_lines_in_code = 0
+ij_json_keep_indents_on_empty_lines = false
+ij_json_keep_line_breaks = true
+ij_json_keep_trailing_comma = false
+ij_json_object_wrapping = split_into_lines
+ij_json_property_alignment = do_not_align
+ij_json_space_after_colon = true
+ij_json_space_after_comma = true
+ij_json_space_before_colon = false
+ij_json_space_before_comma = false
+ij_json_spaces_within_braces = false
+ij_json_spaces_within_brackets = false
+ij_json_wrap_long_lines = false
+
+[{*.htm,*.html,*.ng,*.sht,*.shtm,*.shtml}]
+ij_html_add_new_line_before_tags = body, div, p, form, h1, h2, h3
+ij_html_align_attributes = true
+ij_html_align_text = false
+ij_html_attribute_wrap = normal
+ij_html_block_comment_add_space = false
+ij_html_block_comment_at_first_column = true
+ij_html_do_not_align_children_of_min_lines = 0
+ij_html_do_not_break_if_inline_tags = title, h1, h2, h3, h4, h5, h6, p
+ij_html_do_not_indent_children_of_tags = html, body, thead, tbody, tfoot
+ij_html_enforce_quotes = false
+ij_html_inline_tags = a, abbr, acronym, b, basefont, bdo, big, br, cite, cite, code, dfn, em, font, i, img, input, kbd, label, q, s, samp, select, small, span, strike, strong, sub, sup, textarea, tt, u, var
+ij_html_keep_blank_lines = 2
+ij_html_keep_indents_on_empty_lines = false
+ij_html_keep_line_breaks = true
+ij_html_keep_line_breaks_in_text = true
+ij_html_keep_whitespaces = false
+ij_html_keep_whitespaces_inside = span, pre, textarea
+ij_html_line_comment_at_first_column = true
+ij_html_new_line_after_last_attribute = never
+ij_html_new_line_before_first_attribute = never
+ij_html_quote_style = double
+ij_html_remove_new_line_before_tags = br
+ij_html_space_after_tag_name = false
+ij_html_space_around_equality_in_attribute = false
+ij_html_space_inside_empty_tag = false
+ij_html_text_wrap = normal
+
+[{*.markdown,*.md}]
+ij_markdown_force_one_space_after_blockquote_symbol = true
+ij_markdown_force_one_space_after_header_symbol = true
+ij_markdown_force_one_space_after_list_bullet = true
+ij_markdown_force_one_space_between_words = true
+ij_markdown_format_tables = true
+ij_markdown_insert_quote_arrows_on_wrap = true
+ij_markdown_keep_indents_on_empty_lines = false
+ij_markdown_keep_line_breaks_inside_text_blocks = true
+ij_markdown_max_lines_around_block_elements = 1
+ij_markdown_max_lines_around_header = 1
+ij_markdown_max_lines_between_paragraphs = 1
+ij_markdown_min_lines_around_block_elements = 1
+ij_markdown_min_lines_around_header = 1
+ij_markdown_min_lines_between_paragraphs = 1
+ij_markdown_wrap_text_if_long = true
+ij_markdown_wrap_text_inside_blockquotes = true
diff --git a/.gitignore b/.gitignore
index e9618a3..78b977c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
node_modules
.next
-.env.local
\ No newline at end of file
+.env.local
+.idea
+package-lock.json
\ No newline at end of file
diff --git a/example.env.local b/example.env.local
index 2b26da5..2c06285 100644
--- a/example.env.local
+++ b/example.env.local
@@ -1,9 +1,11 @@
NEXT_PUBLIC_API_NAME = "Loan Facilities Dashboard"
+NEXT_PUBLIC_API_VERSION = "1.0.0"
NEXT_PUBLIC_DEFAULT_LANGUAGE = "fa"
NEXT_PUBLIC_DEFAULT_DIRECTION = "rtl"
-NEXT_PUBLIC_API_URL = "http://Your IP:3000"
+NEXT_PUBLIC_PRIMARY_MAIN = "#084070"
+NEXT_PUBLIC_SECONDARY_MAIN = "#FF4E00"
-NEXT_PUBLIC_BASE_URL = "deploy api"
+NEXT_PUBLIC_BASE_URL = "https://loan.witel.ir"
NODE_ENV = "development"
\ No newline at end of file
diff --git a/jsconfig.json b/jsconfig.json
index f6a30b1..fcd02aa 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -1,8 +1,12 @@
{
"compilerOptions": {
"paths": {
- "@/*": ["./src/*"],
- "&/*": ["./public/*"],
+ "@/*": [
+ "./src/*"
+ ],
+ "&/*": [
+ "./public/*"
+ ]
}
}
}
diff --git a/next.config.js b/next.config.js
index 03fb527..a288e34 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,12 +1,12 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
- reactStrictMode: true,
- i18n: {
- defaultLocale: 'fa',
- locales: ['fa'],
- localeDetection: false,
- },
+ reactStrictMode: true,
+ i18n: {
+ defaultLocale: 'fa',
+ locales: ['fa'],
+ localeDetection: false,
+ }
}
module.exports = nextConfig
diff --git a/package-lock.json b/package-lock.json
index 2f1e600..42161b1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,12 +13,20 @@
"@emotion/styled": "^11.10.6",
"@mui/icons-material": "^5.11.16",
"@mui/material": "^5.12.0",
+ "@mui/x-date-pickers": "^6.9.2",
"axios": "^1.4.0",
+ "colord": "^2.9.3",
+ "date-fns-jalali": "^2.13.0-0",
+ "dayjs": "^1.11.9",
"eslint": "8.36.0",
"formik": "^2.2.9",
"fs-extra": "^11.1.1",
+ "image-resize": "^1.3.2",
+ "image-to-file-converter": "^1.0.6",
+ "jalali-moment": "^3.3.11",
"material-react-table": "^1.11.1",
"moment": "^2.29.4",
+ "moment-jalaali": "^0.10.0",
"next": "^13.3.0",
"next-intl": "^2.13.1",
"next-useragent": "^2.8.0",
@@ -154,9 +162,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.21.0",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
- "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
+ "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
@@ -729,13 +737,13 @@
}
},
"node_modules/@mui/utils": {
- "version": "5.12.0",
- "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.12.0.tgz",
- "integrity": "sha512-RmQwgzF72p7Yr4+AAUO6j1v2uzt6wr7SWXn68KBsnfVpdOHyclCzH2lr/Xu6YOw9su4JRtdAIYfJFXsS6Cjkmw==",
+ "version": "5.13.7",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.7.tgz",
+ "integrity": "sha512-/3BLptG/q0u36eYED7Nhf4fKXmcKb6LjjT7ZMwhZIZSdSxVqDqSTmATW3a56n3KEPQUXCU9TpxAfCBQhs6brVA==",
"dependencies": {
- "@babel/runtime": "^7.21.0",
+ "@babel/runtime": "^7.22.5",
"@types/prop-types": "^15.7.5",
- "@types/react-is": "^16.7.1 || ^17.0.0",
+ "@types/react-is": "^18.2.1",
"prop-types": "^15.8.1",
"react-is": "^18.2.0"
},
@@ -755,6 +763,71 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
+ "node_modules/@mui/x-date-pickers": {
+ "version": "6.9.2",
+ "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.9.2.tgz",
+ "integrity": "sha512-WoXRBUwb/nN/Hg+rArefkuRe30eVTN29dbjTN/vTydBFoNIp8vCaSeqRIEP6Zq2NaDHFWW9FMGChuuFEdROxWA==",
+ "dependencies": {
+ "@babel/runtime": "^7.22.5",
+ "@mui/utils": "^5.13.6",
+ "@types/react-transition-group": "^4.4.6",
+ "clsx": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "react-transition-group": "^4.4.5"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mui"
+ },
+ "peerDependencies": {
+ "@emotion/react": "^11.9.0",
+ "@emotion/styled": "^11.8.1",
+ "@mui/base": "^5.0.0-alpha.87",
+ "@mui/material": "^5.8.6",
+ "@mui/system": "^5.8.0",
+ "date-fns": "^2.25.0",
+ "date-fns-jalali": "^2.13.0-0",
+ "dayjs": "^1.10.7",
+ "luxon": "^3.0.2",
+ "moment": "^2.29.4",
+ "moment-hijri": "^2.1.2",
+ "moment-jalaali": "^0.7.4 || ^0.8.0 || ^0.9.0 || ^0.10.0",
+ "react": "^17.0.0 || ^18.0.0",
+ "react-dom": "^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/react": {
+ "optional": true
+ },
+ "@emotion/styled": {
+ "optional": true
+ },
+ "date-fns": {
+ "optional": true
+ },
+ "date-fns-jalali": {
+ "optional": true
+ },
+ "dayjs": {
+ "optional": true
+ },
+ "luxon": {
+ "optional": true
+ },
+ "moment": {
+ "optional": true
+ },
+ "moment-hijri": {
+ "optional": true
+ },
+ "moment-jalaali": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@next/env": {
"version": "13.3.0",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.0.tgz",
@@ -1081,17 +1154,17 @@
}
},
"node_modules/@types/react-is": {
- "version": "17.0.3",
- "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz",
- "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-18.2.1.tgz",
+ "integrity": "sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw==",
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/react-transition-group": {
- "version": "4.4.5",
- "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz",
- "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==",
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz",
+ "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==",
"dependencies": {
"@types/react": "*"
}
@@ -1236,6 +1309,31 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-escapes/node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -1431,6 +1529,25 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@@ -1439,6 +1556,56 @@
"node": ">=8"
}
},
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bl/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bl/node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/bl/node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1459,6 +1626,29 @@
"node": ">=8"
}
},
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"node_modules/buffer-from": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
@@ -1526,6 +1716,11 @@
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+ },
"node_modules/chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -1563,11 +1758,49 @@
"node": ">= 6"
}
},
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-spinners": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz",
+ "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==",
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
+ "node_modules/clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
"node_modules/clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
@@ -1592,6 +1825,11 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "node_modules/colord": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
+ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="
+ },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -1603,6 +1841,14 @@
"node": ">= 0.8"
}
},
+ "node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -1665,6 +1911,16 @@
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
"dev": true
},
+ "node_modules/date-fns-jalali": {
+ "version": "2.13.0-0",
+ "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-2.13.0-0.tgz",
+ "integrity": "sha512-yjlI9O18Z6ryGNagryrLO8OQ+3rishM3+A0UOX2UX10cWMn2NTlQcQ+ywTEJvF5IJz0FwX/slt2nCcpyQ/c8gw=="
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.9",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
+ "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA=="
+ },
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -1722,6 +1978,17 @@
"node": ">=0.10.0"
}
},
+ "node_modules/defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "dependencies": {
+ "clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/define-lazy-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
@@ -2402,6 +2669,19 @@
"node": ">=0.10.0"
}
},
+ "node_modules/external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "dependencies": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -2453,6 +2733,28 @@
"reusify": "^1.0.4"
}
},
+ "node_modules/figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/figures/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
"node_modules/file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -2894,6 +3196,36 @@
"html-tokenize": "bin/cmd.js"
}
},
+ "node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
"node_modules/ignore": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
@@ -2902,6 +3234,16 @@
"node": ">= 4"
}
},
+ "node_modules/image-resize": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/image-resize/-/image-resize-1.3.2.tgz",
+ "integrity": "sha512-mbWBO4Fh+dsM5Nvj+ob01JE2gzla043PxilytGSMYUluOKEkVs1nhu2JwZ1dpRwwkYDkEOJENgm834LuunlIOQ=="
+ },
+ "node_modules/image-to-file-converter": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/image-to-file-converter/-/image-to-file-converter-1.0.6.tgz",
+ "integrity": "sha512-CokQCAEtUHGOmc537r9yZHCi4UTxOnpUQ7JPcIGRjOntTEVlT7uNpmP1YuhUT/53ufEsxk9C+ReU23zhO/b+6Q=="
+ },
"node_modules/immutable": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
@@ -2944,6 +3286,31 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "node_modules/inquirer": {
+ "version": "8.2.5",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz",
+ "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==",
+ "dependencies": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.1",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "0.0.8",
+ "ora": "^5.4.1",
+ "run-async": "^2.4.0",
+ "rxjs": "^7.5.5",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
"node_modules/internal-slot": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
@@ -3121,6 +3488,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -3132,6 +3507,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
@@ -3270,6 +3653,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/is-weakmap": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
@@ -3327,6 +3721,24 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
+ "node_modules/jalaali-js": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/jalaali-js/-/jalaali-js-1.2.6.tgz",
+ "integrity": "sha512-io974va+Qyu+UfuVX3UIAgJlxLhAMx9Y8VMfh+IG00Js7hXQo1qNQuwSiSa0xxco0SVgx5HWNkaiCcV+aZ8WPw=="
+ },
+ "node_modules/jalali-moment": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/jalali-moment/-/jalali-moment-3.3.11.tgz",
+ "integrity": "sha512-tdSaRs9cjWjOIaWhcsGFZMhZQhfgok5J0TwqFpBIZPudZxxa6yjUPoLCOwuvbAtRpiZn7k/mvazAJh+vEN5suw==",
+ "dependencies": {
+ "commander": "^7.0.0",
+ "inquirer": "^8.0.0",
+ "moment": "^2.26.0"
+ },
+ "bin": {
+ "jalalim": "cli.js"
+ }
+ },
"node_modules/js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
@@ -3464,6 +3876,21 @@
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -3554,6 +3981,14 @@
"node": ">= 0.6"
}
},
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -3581,6 +4016,28 @@
"node": "*"
}
},
+ "node_modules/moment-jalaali": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/moment-jalaali/-/moment-jalaali-0.10.0.tgz",
+ "integrity": "sha512-XICH1+UHd3zyaE1bXWQBlhoXBqbzEyFfT0TrifNobHxLALRuTSwXn376bX8FmkYg9mZimevwwdd6EB57s5wuFA==",
+ "dependencies": {
+ "jalaali-js": "^1.1.0",
+ "moment": "^2.22.2",
+ "moment-timezone": "^0.5.21",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "node_modules/moment-timezone": {
+ "version": "0.5.43",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz",
+ "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==",
+ "dependencies": {
+ "moment": "^2.29.4"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -3595,6 +4052,11 @@
"object-assign": "^4.1.0"
}
},
+ "node_modules/mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+ },
"node_modules/nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
@@ -3855,6 +4317,20 @@
"wrappy": "1"
}
},
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/open": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
@@ -3888,6 +4364,36 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "dependencies": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -4218,6 +4724,18 @@
"node": ">=4"
}
},
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/reusify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
@@ -4241,6 +4759,14 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -4263,6 +4789,14 @@
"queue-microtask": "^1.2.2"
}
},
+ "node_modules/rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
"node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -4282,6 +4816,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
"node_modules/sass": {
"version": "1.62.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.62.0.tgz",
@@ -4354,6 +4893,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -4404,6 +4948,24 @@
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
},
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
"node_modules/string.prototype.matchall": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
@@ -4617,6 +5179,17 @@
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
+ "node_modules/tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "dependencies": {
+ "os-tmpdir": "~1.0.2"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
"node_modules/to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -4806,6 +5379,14 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -4879,6 +5460,22 @@
"node": ">=0.10.0"
}
},
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@@ -5037,9 +5634,9 @@
}
},
"@babel/runtime": {
- "version": "7.21.0",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz",
- "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==",
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
+ "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"requires": {
"regenerator-runtime": "^0.13.11"
}
@@ -5425,13 +6022,13 @@
"requires": {}
},
"@mui/utils": {
- "version": "5.12.0",
- "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.12.0.tgz",
- "integrity": "sha512-RmQwgzF72p7Yr4+AAUO6j1v2uzt6wr7SWXn68KBsnfVpdOHyclCzH2lr/Xu6YOw9su4JRtdAIYfJFXsS6Cjkmw==",
+ "version": "5.13.7",
+ "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.7.tgz",
+ "integrity": "sha512-/3BLptG/q0u36eYED7Nhf4fKXmcKb6LjjT7ZMwhZIZSdSxVqDqSTmATW3a56n3KEPQUXCU9TpxAfCBQhs6brVA==",
"requires": {
- "@babel/runtime": "^7.21.0",
+ "@babel/runtime": "^7.22.5",
"@types/prop-types": "^15.7.5",
- "@types/react-is": "^16.7.1 || ^17.0.0",
+ "@types/react-is": "^18.2.1",
"prop-types": "^15.8.1",
"react-is": "^18.2.0"
},
@@ -5443,6 +6040,19 @@
}
}
},
+ "@mui/x-date-pickers": {
+ "version": "6.9.2",
+ "resolved": "https://registry.npmjs.org/@mui/x-date-pickers/-/x-date-pickers-6.9.2.tgz",
+ "integrity": "sha512-WoXRBUwb/nN/Hg+rArefkuRe30eVTN29dbjTN/vTydBFoNIp8vCaSeqRIEP6Zq2NaDHFWW9FMGChuuFEdROxWA==",
+ "requires": {
+ "@babel/runtime": "^7.22.5",
+ "@mui/utils": "^5.13.6",
+ "@types/react-transition-group": "^4.4.6",
+ "clsx": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "react-transition-group": "^4.4.5"
+ }
+ },
"@next/env": {
"version": "13.3.0",
"resolved": "https://registry.npmjs.org/@next/env/-/env-13.3.0.tgz",
@@ -5633,17 +6243,17 @@
}
},
"@types/react-is": {
- "version": "17.0.3",
- "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-17.0.3.tgz",
- "integrity": "sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==",
+ "version": "18.2.1",
+ "resolved": "https://registry.npmjs.org/@types/react-is/-/react-is-18.2.1.tgz",
+ "integrity": "sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw==",
"requires": {
"@types/react": "*"
}
},
"@types/react-transition-group": {
- "version": "4.4.5",
- "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz",
- "integrity": "sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==",
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.6.tgz",
+ "integrity": "sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==",
"requires": {
"@types/react": "*"
}
@@ -5728,6 +6338,21 @@
"uri-js": "^4.2.2"
}
},
+ "ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "requires": {
+ "type-fest": "^0.21.3"
+ },
+ "dependencies": {
+ "type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="
+ }
+ }
+ },
"ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
@@ -5877,11 +6502,51 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+ },
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
},
+ "bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "requires": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ },
+ "string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "requires": {
+ "safe-buffer": "~5.2.0"
+ }
+ }
+ }
+ },
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -5899,6 +6564,15 @@
"fill-range": "^7.0.1"
}
},
+ "buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "requires": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
"buffer-from": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz",
@@ -5941,6 +6615,11 @@
"supports-color": "^7.1.0"
}
},
+ "chardet": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
+ "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="
+ },
"chokidar": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
@@ -5966,11 +6645,34 @@
}
}
},
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-spinners": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz",
+ "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g=="
+ },
+ "cli-width": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+ "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw=="
+ },
"client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
"integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
},
+ "clone": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="
+ },
"clsx": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
@@ -5989,6 +6691,11 @@
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
+ "colord": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
+ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="
+ },
"combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -5997,6 +6704,11 @@
"delayed-stream": "~1.0.0"
}
},
+ "commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="
+ },
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@@ -6050,6 +6762,16 @@
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
"dev": true
},
+ "date-fns-jalali": {
+ "version": "2.13.0-0",
+ "resolved": "https://registry.npmjs.org/date-fns-jalali/-/date-fns-jalali-2.13.0-0.tgz",
+ "integrity": "sha512-yjlI9O18Z6ryGNagryrLO8OQ+3rishM3+A0UOX2UX10cWMn2NTlQcQ+ywTEJvF5IJz0FwX/slt2nCcpyQ/c8gw=="
+ },
+ "dayjs": {
+ "version": "1.11.9",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
+ "integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA=="
+ },
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -6093,6 +6815,14 @@
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
"integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA=="
},
+ "defaults": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+ "requires": {
+ "clone": "^1.0.2"
+ }
+ },
"define-lazy-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
@@ -6626,6 +7356,16 @@
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
},
+ "external-editor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
+ "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
+ "requires": {
+ "chardet": "^0.7.0",
+ "iconv-lite": "^0.4.24",
+ "tmp": "^0.0.33"
+ }
+ },
"fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -6673,6 +7413,21 @@
"reusify": "^1.0.4"
}
},
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "dependencies": {
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="
+ }
+ }
+ },
"file-entry-cache": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -6984,11 +7739,34 @@
"through2": "~0.4.1"
}
},
+ "iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "requires": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ }
+ },
+ "ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
+ },
"ignore": {
"version": "5.2.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
"integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ=="
},
+ "image-resize": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/image-resize/-/image-resize-1.3.2.tgz",
+ "integrity": "sha512-mbWBO4Fh+dsM5Nvj+ob01JE2gzla043PxilytGSMYUluOKEkVs1nhu2JwZ1dpRwwkYDkEOJENgm834LuunlIOQ=="
+ },
+ "image-to-file-converter": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/image-to-file-converter/-/image-to-file-converter-1.0.6.tgz",
+ "integrity": "sha512-CokQCAEtUHGOmc537r9yZHCi4UTxOnpUQ7JPcIGRjOntTEVlT7uNpmP1YuhUT/53ufEsxk9C+ReU23zhO/b+6Q=="
+ },
"immutable": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
@@ -7022,6 +7800,28 @@
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "inquirer": {
+ "version": "8.2.5",
+ "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz",
+ "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==",
+ "requires": {
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.1.1",
+ "cli-cursor": "^3.1.0",
+ "cli-width": "^3.0.0",
+ "external-editor": "^3.0.3",
+ "figures": "^3.0.0",
+ "lodash": "^4.17.21",
+ "mute-stream": "0.0.8",
+ "ora": "^5.4.1",
+ "run-async": "^2.4.0",
+ "rxjs": "^7.5.5",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "through": "^2.3.6",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
"internal-slot": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz",
@@ -7150,6 +7950,11 @@
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
},
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+ },
"is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
@@ -7158,6 +7963,11 @@
"is-extglob": "^2.1.1"
}
},
+ "is-interactive": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="
+ },
"is-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
@@ -7245,6 +8055,11 @@
"has-tostringtag": "^1.0.0"
}
},
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="
+ },
"is-weakmap": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
@@ -7290,6 +8105,21 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
+ "jalaali-js": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/jalaali-js/-/jalaali-js-1.2.6.tgz",
+ "integrity": "sha512-io974va+Qyu+UfuVX3UIAgJlxLhAMx9Y8VMfh+IG00Js7hXQo1qNQuwSiSa0xxco0SVgx5HWNkaiCcV+aZ8WPw=="
+ },
+ "jalali-moment": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/jalali-moment/-/jalali-moment-3.3.11.tgz",
+ "integrity": "sha512-tdSaRs9cjWjOIaWhcsGFZMhZQhfgok5J0TwqFpBIZPudZxxa6yjUPoLCOwuvbAtRpiZn7k/mvazAJh+vEN5suw==",
+ "requires": {
+ "commander": "^7.0.0",
+ "inquirer": "^8.0.0",
+ "moment": "^2.26.0"
+ }
+ },
"js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
@@ -7403,6 +8233,15 @@
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
},
+ "log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "requires": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ }
+ },
"loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -7460,6 +8299,11 @@
"mime-db": "1.52.0"
}
},
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
+ },
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -7478,6 +8322,25 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
},
+ "moment-jalaali": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/moment-jalaali/-/moment-jalaali-0.10.0.tgz",
+ "integrity": "sha512-XICH1+UHd3zyaE1bXWQBlhoXBqbzEyFfT0TrifNobHxLALRuTSwXn376bX8FmkYg9mZimevwwdd6EB57s5wuFA==",
+ "requires": {
+ "jalaali-js": "^1.1.0",
+ "moment": "^2.22.2",
+ "moment-timezone": "^0.5.21",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "moment-timezone": {
+ "version": "0.5.43",
+ "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz",
+ "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==",
+ "requires": {
+ "moment": "^2.29.4"
+ }
+ },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -7492,6 +8355,11 @@
"object-assign": "^4.1.0"
}
},
+ "mute-stream": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA=="
+ },
"nanoid": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
@@ -7657,6 +8525,14 @@
"wrappy": "1"
}
},
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
"open": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
@@ -7681,6 +8557,27 @@
"word-wrap": "^1.2.3"
}
},
+ "ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+ "requires": {
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
+ "wcwidth": "^1.0.1"
+ }
+ },
+ "os-tmpdir": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
+ "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="
+ },
"p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
@@ -7909,6 +8806,15 @@
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
},
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
"reusify": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
@@ -7922,6 +8828,11 @@
"glob": "^7.1.3"
}
},
+ "run-async": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+ "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ=="
+ },
"run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -7930,6 +8841,14 @@
"queue-microtask": "^1.2.2"
}
},
+ "rxjs": {
+ "version": "7.8.1",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+ "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@@ -7946,6 +8865,11 @@
"is-regex": "^1.1.4"
}
},
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
"sass": {
"version": "1.62.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.62.0.tgz",
@@ -7997,6 +8921,11 @@
"object-inspect": "^1.9.0"
}
},
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
+ },
"slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
@@ -8032,6 +8961,23 @@
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
},
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "dependencies": {
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ }
+ }
+ },
"string.prototype.matchall": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz",
@@ -8186,6 +9132,14 @@
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
},
+ "tmp": {
+ "version": "0.0.33",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
+ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "requires": {
+ "os-tmpdir": "~1.0.2"
+ }
+ },
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -8319,6 +9273,14 @@
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
+ "wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+ "requires": {
+ "defaults": "^1.0.3"
+ }
+ },
"which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -8371,6 +9333,16 @@
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
},
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
diff --git a/package.json b/package.json
index cbb68a7..86613ec 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,11 @@
"dev": "next dev",
"build": "next build",
"start": "next start",
- "lint": "next lint"
+ "publish-3002": "next start -p 3002",
+ "lint": "next lint",
+ "update": "run-script-os",
+ "update:win32": "echo 'ok'",
+ "update:linux": "rm -rf .next/ && npm i && npm run build && sudo systemctl restart loan_facilities_develop_expert.service"
},
"dependencies": {
"@emotion/react": "^11.10.6",
@@ -14,12 +18,20 @@
"@emotion/styled": "^11.10.6",
"@mui/icons-material": "^5.11.16",
"@mui/material": "^5.12.0",
+ "@mui/x-date-pickers": "^6.9.2",
"axios": "^1.4.0",
+ "colord": "^2.9.3",
+ "date-fns-jalali": "^2.13.0-0",
+ "dayjs": "^1.11.9",
"eslint": "8.36.0",
"formik": "^2.2.9",
"fs-extra": "^11.1.1",
+ "image-resize": "^1.3.2",
+ "image-to-file-converter": "^1.0.6",
+ "jalali-moment": "^3.3.11",
"material-react-table": "^1.11.1",
"moment": "^2.29.4",
+ "moment-jalaali": "^0.10.0",
"next": "^13.3.0",
"next-intl": "^2.13.1",
"next-useragent": "^2.8.0",
@@ -36,6 +48,7 @@
},
"devDependencies": {
"@faker-js/faker": "^7.6.0",
- "eslint-config-next": "^13.3.0"
+ "eslint-config-next": "^13.3.0",
+ "run-script-os": "^1.1.6"
}
}
diff --git a/public/fontiran.scss b/public/fontiran.scss
index e263b42..86d585d 100644
--- a/public/fontiran.scss
+++ b/public/fontiran.scss
@@ -17,80 +17,153 @@ This set of fonts are used in this project under the license: (.....)
*
**/
@font-face {
- font-family: IRANSans;
- font-style: normal;
- font-weight: 900;
- src: url('./fonts/eot/IRANSansWeb_Black.eot');
- src: url('./fonts/eot/IRANSansWeb_Black.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
- url('./fonts/woff2/IRANSansWeb_Black.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
- url('./fonts/woff/IRANSansWeb_Black.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
- url('./fonts/ttf/IRANSansWeb_Black.ttf') format('truetype');
+ font-family: IRANSansFaNum;
+ font-style: normal;
+ font-weight: 900;
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_Black.eot');
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_Black.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb(FaNum)_Black.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb(FaNum)_Black.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb(FaNum)_Black.ttf') format('truetype');
}
+
@font-face {
- font-family: IRANSans;
- font-style: normal;
- font-weight: bold;
- src: url('./fonts/eot/IRANSansWeb_Bold.eot');
- src: url('./fonts/eot/IRANSansWeb_Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
- url('./fonts/woff2/IRANSansWeb_Bold.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
- url('./fonts/woff/IRANSansWeb_Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
- url('./fonts/ttf/IRANSansWeb_Bold.ttf') format('truetype');
+ font-family: IRANSansFaNum;
+ font-style: normal;
+ font-weight: bold;
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_Bold.eot');
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb(FaNum)_Bold.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb(FaNum)_Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb(FaNum)_Bold.ttf') format('truetype');
}
+
@font-face {
- font-family: IRANSans;
- font-style: normal;
- font-weight: 500;
- src: url('./fonts/eot/IRANSansWeb_Medium.eot');
- src: url('./fonts/eot/IRANSansWeb_Medium.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
- url('./fonts/woff2/IRANSansWeb_Medium.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
- url('./fonts/woff/IRANSansWeb_Medium.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
- url('./fonts/ttf/IRANSansWeb_Medium.ttf') format('truetype');
+ font-family: IRANSansFaNum;
+ font-style: normal;
+ font-weight: 500;
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_Medium.eot');
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_Medium.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb(FaNum)_Medium.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb(FaNum)_Medium.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb(FaNum)_Medium.ttf') format('truetype');
}
+
@font-face {
- font-family: IRANSans;
- font-style: normal;
- font-weight: 300;
- src: url('./fonts/eot/IRANSansWeb_Light.eot');
- src: url('./fonts/eot/IRANSansWeb_Light.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
- url('./fonts/woff2/IRANSansWeb_Light.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
- url('./fonts/woff/IRANSansWeb_Light.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
- url('./fonts/ttf/IRANSansWeb_Light.ttf') format('truetype');
+ font-family: IRANSansFaNum;
+ font-style: normal;
+ font-weight: 300;
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_Light.eot');
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_Light.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb(FaNum)_Light.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb(FaNum)_Light.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb(FaNum)_Light.ttf') format('truetype');
}
+
@font-face {
- font-family: IRANSans;
- font-style: normal;
- font-weight: 200;
- src: url('./fonts/eot/IRANSansWeb_UltraLight.eot');
- src: url('./fonts/eot/IRANSansWeb_UltraLight.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
- url('./fonts/woff2/IRANSansWeb_UltraLight.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
- url('./fonts/woff/IRANSansWeb_UltraLight.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
- url('./fonts/ttf/IRANSansWeb_UltraLight.ttf') format('truetype');
+ font-family: IRANSansFaNum;
+ font-style: normal;
+ font-weight: 200;
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot');
+ src: url('./fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb(FaNum)_UltraLight.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb(FaNum)_UltraLight.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb(FaNum)_UltraLight.ttf') format('truetype');
}
+
@font-face {
- font-family: IRANSans;
- font-style: normal;
- font-weight: normal;
- src: url('./fonts/eot/IRANSansWeb.eot');
- src: url('./fonts/eot/IRANSansWeb.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
- url('./fonts/woff2/IRANSansWeb.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
- url('./fonts/woff/IRANSansWeb.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
- url('./fonts/ttf/IRANSansWeb.ttf') format('truetype');
+ font-family: IRANSansFaNum;
+ font-style: normal;
+ font-weight: normal;
+ src: url('./fonts/eot/IRANSansWeb(FaNum).eot');
+ src: url('./fonts/eot/IRANSansWeb(FaNum).eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb(FaNum).woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb(FaNum).woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb(FaNum).ttf') format('truetype');
}
+
@font-face {
- font-family: Parastoo;
- font-style: normal;
- font-weight: normal;
- src: url('./fonts/eot/Parastoo.eot');
- src: url('./fonts/eot/Parastoo.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
- url('./fonts/woff/Parastoo.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
- url('./fonts/ttf/Parastoo.ttf') format('truetype');
+ font-family: IRANSans;
+ font-style: normal;
+ font-weight: 900;
+ src: url('./fonts/eot/IRANSansWeb_Black.eot');
+ src: url('./fonts/eot/IRANSansWeb_Black.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb_Black.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb_Black.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb_Black.ttf') format('truetype');
}
+
@font-face {
- font-family: Parastoo;
- font-style: normal;
- font-weight: bold;
- src: url('./fonts/eot/Parastoo-Bold.eot');
- src: url('./fonts/eot/Parastoo-Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
- url('./fonts/woff/Parastoo-Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
- url('./fonts/ttf/Parastoo-Bold.ttf') format('truetype');
+ font-family: IRANSans;
+ font-style: normal;
+ font-weight: bold;
+ src: url('./fonts/eot/IRANSansWeb_Bold.eot');
+ src: url('./fonts/eot/IRANSansWeb_Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb_Bold.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb_Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb_Bold.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: IRANSans;
+ font-style: normal;
+ font-weight: 500;
+ src: url('./fonts/eot/IRANSansWeb_Medium.eot');
+ src: url('./fonts/eot/IRANSansWeb_Medium.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb_Medium.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb_Medium.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb_Medium.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: IRANSans;
+ font-style: normal;
+ font-weight: 300;
+ src: url('./fonts/eot/IRANSansWeb_Light.eot');
+ src: url('./fonts/eot/IRANSansWeb_Light.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb_Light.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb_Light.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb_Light.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: IRANSans;
+ font-style: normal;
+ font-weight: 200;
+ src: url('./fonts/eot/IRANSansWeb_UltraLight.eot');
+ src: url('./fonts/eot/IRANSansWeb_UltraLight.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb_UltraLight.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb_UltraLight.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb_UltraLight.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: IRANSans;
+ font-style: normal;
+ font-weight: normal;
+ src: url('./fonts/eot/IRANSansWeb.eot');
+ src: url('./fonts/eot/IRANSansWeb.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff2/IRANSansWeb.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/
+ url('./fonts/woff/IRANSansWeb.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/IRANSansWeb.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: Parastoo;
+ font-style: normal;
+ font-weight: normal;
+ src: url('./fonts/eot/Parastoo.eot');
+ src: url('./fonts/eot/Parastoo.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff/Parastoo.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/Parastoo.ttf') format('truetype');
+}
+
+@font-face {
+ font-family: Parastoo;
+ font-style: normal;
+ font-weight: bold;
+ src: url('./fonts/eot/Parastoo-Bold.eot');
+ src: url('./fonts/eot/Parastoo-Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
+ url('./fonts/woff/Parastoo-Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
+ url('./fonts/ttf/Parastoo-Bold.ttf') format('truetype');
}
diff --git a/public/fonts/eot/IRANSansWeb(FaNum).eot b/public/fonts/eot/IRANSansWeb(FaNum).eot
new file mode 100644
index 0000000..5a6fdd0
Binary files /dev/null and b/public/fonts/eot/IRANSansWeb(FaNum).eot differ
diff --git a/public/fonts/eot/IRANSansWeb(FaNum)_Black.eot b/public/fonts/eot/IRANSansWeb(FaNum)_Black.eot
new file mode 100644
index 0000000..a012bc6
Binary files /dev/null and b/public/fonts/eot/IRANSansWeb(FaNum)_Black.eot differ
diff --git a/public/fonts/eot/IRANSansWeb(FaNum)_Bold.eot b/public/fonts/eot/IRANSansWeb(FaNum)_Bold.eot
new file mode 100644
index 0000000..82525e5
Binary files /dev/null and b/public/fonts/eot/IRANSansWeb(FaNum)_Bold.eot differ
diff --git a/public/fonts/eot/IRANSansWeb(FaNum)_Light.eot b/public/fonts/eot/IRANSansWeb(FaNum)_Light.eot
new file mode 100644
index 0000000..f899008
Binary files /dev/null and b/public/fonts/eot/IRANSansWeb(FaNum)_Light.eot differ
diff --git a/public/fonts/eot/IRANSansWeb(FaNum)_Medium.eot b/public/fonts/eot/IRANSansWeb(FaNum)_Medium.eot
new file mode 100644
index 0000000..117c2c8
Binary files /dev/null and b/public/fonts/eot/IRANSansWeb(FaNum)_Medium.eot differ
diff --git a/public/fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot b/public/fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot
new file mode 100644
index 0000000..9cd9b66
Binary files /dev/null and b/public/fonts/eot/IRANSansWeb(FaNum)_UltraLight.eot differ
diff --git a/public/fonts/ttf/IRANSansWeb(FaNum).ttf b/public/fonts/ttf/IRANSansWeb(FaNum).ttf
new file mode 100644
index 0000000..cd74265
Binary files /dev/null and b/public/fonts/ttf/IRANSansWeb(FaNum).ttf differ
diff --git a/public/fonts/ttf/IRANSansWeb(FaNum)_Black.ttf b/public/fonts/ttf/IRANSansWeb(FaNum)_Black.ttf
new file mode 100644
index 0000000..0f84dbf
Binary files /dev/null and b/public/fonts/ttf/IRANSansWeb(FaNum)_Black.ttf differ
diff --git a/public/fonts/ttf/IRANSansWeb(FaNum)_Bold.ttf b/public/fonts/ttf/IRANSansWeb(FaNum)_Bold.ttf
new file mode 100644
index 0000000..6fa2412
Binary files /dev/null and b/public/fonts/ttf/IRANSansWeb(FaNum)_Bold.ttf differ
diff --git a/public/fonts/ttf/IRANSansWeb(FaNum)_Light.ttf b/public/fonts/ttf/IRANSansWeb(FaNum)_Light.ttf
new file mode 100644
index 0000000..d9000c9
Binary files /dev/null and b/public/fonts/ttf/IRANSansWeb(FaNum)_Light.ttf differ
diff --git a/public/fonts/ttf/IRANSansWeb(FaNum)_Medium.ttf b/public/fonts/ttf/IRANSansWeb(FaNum)_Medium.ttf
new file mode 100644
index 0000000..e20001c
Binary files /dev/null and b/public/fonts/ttf/IRANSansWeb(FaNum)_Medium.ttf differ
diff --git a/public/fonts/ttf/IRANSansWeb(FaNum)_UltraLight.ttf b/public/fonts/ttf/IRANSansWeb(FaNum)_UltraLight.ttf
new file mode 100644
index 0000000..0072606
Binary files /dev/null and b/public/fonts/ttf/IRANSansWeb(FaNum)_UltraLight.ttf differ
diff --git a/public/fonts/woff/IRANSansWeb(FaNum).woff b/public/fonts/woff/IRANSansWeb(FaNum).woff
new file mode 100644
index 0000000..e34dfc4
Binary files /dev/null and b/public/fonts/woff/IRANSansWeb(FaNum).woff differ
diff --git a/public/fonts/woff/IRANSansWeb(FaNum)_Black.woff b/public/fonts/woff/IRANSansWeb(FaNum)_Black.woff
new file mode 100644
index 0000000..bbbca77
Binary files /dev/null and b/public/fonts/woff/IRANSansWeb(FaNum)_Black.woff differ
diff --git a/public/fonts/woff/IRANSansWeb(FaNum)_Bold.woff b/public/fonts/woff/IRANSansWeb(FaNum)_Bold.woff
new file mode 100644
index 0000000..05d933e
Binary files /dev/null and b/public/fonts/woff/IRANSansWeb(FaNum)_Bold.woff differ
diff --git a/public/fonts/woff/IRANSansWeb(FaNum)_Light.woff b/public/fonts/woff/IRANSansWeb(FaNum)_Light.woff
new file mode 100644
index 0000000..fe80d47
Binary files /dev/null and b/public/fonts/woff/IRANSansWeb(FaNum)_Light.woff differ
diff --git a/public/fonts/woff/IRANSansWeb(FaNum)_Medium.woff b/public/fonts/woff/IRANSansWeb(FaNum)_Medium.woff
new file mode 100644
index 0000000..f13a870
Binary files /dev/null and b/public/fonts/woff/IRANSansWeb(FaNum)_Medium.woff differ
diff --git a/public/fonts/woff/IRANSansWeb(FaNum)_UltraLight.woff b/public/fonts/woff/IRANSansWeb(FaNum)_UltraLight.woff
new file mode 100644
index 0000000..9c653a4
Binary files /dev/null and b/public/fonts/woff/IRANSansWeb(FaNum)_UltraLight.woff differ
diff --git a/public/fonts/woff2/IRANSansWeb(FaNum).woff2 b/public/fonts/woff2/IRANSansWeb(FaNum).woff2
new file mode 100644
index 0000000..30a377d
Binary files /dev/null and b/public/fonts/woff2/IRANSansWeb(FaNum).woff2 differ
diff --git a/public/fonts/woff2/IRANSansWeb(FaNum)_Black.woff2 b/public/fonts/woff2/IRANSansWeb(FaNum)_Black.woff2
new file mode 100644
index 0000000..0b15441
Binary files /dev/null and b/public/fonts/woff2/IRANSansWeb(FaNum)_Black.woff2 differ
diff --git a/public/fonts/woff2/IRANSansWeb(FaNum)_Bold.woff2 b/public/fonts/woff2/IRANSansWeb(FaNum)_Bold.woff2
new file mode 100644
index 0000000..f2353b2
Binary files /dev/null and b/public/fonts/woff2/IRANSansWeb(FaNum)_Bold.woff2 differ
diff --git a/public/fonts/woff2/IRANSansWeb(FaNum)_Light.woff2 b/public/fonts/woff2/IRANSansWeb(FaNum)_Light.woff2
new file mode 100644
index 0000000..562d663
Binary files /dev/null and b/public/fonts/woff2/IRANSansWeb(FaNum)_Light.woff2 differ
diff --git a/public/fonts/woff2/IRANSansWeb(FaNum)_Medium.woff2 b/public/fonts/woff2/IRANSansWeb(FaNum)_Medium.woff2
new file mode 100644
index 0000000..a69f4d0
Binary files /dev/null and b/public/fonts/woff2/IRANSansWeb(FaNum)_Medium.woff2 differ
diff --git a/public/fonts/woff2/IRANSansWeb(FaNum)_UltraLight.woff2 b/public/fonts/woff2/IRANSansWeb(FaNum)_UltraLight.woff2
new file mode 100644
index 0000000..1114f71
Binary files /dev/null and b/public/fonts/woff2/IRANSansWeb(FaNum)_UltraLight.woff2 differ
diff --git a/public/icons/favicon.png b/public/icons/favicon.png
new file mode 100644
index 0000000..c82bf9a
Binary files /dev/null and b/public/icons/favicon.png differ
diff --git a/public/images/change-password.svg b/public/images/change-password.svg
deleted file mode 100644
index f3b65aa..0000000
--- a/public/images/change-password.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/images/dashboard.svg b/public/images/dashboard.svg
deleted file mode 100644
index ea3f11b..0000000
--- a/public/images/dashboard.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/images/login.svg b/public/images/login.svg
deleted file mode 100644
index e2854d2..0000000
--- a/public/images/login.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/images/logo.svg b/public/images/logo.svg
index 5931dd4..eebb9fa 100644
--- a/public/images/logo.svg
+++ b/public/images/logo.svg
@@ -1,10 +1,19 @@
diff --git a/public/locales/fa/app.json b/public/locales/fa/app.json
index 7d0f4ed..e78f16e 100644
--- a/public/locales/fa/app.json
+++ b/public/locales/fa/app.json
@@ -6,26 +6,59 @@
"login": "ورود",
"login_expert": "ورود کارشناس",
"expert": "کارشناس",
+ "last_updated_at": "اخرین بروز رسانی",
+ "filter_mode": "حالت فیلتر",
+ "date_picker_label": "فیلتر بر اساس تاریخ",
+ "lessThan": "کوچکتر از",
+ "greaterThan": "بزرگتر از",
+ "between": "میان",
+ "online_message": "شما به اینترنت وصل هستید",
+ "offline_message": "اتصال شما به اینترنت قطع شده است",
"header": {
"open_profile": "پروفایل",
- "edit_profile": "ویرایش پروفایل",
+ "edit_profile": " پروفایل",
"change_password": "تغییر رمز عبور",
"logout": "خروج"
},
"Titles": {
"title_login_page": "صفحه ورود",
- "title_login_expert_page": "ورود کارشناس"
+ "title_login_expert_page": "ورود کارشناس",
+ "title_custom_404": "صفحه یافت نشد",
+ "title_custom_403": "عدم دسترسی",
+ "title_custom_500": "خطای سرور"
},
"sidebar": {
- "dashboard": "داشبورد"
+ "dashboard": "داشبورد",
+ "passenger-office-chief": "اداره مسافر",
+ "machinery-expert": "ماشین آلات",
+ "passenger-boss": "رئیس مسافر ",
+ "transportation-assistant": "معاونت حمل و نقل",
+ "navgan-province-manager": "مدیر کل استانی",
+ "refahi-province-manager": "مدیر کل استانی",
+ "commercial-chief": "رئیس اداره بازرگانی",
+ "inspector-expert": "بازدید کارشناس",
+ "province-head-expert": "کارشناس ستادی",
+ "change-password": "تغییر رمز عبور",
+ "development-assistant": "معاون توسعه",
+ "edit-profile": "ویرایش پروفایل"
+ },
+ "secondary": {
+ "passenger-office": "توزیع درخواست",
+ "passenger-boss": "کارگروه استانی",
+ "refahi-province-manager": "رفاهی",
+ "navgan-province-manager": "ناوگان"
},
"Authorization": {
"typography_your_login_is_valid_and_you_do_not_need_to_login_again": "شما دسترسی لازم به این صفحه را دارید نیاز به ورود مجدد نیست.",
"typography_your_access_to_this_page_has_expired_Please_login_again": "دسترسی شما منقضی شده است لطفا دوباره ورود نمایید.",
- "typography_redirect_to": "رفتن به صفحه",
+ "typography_redirect_to": "درحال رفتن به صفحه",
"typography_routing_previuos_page": "صفحه قبل...",
"typography_routing_dashbaord_page": "داشبورد..."
},
+ "Permission": {
+ "typography_you_dont_have_access": "شما دسترسی لازم برای مشاهده این صفحه را ندارید!",
+ "button_back_dashboard": "بازگشت به صفحه اصلی"
+ },
"LoginPage": {
"text_field_user_name": "نام کاربری",
"text_field_enter_your_username": "نام کاربری خود را وارد کنید",
@@ -35,10 +68,230 @@
"link_routing_back_to": "بازگشت به",
"link_routing_previuos_page": "صفحه قبل",
"link_routing_main_page": "صفحه اصلی",
- "error_message_required": "اجباری!",
- "button_make_account": "ایجاد حساب"
+ "error_message_required": "اجباری!"
},
- "dashboard": {
- "dashboard_page": "داشبورد"
+ "ErrorPage": {
+ "custom_404": "صفحه مورد نظر یافت نشد | 404",
+ "custom_500": "دسترسی به سامانه امکانپذیر نمی باشد دقایقی دیگر تلاش نمائید | 500",
+ "custom_403": "شما دسترسی به این بخش را ندارید | 403",
+ "link_routing_back_to": "بازگشت به",
+ "link_routing_previuos_page": "صفحه قبل",
+ "link_routing_main_page": "صفحه اصلی"
+ },
+ "Dashboard": {
+ "dashboard_page": "داشبورد",
+ "passenger_boss_page": "رئیس مسافر",
+ "transportation_assistance": "معاونت حمل و نقل",
+ "change_password": "تغییر رمز عبور",
+ "province_manager_page": "مدیر کل استانی",
+ "province_head_expert": "کارشناس ستادی",
+ "passenger_office_page": "اداره مسافر",
+ "machinary_office_page": "ماشین آلات",
+ "development_assistant_page": "معاون توسعه",
+ "inspector_expert_page": "بازدید کارشناس",
+ "commercial_chief_page": "رئیس اداره بازرگانی",
+ "edit_profile": "ویرایش پروفایل"
+ },
+ "MuiDatePicker": {
+ "date_picker_birthday": "تاریخ"
+ },
+ "ChangePassword": {
+ "typography_change_password": "تغییر رمز عبور",
+ "label_current_password": "رمز عبور فعلی",
+ "label_new_password": "رمز عبور جدید",
+ "label_confirm_password": "تکرار رمز عبور جدید",
+ "error_message_required": "اجباری !",
+ "error_message_password_length": "رمز عبور باید حداقل 8 کاراکتر باشد.",
+ "error_message_password_match": "پسورد ها یکسان هستند",
+ "error_message_password_not_match": "پسورد و تکرار رمز عبور باید یکسان باشد"
+ },
+ "SubmitButton": {
+ "button_while_submit": "در حال ثبت",
+ "button_submit": "ثبت"
+ },
+ "UpdateProfile": {
+ "error_invalid_email": "ایمیل نامعتبر است",
+ "typography_edit_profile": "پروفایل",
+ "text_field_email": "ایمیل",
+ "text_field_enter_your_password": "رمز عبور خود را وارد کنید",
+ "text_field_username": "نام کاربری",
+ "text_field_name": "نام",
+ "text_field_phone_number": "شماره تماس",
+ "text_field_position": "سمت",
+ "text_field_province_name": "نام استان",
+ "error_message_required": "اجباری !"
+ },
+ "notifications": {
+ "code": "کد",
+ "error": "خطا",
+ "warning": "خطا",
+ "success": "موفق",
+ "error_static_text": "عملیات شما با خطا مواجه شد",
+ "warning_static_text": "خطا سرور",
+ "success_static_text": "عملیات شما با موفقیت انجام شد",
+ "pending": "در حال انجام..."
+ },
+ "PassengerOffice": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "CommercialChief": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "NavganProvinceManager": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "PassengerBoss": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "RefahiProvinceManager": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "DevelopmentAssistant": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "DevelopmentAssistant": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "ProvinceHeadExpert": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "TransportationAssistance": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "InspectorExpert": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "MachinaryOffice": {
+ "name": "نام",
+ "id": "کد یکتا",
+ "national_id": "کد ملی",
+ "phone_number": "موبایل",
+ "created_at": "تاریخ درخواست",
+ "updated_at": "تاریخ بروزرسانی",
+ "navgan_id": "کد ناوگان",
+ "vehicle_type": "نوع ماشین",
+ "state_name": "وضعیت درخواست"
+ },
+ "ConfirmDialog": {
+ "confirm": "تایید",
+ "context": "آیا از تایید این آیتم اطمینان دارید؟",
+ "button-cancel": "بستن",
+ "button-confirm": "تایید",
+ "description_error": "وارد کردن توضیحات الزامی است!",
+ "optional": " (اختیاری)",
+ "unit": " (ریال)",
+ "description": "توضیحات خود را وارد نمائید",
+ "choose_file": "انتخاب فایل",
+ "approved_amount": "مبلغ تصویب شده",
+ "approved_amount_error": "وارد کردن مبلغ تصویب شده الزامیست",
+ "approved_amount_positive": "مبلغ تصویب شده باید مثبت باشد",
+ "proposed_amount_error": "وارد کردن مقدار پیشنهادی الزامیست",
+ "proposed_amount": "مقدار پیشنهادی",
+ "proposed_amount_positive": "مقدار پیشنهادی باید مثبت باشد"
+ },
+ "ReviseDialog": {
+ "revise": "ویرایش",
+ "description_error": "وارد کردن توضیحات الزامی است!",
+ "optional": " (اختیاری)",
+ "button-cancel": "بستن",
+ "button-revise": "ویرایش",
+ "description": "توضیحات خود را وارد نمائید"
+ },
+ "RejectDialog": {
+ "reject": "عدم تایید",
+ "context": "آیا از عدم تایید این آیتم اطمینان دارید؟",
+ "button-cancel": "بستن",
+ "button-reject": "عدم تایید",
+ "description": "توضیحات خود را وارد نمائید",
+ "optional": " (اختیاری)",
+ "description_error": "وارد کردن توضیحات الزامی است!"
+ },
+ "UploadSystem": {
+ "upload_file": "فایل خود را بارگذاری کنید",
+ "optional": " (اختیاری)",
+ "upload_file_unit": "حداکثر 2Mb",
+ "upload_file_format": "فرمت قابل قبول : png,jpg,pdf",
+ "delete": "پاک کردن",
+ "uploadfile_error": "حجم فایل بیشتر از 2 مگابایت می باشد"
}
}
diff --git a/public/locales/fa/datatable.js b/public/locales/fa/datatable.js
index e42208f..fd43663 100644
--- a/public/locales/fa/datatable.js
+++ b/public/locales/fa/datatable.js
@@ -1,92 +1,92 @@
export const FA_DATATABLE_LOCALIZATION = {
- actions: "Actions",
- and: "and",
- cancel: "Cancel",
- changeFilterMode: "Change filter mode",
- changeSearchMode: "Change search mode",
- clearFilter: "Clear filter",
- clearSearch: "Clear search",
- clearSort: "Clear sort",
- clickToCopy: "Click to copy",
- collapse: "Collapse",
- collapseAll: "Collapse all",
- columnActions: "Column Actions",
- copiedToClipboard: "Copied to clipboard",
- dropToGroupBy: "Drop to group by {column}",
- edit: "Edit",
- expand: "Expand",
- expandAll: "Expand all",
- filterArrIncludes: "Includes",
- filterArrIncludesAll: "Includes all",
- filterArrIncludesSome: "Includes",
- filterBetween: "Between",
- filterBetweenInclusive: "Between Inclusive",
- filterByColumn: "Filter by {column}",
- filterContains: "Contains",
- filterEmpty: "Empty",
- filterEndsWith: "Ends With",
- filterEquals: "Equals",
- filterEqualsString: "Equals",
- filterFuzzy: "Fuzzy",
- filterGreaterThan: "Greater Than",
- filterGreaterThanOrEqualTo: "Greater Than Or Equal To",
- filterInNumberRange: "Between",
- filterIncludesString: "Contains",
- filterIncludesStringSensitive: "Contains",
- filterLessThan: "Less Than",
- filterLessThanOrEqualTo: "Less Than Or Equal To",
- filterMode: "Filter Mode: {filterType}",
- filterNotEmpty: "Not Empty",
- filterNotEquals: "Not Equals",
- filterStartsWith: "Starts With",
- filterWeakEquals: "Equals",
- filteringByColumn: "Filtering by {column} - {filterType} {filterValue}",
- goToFirstPage: "Go to first page",
- goToLastPage: "Go to last page",
- goToNextPage: "Go to next page",
- goToPreviousPage: "Go to previous page",
- grab: "Grab",
- groupByColumn: "Group by {column}",
- groupedBy: "Grouped by ",
- hideAll: "Hide all",
- hideColumn: "Hide {column} column",
- max: "Max",
- min: "Min",
- move: "Move",
- noRecordsToDisplay: "No records to display",
- noResultsFound: "No results found",
- of: "of",
- or: "or",
- pinToLeft: "Pin to left",
- pinToRight: "Pin to right",
- resetColumnSize: "Reset column size",
- resetOrder: "Reset order",
- rowActions: "Row Actions",
- rowNumber: "#",
- rowNumbers: "Row Numbers",
- rowsPerPage: "Rows per page",
- save: "Save",
- search: "Search",
- selectedCountOfRowCountRowsSelected:
- "{selectedCount} of {rowCount} row(s) selected",
- select: "Select",
- showAll: "Show all",
- showAllColumns: "Show all columns",
- showHideColumns: "Show/Hide columns",
- showHideFilters: "Show/Hide filters",
- showHideSearch: "Show/Hide search",
- sortByColumnAsc: "Sort by {column} ascending",
- sortByColumnDesc: "Sort by {column} descending",
- sortedByColumnAsc: "Sorted by {column} ascending",
- sortedByColumnDesc: "Sorted by {column} descending",
- thenBy: ", then by ",
- toggleDensity: "Toggle density",
- toggleFullScreen: "Toggle full screen",
- toggleSelectAll: "Toggle select all",
- toggleSelectRow: "Toggle select row",
- toggleVisibility: "Toggle visibility",
- ungroupByColumn: "Ungroup by {column}",
- unpin: "Unpin",
- unpinAll: "Unpin all",
- unsorted: "Unsorted",
+ actions: "عملیات",
+ and: "و",
+ cancel: "لغو",
+ changeFilterMode: "تغییر حالت فیلتر",
+ changeSearchMode: "تغییر حالت جستجو",
+ clearFilter: "پاک کردن فیلتر",
+ clearSearch: "پاک کردن جستجو",
+ clearSort: "پاک کردن مرتب سازی",
+ clickToCopy: "کلیک برای کپی",
+ collapse: "جمع شدن",
+ collapseAll: "جمع شدن همه",
+ columnActions: "عملیات ستون",
+ copiedToClipboard: "کپی شد",
+ dropToGroupBy: "رها کردن برای گروه بندی بر اساس {column}",
+ edit: "ویرایش",
+ expand: "باز شدن",
+ expandAll: "باز شدن همه",
+ filterArrIncludes: "شامل",
+ filterArrIncludesAll: "شامل همه",
+ filterArrIncludesSome: "شامل",
+ filterBetween: "میان",
+ filterBetweenInclusive: "میان با احتساب هر دو",
+ filterByColumn: "فیلتر بر اساس {column}",
+ filterContains: "شامل",
+ filterEmpty: "خالی",
+ filterEndsWith: "به پایان میرسد با",
+ filterEquals: "برابر",
+ filterEqualsString: "برابر",
+ filterFuzzy: "نزدیک",
+ filterGreaterThan: "بزرگتر از",
+ filterGreaterThanOrEqualTo: "بزرگتر یا مساوی",
+ filterInNumberRange: "میان",
+ filterIncludesString: "شامل",
+ filterIncludesStringSensitive: "شامل",
+ filterLessThan: "کوچکتر از",
+ filterLessThanOrEqualTo: "کوچکتر یا مساوی",
+ filterMode: "حالت فیلتر: {filterType}",
+ filterNotEmpty: "غیر خالی",
+ filterNotEquals: "نا برابر",
+ filterStartsWith: "شروع میشود با",
+ filterWeakEquals: "برابر",
+ filteringByColumn: "فیلتر بر اساس {column} - {filterType} {filterValue}",
+ goToFirstPage: "رفتن به صفحه اول",
+ goToLastPage: "رفتن به صفحه آخر",
+ goToNextPage: "رفتن به صفحه بعدی",
+ goToPreviousPage: "رفتن به صفحه قبلی",
+ grab: "گرفتن",
+ groupByColumn: "گروه بندی بر اساس {column}",
+ groupedBy: "گروه بندی شده بر اساس",
+ hideAll: "پنهان کردن همه",
+ hideColumn: "پنهان کردن ستون {column}",
+ max: "حداکثر",
+ min: "حداقل",
+ move: "انتقال",
+ noRecordsToDisplay: "هیچ رکوردی برای نمایش وجود ندارد",
+ noResultsFound: "نتیجهای یافت نشد",
+ of: "از",
+ or: "یا",
+ pinToLeft: "چسباندن به سمت چپ",
+ pinToRight: "چسباندن به سمت راست",
+ resetColumnSize: "بازنشانی اندازه ستون",
+ resetOrder: "بازنشانی ترتیب",
+ rowActions: "عملیات ردیف",
+ rowNumber: "#",
+ rowNumbers: "شماره ردیف",
+ rowsPerPage: "ردیف در هر صفحه",
+ save: "ذخیره",
+ search: "جستجو",
+ selectedCountOfRowCountRowsSelected:
+ "{selectedCount} از {rowCount} ردیف انتخاب شده",
+ select: "انتخاب",
+ showAll: "نمایش همه",
+ showAllColumns: "نمایش همه ستونها",
+ showHideColumns: "نمایش/مخفی کردن ستونها",
+ showHideFilters: "نمایش/مخفی کردن فیلترها",
+ showHideSearch: "نمایش/مخفی کردن جستجو",
+ sortByColumnAsc: "مرتب سازی بر اساس {column} صعودی",
+ sortByColumnDesc: "مرتب سازی بر اساس {column} نزولی",
+ sortedByColumnAsc: "مرتب شده بر اساس {column} صعودی",
+ sortedByColumnDesc: "مرتب شده بر اساس {column} نزولی",
+ thenBy: "، سپس بر اساس ",
+ toggleDensity: "تغییر تراکم",
+ toggleFullScreen: "تغییر حالت تمام صفحه",
+ toggleSelectAll: "انتخاب/عدم انتخاب همه",
+ toggleSelectRow: "انتخاب/عدم انتخاب ردیف",
+ toggleVisibility: "تغییر پیدا/پنهان",
+ ungroupByColumn: "لغو گروه بندی بر اساس {column}",
+ unpin: "رها کردن",
+ unpinAll: "رها کردن همه",
+ unsorted: "بدون مرتب سازی",
};
diff --git a/public/manifest.json b/public/manifest.json
new file mode 100644
index 0000000..6bc19ce
--- /dev/null
+++ b/public/manifest.json
@@ -0,0 +1,57 @@
+{
+ "short_name": "Loan Facilities Dashboard",
+ "name": "Loan Facilities Expert Dashboard",
+ "description": "Loan Facilities",
+ "version": "1.0.0",
+ "version_name": "1.0.0 beta",
+ "start_url": "/dashboard",
+ "orientation": "portrait",
+ "display": "standalone",
+ "theme_color": "#084070",
+ "background_color": "#084070",
+ "icons": [
+ {
+ "src": "/icons/maskable_icon.png",
+ "sizes": "any",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x48.png",
+ "sizes": "48x48",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x72.png",
+ "sizes": "72x72",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x96.png",
+ "sizes": "96x96",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x128.png",
+ "sizes": "128x128",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x384.png",
+ "sizes": "384x384",
+ "type": "image/png"
+ },
+ {
+ "src": "/icons/maskable_icon_x512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }
+ ],
+ "categories": [
+ "government"
+ ]
+}
diff --git a/src/components/dashboard/change-password/index.jsx b/src/components/dashboard/change-password/index.jsx
new file mode 100644
index 0000000..ae74de6
--- /dev/null
+++ b/src/components/dashboard/change-password/index.jsx
@@ -0,0 +1,149 @@
+import CenterLayout from "@/layouts/CenterLayout";
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Button, Container, Paper, Stack, Typography,} from "@mui/material";
+import {Formik} from "formik";
+import * as Yup from "yup";
+import {useTranslations} from "next-intl";
+import PasswordField from "@/core/components/PasswordField";
+import StyledForm from "@/core/components/StyledForm";
+import {SET_USER_PASSWORD} from "@/core/data/apiRoutes";
+import SvgChangePassword from "@/core/components/svgs/SvgChangePassword";
+import useRequest from "@/lib/app/hooks/useRequest";
+
+const DashboardChangePasswordComponent = () => {
+ const t = useTranslations();
+ const requestServer = useRequest({auth: true})
+
+ const handleSubmit = (values, {setSubmitting, resetForm}) => {
+ requestServer(SET_USER_PASSWORD, 'post', {
+ data: {
+ current_password: values.current_password,
+ new_password: values.new_password,
+ new_password_confirmation: values.new_password_confirmation,
+ },
+ }).then((response) => {
+ resetForm();
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ };
+ const initialValues = {
+ current_password: "",
+ new_password: "",
+ new_password_confirmation: "",
+ };
+ const validationSchema = Yup.object().shape({
+ current_password: Yup.string().required(
+ t("ChangePassword.error_message_required")
+ ),
+ new_password: Yup.string()
+ .min(8, t("ChangePassword.error_message_password_length"))
+ .required(t("ChangePassword.error_message_required")),
+ new_password_confirmation: Yup.string()
+ .required(t("ChangePassword.error_message_required"))
+ .test(
+ t("ChangePassword.error_message_password_match"),
+ t("ChangePassword.error_message_password_not_match"),
+ function (value) {
+ return this.parent.new_password === value;
+ }
+ ),
+ });
+
+ return (
+
+
+
+
+ {(props) => (
+ {
+ e.preventDefault();
+ props.handleSubmit();
+ }}
+ >
+
+
+
+
+ {t("ChangePassword.typography_change_password")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+
+ );
+};
+export default DashboardChangePasswordComponent;
diff --git a/src/components/dashboard/commercial-chief/Form/ConfirmForm.jsx b/src/components/dashboard/commercial-chief/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..c2025ab
--- /dev/null
+++ b/src/components/dashboard/commercial-chief/Form/ConfirmForm.jsx
@@ -0,0 +1,142 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import {CONFIRM_COMMERCIAL_CHIEF} from "@/core/data/apiRoutes";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ confirm_img: null
+ },
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ if (values.description != "") formData.append("description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_COMMERCIAL_CHIEF}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/commercial-chief/Form/RejectForm.jsx b/src/components/dashboard/commercial-chief/Form/RejectForm.jsx
new file mode 100644
index 0000000..fd8becb
--- /dev/null
+++ b/src/components/dashboard/commercial-chief/Form/RejectForm.jsx
@@ -0,0 +1,146 @@
+import {REJECT_COMMERCIAL_CHIEF} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_COMMERCIAL_CHIEF}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/commercial-chief/TableRowActions.jsx b/src/components/dashboard/commercial-chief/TableRowActions.jsx
new file mode 100644
index 0000000..601240f
--- /dev/null
+++ b/src/components/dashboard/commercial-chief/TableRowActions.jsx
@@ -0,0 +1,23 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+
+const TableRow = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+ );
+};
+
+export default TableRow;
diff --git a/src/components/dashboard/commercial-chief/TableTollbar.jsx b/src/components/dashboard/commercial-chief/TableTollbar.jsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/dashboard/commercial-chief/index.jsx b/src/components/dashboard/commercial-chief/index.jsx
new file mode 100644
index 0000000..4ac03b3
--- /dev/null
+++ b/src/components/dashboard/commercial-chief/index.jsx
@@ -0,0 +1,201 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {GET_COMMERCIAL_CHIEF} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import TableRowActions from "./TableRowActions";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import {faIR} from "@mui/x-date-pickers/locales";
+import DataTable from "@/core/components/DataTable";
+
+function DashboardCommercialChiefComponent() {
+ const t = useTranslations();
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("CommercialChief.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("CommercialChief.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("CommercialChief.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("CommercialChief.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("CommercialChief.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => {
+ return {renderedCellValue};
+ },
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "updated_at",
+ header: t("CommercialChief.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("CommercialChief.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+
+
+
+ );
+}
+
+export default DashboardCommercialChiefComponent;
diff --git a/src/components/dashboard/development-assistant/Form/ConfirmForm.jsx b/src/components/dashboard/development-assistant/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..07b3253
--- /dev/null
+++ b/src/components/dashboard/development-assistant/Form/ConfirmForm.jsx
@@ -0,0 +1,141 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import {CONFIRM_DEVELOPMENT_ASSISTANT} from "@/core/data/apiRoutes";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ confirm_img: null
+ },
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ if (values.description != "") formData.append("description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_DEVELOPMENT_ASSISTANT}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/development-assistant/Form/RejectForm.jsx b/src/components/dashboard/development-assistant/Form/RejectForm.jsx
new file mode 100644
index 0000000..eb4e4a1
--- /dev/null
+++ b/src/components/dashboard/development-assistant/Form/RejectForm.jsx
@@ -0,0 +1,146 @@
+import {REJECT_DEVELOPMENT_ASSISTANT} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_DEVELOPMENT_ASSISTANT}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/development-assistant/TableRowActions.jsx b/src/components/dashboard/development-assistant/TableRowActions.jsx
new file mode 100644
index 0000000..601240f
--- /dev/null
+++ b/src/components/dashboard/development-assistant/TableRowActions.jsx
@@ -0,0 +1,23 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+
+const TableRow = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+ );
+};
+
+export default TableRow;
diff --git a/src/components/dashboard/development-assistant/TableTollbar.jsx b/src/components/dashboard/development-assistant/TableTollbar.jsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/dashboard/development-assistant/index.jsx b/src/components/dashboard/development-assistant/index.jsx
new file mode 100644
index 0000000..e54daab
--- /dev/null
+++ b/src/components/dashboard/development-assistant/index.jsx
@@ -0,0 +1,202 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {GET_DEVELOPMENT_ASSISTANT} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import TableRowActions from "./TableRowActions";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import {faIR} from "@mui/x-date-pickers/locales";
+import DataTable from "@/core/components/DataTable";
+
+function DashboardDevelopmentAssistantComponent() {
+ const t = useTranslations();
+
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("DevelopmentAssistant.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("DevelopmentAssistant.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("DevelopmentAssistant.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("DevelopmentAssistant.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("DevelopmentAssistant.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => {
+ return {renderedCellValue};
+ },
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "updated_at",
+ header: t("DevelopmentAssistant.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("DevelopmentAssistant.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+
+
+
+ );
+}
+
+export default DashboardDevelopmentAssistantComponent;
diff --git a/src/components/dashboard/edit-profile/index.jsx b/src/components/dashboard/edit-profile/index.jsx
new file mode 100644
index 0000000..3018aa3
--- /dev/null
+++ b/src/components/dashboard/edit-profile/index.jsx
@@ -0,0 +1,223 @@
+import StyledForm from "@/core/components/StyledForm";
+import CenterLayout from "@/layouts/CenterLayout";
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import useUser from "@/lib/app/hooks/useUser";
+import {Box, Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material";
+import * as Yup from "yup";
+import {Field, Formik} from "formik";
+import {useTranslations} from "next-intl";
+import AvatarUpload from "@/core/components/AvatarUpload";
+import axios from "axios";
+import {UPDATE_AVATAR} from "@/core/data/apiRoutes";
+import useDirection from "@/lib/app/hooks/useDirection";
+import Notifications from "@/core/components/notifications";
+import ImageResizer from "@/core/components/ImageConvertor";
+
+const DashboardEditProfile = () => {
+ const t = useTranslations();
+ const {user, token, getUser, changeUser} = useUser();
+ const {directionApp} = useDirection();
+
+ const editAvatar = async (avatar) => {
+ Notifications(t);
+ try {
+ const formData = new FormData();
+
+ if (avatar != null) {
+ var resizedAvatar;
+ resizedAvatar = await ImageResizer(avatar);
+ formData.append("avatar", resizedAvatar);
+ }
+
+ await axios.post(UPDATE_AVATAR, formData, {
+ headers: {
+ authorization: `Bearer ${token}`,
+ "Content-Type": "multipart/form-data",
+ },
+ });
+ } catch (error) {
+ Notifications(t, error.response);
+ throw error;
+ }
+ };
+ const handleSubmit = (values, {setSubmitting}) => {
+
+ };
+ const initialValues = {
+ expert_avatar: null,
+ username: user.username,
+ name: user.name,
+ email: user.email,
+ province_name: user.province_name,
+ position: user.position,
+ };
+ const validationSchema = Yup.object().shape({});
+
+ return (
+
+
+
+
+ {(props) => (
+ {
+ e.preventDefault();
+ props.handleSubmit();
+ }}
+ >
+
+
+
+ {t("UpdateProfile.typography_edit_profile")}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+
+ );
+};
+
+export default DashboardEditProfile;
diff --git a/src/components/dashboard/first/index.jsx b/src/components/dashboard/first/index.jsx
index c693380..ee4f80a 100644
--- a/src/components/dashboard/first/index.jsx
+++ b/src/components/dashboard/first/index.jsx
@@ -1,7 +1,7 @@
import DashboardLayouts from "@/layouts/dashboardLayouts";
const DashboardFirstComponent = () => {
- return ;
+ return ;
};
export default DashboardFirstComponent;
diff --git a/src/components/dashboard/inspector-expert/Form/ConfirmForm.jsx b/src/components/dashboard/inspector-expert/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..409ba94
--- /dev/null
+++ b/src/components/dashboard/inspector-expert/Form/ConfirmForm.jsx
@@ -0,0 +1,141 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import {CONFIRM_INSPECTOR_EXPERT} from "@/core/data/apiRoutes";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ confirm_img: null
+ },
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ if (values.description != "") formData.append("description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_INSPECTOR_EXPERT}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/inspector-expert/Form/RejectForm.jsx b/src/components/dashboard/inspector-expert/Form/RejectForm.jsx
new file mode 100644
index 0000000..f59758d
--- /dev/null
+++ b/src/components/dashboard/inspector-expert/Form/RejectForm.jsx
@@ -0,0 +1,148 @@
+import {REJECT_INSPECTOR_EXPERT} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useDirection from "@/lib/app/hooks/useDirection";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_INSPECTOR_EXPERT}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/inspector-expert/Form/ReviseForm.jsx b/src/components/dashboard/inspector-expert/Form/ReviseForm.jsx
new file mode 100644
index 0000000..2661965
--- /dev/null
+++ b/src/components/dashboard/inspector-expert/Form/ReviseForm.jsx
@@ -0,0 +1,104 @@
+import {REVISE_INSPECTOR_EXPERT} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import useRequest from "@/lib/app/hooks/useRequest";
+import EditIcon from "@mui/icons-material/Edit";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Revise = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("ReviseDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("description", values.description);
+
+ requestServer(`${REVISE_INSPECTOR_EXPERT}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Revise;
\ No newline at end of file
diff --git a/src/components/dashboard/inspector-expert/TableRowActions.jsx b/src/components/dashboard/inspector-expert/TableRowActions.jsx
new file mode 100644
index 0000000..f76c2d2
--- /dev/null
+++ b/src/components/dashboard/inspector-expert/TableRowActions.jsx
@@ -0,0 +1,29 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+import ReviseForm from "./Form/ReviseForm"
+
+const TableRow = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default TableRow;
diff --git a/src/components/dashboard/inspector-expert/TableTollbar.jsx b/src/components/dashboard/inspector-expert/TableTollbar.jsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/dashboard/inspector-expert/index.jsx b/src/components/dashboard/inspector-expert/index.jsx
new file mode 100644
index 0000000..5eeb329
--- /dev/null
+++ b/src/components/dashboard/inspector-expert/index.jsx
@@ -0,0 +1,201 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {GET_INSPECTOR_EXPERT} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import TableRowActions from "./TableRowActions";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import {faIR} from "@mui/x-date-pickers/locales";
+import DataTable from "@/core/components/DataTable";
+
+function DashboardInspectorExpertComponent() {
+ const t = useTranslations();
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("InspectorExpert.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("InspectorExpert.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("InspectorExpert.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("InspectorExpert.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("InspectorExpert.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => {
+ return {renderedCellValue};
+ },
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "updated_at",
+ header: t("InspectorExpert.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("InspectorExpert.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+
+
+
+ );
+}
+
+export default DashboardInspectorExpertComponent;
diff --git a/src/components/dashboard/loan-follow-up/index.jsx b/src/components/dashboard/loan-follow-up/index.jsx
deleted file mode 100644
index e69147e..0000000
--- a/src/components/dashboard/loan-follow-up/index.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import CenterLayout from "@/layouts/CenterLayout";
-import DashboardLayouts from "@/layouts/dashboardLayouts";
-import useUser from "@/lib/app/hooks/useUser";
-import { useTranslations } from "next-intl";
-import React from "react";
-
-const DashboardLoanFollowUpComponent = () => {
- const t = useTranslations();
- const { token } = useUser();
- return (
-
-
- چه کشکی چه پشمی
-
-
- );
-};
-
-export default DashboardLoanFollowUpComponent;
diff --git a/src/components/dashboard/loan-request/index.jsx b/src/components/dashboard/loan-request/index.jsx
deleted file mode 100644
index b13cf78..0000000
--- a/src/components/dashboard/loan-request/index.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import CenterLayout from "@/layouts/CenterLayout";
-import DashboardLayouts from "@/layouts/dashboardLayouts";
-import useUser from "@/lib/app/hooks/useUser";
-import { useTranslations } from "next-intl";
-import React from "react";
-
-const DashboardLoanRequestComponent = () => {
- const t = useTranslations();
- const { token } = useUser();
- return (
-
-
- نکنه وامم میخوای؟؟؟
-
-
- );
-};
-
-export default DashboardLoanRequestComponent;
diff --git a/src/components/dashboard/machinary-office/Form/ConfirmForm.jsx b/src/components/dashboard/machinary-office/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..ab4b11f
--- /dev/null
+++ b/src/components/dashboard/machinary-office/Form/ConfirmForm.jsx
@@ -0,0 +1,178 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import useDirection from "@/lib/app/hooks/useDirection";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import {CONFIRM_MACHINARY_OFFICE} from "@/core/data/apiRoutes";
+import * as Yup from "yup";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ proposed_amount: Yup.number().positive(t("ConfirmDialog.proposed_amount_positive")).required(t("ConfirmDialog.proposed_amount_error")),
+ })
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ proposed_amount: "",
+ confirm_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("proposed_amount", values.proposed_amount);
+ if (values.description != "") formData.append("expert_description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_MACHINARY_OFFICE}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+ const handleAmountChange = (event) => {
+ formik.setFieldValue("proposed_amount", event.target.value);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/machinary-office/Form/RejectForm.jsx b/src/components/dashboard/machinary-office/Form/RejectForm.jsx
new file mode 100644
index 0000000..61cec90
--- /dev/null
+++ b/src/components/dashboard/machinary-office/Form/RejectForm.jsx
@@ -0,0 +1,148 @@
+import {REJECT_MACHINARY_OFFICE} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useDirection from "@/lib/app/hooks/useDirection";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("expert_description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_MACHINARY_OFFICE}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/machinary-office/TableRowActions.jsx b/src/components/dashboard/machinary-office/TableRowActions.jsx
new file mode 100644
index 0000000..601240f
--- /dev/null
+++ b/src/components/dashboard/machinary-office/TableRowActions.jsx
@@ -0,0 +1,23 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+
+const TableRow = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+ );
+};
+
+export default TableRow;
diff --git a/src/components/dashboard/machinary-office/TableTolbar.jsx b/src/components/dashboard/machinary-office/TableTolbar.jsx
new file mode 100644
index 0000000..e267691
--- /dev/null
+++ b/src/components/dashboard/machinary-office/TableTolbar.jsx
@@ -0,0 +1,13 @@
+import {Stack, Tooltip} from "@mui/material";
+import {useTranslations} from "next-intl";
+
+function TableToolbar() {
+ const t = useTranslations();
+ return (
+
+
+
+ );
+}
+
+export default TableToolbar;
diff --git a/src/components/dashboard/machinary-office/index.jsx b/src/components/dashboard/machinary-office/index.jsx
new file mode 100644
index 0000000..8f68209
--- /dev/null
+++ b/src/components/dashboard/machinary-office/index.jsx
@@ -0,0 +1,232 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {GET_MACHINARY_OFFICE} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import TableRowActions from "./TableRowActions";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import {faIR} from "@mui/x-date-pickers/locales";
+import DataTable from "@/core/components/DataTable";
+
+function DashboardMachinaryOfficeComponent() {
+ const t = useTranslations();
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("PassengerOffice.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("MachinaryOffice.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("MachinaryOffice.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("MachinaryOffice.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("MachinaryOffice.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => {
+ return {renderedCellValue};
+ },
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "updated_at",
+ header: t("MachinaryOffice.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.navgan_id,
+ id: "navgan_id",
+ header: t("MachinaryOffice.navgan_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.vehicle_type,
+ id: "vehicle_type",
+ header: t("MachinaryOffice.vehicle_type"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("MachinaryOffice.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+
+
+
+ );
+}
+
+export default DashboardMachinaryOfficeComponent;
diff --git a/src/components/dashboard/navgan-province-manager/Form/ConfirmForm.jsx b/src/components/dashboard/navgan-province-manager/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..a4d0c1a
--- /dev/null
+++ b/src/components/dashboard/navgan-province-manager/Form/ConfirmForm.jsx
@@ -0,0 +1,143 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import useDirection from "@/lib/app/hooks/useDirection";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import {CONFIRM_NAVGAN_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ confirm_img: null
+ },
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ if (values.description != "") formData.append("expert_description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_NAVGAN_PROVINCE_MANAGER}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/navgan-province-manager/Form/RejectForm.jsx b/src/components/dashboard/navgan-province-manager/Form/RejectForm.jsx
new file mode 100644
index 0000000..6f81b4a
--- /dev/null
+++ b/src/components/dashboard/navgan-province-manager/Form/RejectForm.jsx
@@ -0,0 +1,148 @@
+import {REJECT_NAVGAN_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useDirection from "@/lib/app/hooks/useDirection";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("expert_description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_NAVGAN_PROVINCE_MANAGER}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/navgan-province-manager/TableRowActions.jsx b/src/components/dashboard/navgan-province-manager/TableRowActions.jsx
new file mode 100644
index 0000000..601240f
--- /dev/null
+++ b/src/components/dashboard/navgan-province-manager/TableRowActions.jsx
@@ -0,0 +1,23 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+
+const TableRow = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+ );
+};
+
+export default TableRow;
diff --git a/src/components/dashboard/navgan-province-manager/TableTollbar.jsx b/src/components/dashboard/navgan-province-manager/TableTollbar.jsx
new file mode 100644
index 0000000..e267691
--- /dev/null
+++ b/src/components/dashboard/navgan-province-manager/TableTollbar.jsx
@@ -0,0 +1,13 @@
+import {Stack, Tooltip} from "@mui/material";
+import {useTranslations} from "next-intl";
+
+function TableToolbar() {
+ const t = useTranslations();
+ return (
+
+
+
+ );
+}
+
+export default TableToolbar;
diff --git a/src/components/dashboard/navgan-province-manager/index.jsx b/src/components/dashboard/navgan-province-manager/index.jsx
new file mode 100644
index 0000000..702175c
--- /dev/null
+++ b/src/components/dashboard/navgan-province-manager/index.jsx
@@ -0,0 +1,233 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {GET_NAVGAN_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import TableRowActions from "./TableRowActions";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import {faIR} from "@mui/x-date-pickers/locales";
+import DataTable from "@/core/components/DataTable";
+
+function DashboardNavganProvinceManagerComponent() {
+ const t = useTranslations();
+
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("NavganProvinceManager.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("NavganProvinceManager.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("NavganProvinceManager.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("NavganProvinceManager.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("NavganProvinceManager.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => {
+ return {renderedCellValue};
+ },
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "updated_at",
+ header: t("NavganProvinceManager.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.navgan_id,
+ id: "navgan_id",
+ header: t("NavganProvinceManager.navgan_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.vehicle_type,
+ id: "vehicle_type",
+ header: t("NavganProvinceManager.vehicle_type"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("NavganProvinceManager.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+
+
+
+ );
+}
+
+export default DashboardNavganProvinceManagerComponent;
diff --git a/src/components/dashboard/passenger-boss/Form/ConfirmForm.jsx b/src/components/dashboard/passenger-boss/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..d4305f5
--- /dev/null
+++ b/src/components/dashboard/passenger-boss/Form/ConfirmForm.jsx
@@ -0,0 +1,178 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import useDirection from "@/lib/app/hooks/useDirection";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import * as Yup from "yup";
+import useRequest from "@/lib/app/hooks/useRequest";
+import {CONFIRM_PASSENGER_BOSS} from "@/core/data/apiRoutes";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ approved_amount: Yup.number().positive(t("ConfirmDialog.approved_amount_positive")).required(t("ConfirmDialog.approved_amount_error"))
+ });
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ approved_amount: "",
+ confirm_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("approved_amount", values.approved_amount);
+ if (values.description != "") formData.append("expert_description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_PASSENGER_BOSS}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+ const handleAmountChange = (event) => {
+ formik.setFieldValue("approved_amount", event.target.value);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/passenger-boss/Form/RejectForm.jsx b/src/components/dashboard/passenger-boss/Form/RejectForm.jsx
new file mode 100644
index 0000000..3688ae7
--- /dev/null
+++ b/src/components/dashboard/passenger-boss/Form/RejectForm.jsx
@@ -0,0 +1,148 @@
+import {REJECT_PASSENGER_BOSS} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useDirection from "@/lib/app/hooks/useDirection";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("expert_description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_PASSENGER_BOSS}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/passenger-boss/TableRowActions.jsx b/src/components/dashboard/passenger-boss/TableRowActions.jsx
new file mode 100644
index 0000000..601240f
--- /dev/null
+++ b/src/components/dashboard/passenger-boss/TableRowActions.jsx
@@ -0,0 +1,23 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+
+const TableRow = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+ );
+};
+
+export default TableRow;
diff --git a/src/components/dashboard/passenger-boss/TableTollbar.jsx b/src/components/dashboard/passenger-boss/TableTollbar.jsx
new file mode 100644
index 0000000..e267691
--- /dev/null
+++ b/src/components/dashboard/passenger-boss/TableTollbar.jsx
@@ -0,0 +1,13 @@
+import {Stack, Tooltip} from "@mui/material";
+import {useTranslations} from "next-intl";
+
+function TableToolbar() {
+ const t = useTranslations();
+ return (
+
+
+
+ );
+}
+
+export default TableToolbar;
diff --git a/src/components/dashboard/passenger-boss/index.jsx b/src/components/dashboard/passenger-boss/index.jsx
new file mode 100644
index 0000000..5fe7342
--- /dev/null
+++ b/src/components/dashboard/passenger-boss/index.jsx
@@ -0,0 +1,234 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {GET_PASSENGER_BOSS} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import TableRowActions from "./TableRowActions";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import {faIR} from "@mui/x-date-pickers/locales";
+import DataTable from "@/core/components/DataTable";
+
+function DashboardPassengerOfficeComponent() {
+ const t = useTranslations();
+
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("PassengerBoss.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("PassengerBoss.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("PassengerBoss.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("PassengerBoss.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("PassengerBoss.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => {
+ return {renderedCellValue};
+ },
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "updated_at",
+ header: t("PassengerBoss.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.navgan_id,
+ id: "navgan_id",
+ header: t("PassengerBoss.navgan_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.vehicle_type,
+ id: "vehicle_type",
+ header: t("PassengerBoss.vehicle_type"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("PassengerBoss.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+ }
+ enableLastUpdate={true}
+ enablePinning={true}
+ enableDensityToggle={false}
+ initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
+ enableColumnFilters={true}
+ enableHiding={true}
+ enableFullScreenToggle={false}
+ enableGlobalFilter={false}
+ enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
+ enableRowActions={true}
+ TableRowAction={TableRowActions}
+ />
+
+
+ );
+}
+
+export default DashboardPassengerOfficeComponent;
diff --git a/src/components/dashboard/passenger-office/Form/ConfirmForm.jsx b/src/components/dashboard/passenger-office/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..1be22c8
--- /dev/null
+++ b/src/components/dashboard/passenger-office/Form/ConfirmForm.jsx
@@ -0,0 +1,142 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import useDirection from "@/lib/app/hooks/useDirection";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useRequest from "@/lib/app/hooks/useRequest";
+import {CONFIRM_PASSENGER_OFFICE} from "@/core/data/apiRoutes";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ confirm_img: null
+ },
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ if (values.description != "") formData.append("expert_description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_PASSENGER_OFFICE}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/passenger-office/Form/RejectForm.jsx b/src/components/dashboard/passenger-office/Form/RejectForm.jsx
new file mode 100644
index 0000000..b187a2b
--- /dev/null
+++ b/src/components/dashboard/passenger-office/Form/RejectForm.jsx
@@ -0,0 +1,148 @@
+import {REJECT_PASSENGER_OFFICE} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useDirection from "@/lib/app/hooks/useDirection";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("expert_description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_PASSENGER_OFFICE}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/passenger-office/TableRowActions.jsx b/src/components/dashboard/passenger-office/TableRowActions.jsx
new file mode 100644
index 0000000..601240f
--- /dev/null
+++ b/src/components/dashboard/passenger-office/TableRowActions.jsx
@@ -0,0 +1,23 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+
+const TableRow = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+ );
+};
+
+export default TableRow;
diff --git a/src/components/dashboard/passenger-office/TableTollbar.jsx b/src/components/dashboard/passenger-office/TableTollbar.jsx
new file mode 100644
index 0000000..e267691
--- /dev/null
+++ b/src/components/dashboard/passenger-office/TableTollbar.jsx
@@ -0,0 +1,13 @@
+import {Stack, Tooltip} from "@mui/material";
+import {useTranslations} from "next-intl";
+
+function TableToolbar() {
+ const t = useTranslations();
+ return (
+
+
+
+ );
+}
+
+export default TableToolbar;
diff --git a/src/components/dashboard/passenger-office/index.jsx b/src/components/dashboard/passenger-office/index.jsx
new file mode 100644
index 0000000..d36acff
--- /dev/null
+++ b/src/components/dashboard/passenger-office/index.jsx
@@ -0,0 +1,235 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {faIR} from "@mui/x-date-pickers/locales";
+import {GET_PASSENGER_OFFICE} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import TableRowActions from "./TableRowActions";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import DataTable from "@/core/components/DataTable";
+
+function DashboardPassengerOfficeComponent() {
+ const t = useTranslations();
+
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("PassengerOffice.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("PassengerOffice.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("PassengerOffice.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("PassengerOffice.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("PassengerOffice.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => {
+ return {renderedCellValue};
+ },
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ actionbar: {actions: ["accept", "today"]},
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | YYYY/MM/DD"),
+ id: "updated_at",
+ header: t("PassengerOffice.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.navgan_id,
+ id: "navgan_id",
+ header: t("PassengerOffice.navgan_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.vehicle_type,
+ id: "vehicle_type",
+ header: t("PassengerOffice.vehicle_type"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("PassengerOffice.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+ }
+ enableLastUpdate={true}
+ enablePinning={true}
+ enableDensityToggle={false}
+ initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
+ enableColumnFilters={true}
+ enableHiding={true}
+ enableFullScreenToggle={false}
+ enableGlobalFilter={false}
+ enableColumnResizing={false} // if you want true this you shold change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
+ enableRowActions={true}
+ TableRowAction={TableRowActions}
+ />
+
+
+ );
+}
+
+export default DashboardPassengerOfficeComponent;
diff --git a/src/components/dashboard/province-head-expert/Form/ConfirmForm.jsx b/src/components/dashboard/province-head-expert/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..c4cc607
--- /dev/null
+++ b/src/components/dashboard/province-head-expert/Form/ConfirmForm.jsx
@@ -0,0 +1,141 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import {CONFIRM_PROVINCE_HEAD_EXPERT} from "@/core/data/apiRoutes";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ confirm_img: null
+ },
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ if (values.description != "") formData.append("description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_PROVINCE_HEAD_EXPERT}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/province-head-expert/Form/RejectForm.jsx b/src/components/dashboard/province-head-expert/Form/RejectForm.jsx
new file mode 100644
index 0000000..e41f95a
--- /dev/null
+++ b/src/components/dashboard/province-head-expert/Form/RejectForm.jsx
@@ -0,0 +1,148 @@
+import {REJECT_PROVINCE_HEAD_EXPERT} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useDirection from "@/lib/app/hooks/useDirection";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_PROVINCE_HEAD_EXPERT}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/province-head-expert/Form/ReviceForm.jsx b/src/components/dashboard/province-head-expert/Form/ReviceForm.jsx
new file mode 100644
index 0000000..0c61316
--- /dev/null
+++ b/src/components/dashboard/province-head-expert/Form/ReviceForm.jsx
@@ -0,0 +1,108 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+} from "@mui/material";
+import EditIcon from '@mui/icons-material/Edit';
+import {useFormik} from "formik";
+import {REVISE_PROVINCE_HEAD_EXPERT} from "@/core/data/apiRoutes";
+import useRequest from "@/lib/app/hooks/useRequest";
+import * as Yup from "yup";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Revise = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ if (values.description != "") formData.append("description", values.description);
+
+ requestServer(`${REVISE_PROVINCE_HEAD_EXPERT}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Revise;
\ No newline at end of file
diff --git a/src/components/dashboard/province-head-expert/TableRowActions.jsx b/src/components/dashboard/province-head-expert/TableRowActions.jsx
new file mode 100644
index 0000000..b92f311
--- /dev/null
+++ b/src/components/dashboard/province-head-expert/TableRowActions.jsx
@@ -0,0 +1,29 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+import ReviseForm from "@/components/dashboard/province-head-expert/Form/ReviceForm";
+
+const TableRowActions = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+
+ );
+};
+
+export default TableRowActions;
diff --git a/src/components/dashboard/province-head-expert/TableTollbar.jsx b/src/components/dashboard/province-head-expert/TableTollbar.jsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/dashboard/province-head-expert/index.jsx b/src/components/dashboard/province-head-expert/index.jsx
new file mode 100644
index 0000000..ded6eef
--- /dev/null
+++ b/src/components/dashboard/province-head-expert/index.jsx
@@ -0,0 +1,202 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {GET_PROVINCE_HEAD_EXPERT} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import {faIR} from "@mui/x-date-pickers/locales";
+import DataTable from "@/core/components/DataTable";
+import TableRowActions from "./TableRowActions"
+
+function DashboardProvinceHeadExpertComponent() {
+ const t = useTranslations();
+
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("ProvinceHeadExpert.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("ProvinceHeadExpert.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("ProvinceHeadExpert.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("ProvinceHeadExpert.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("ProvinceHeadExpert.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => {
+ return {renderedCellValue};
+ },
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "updated_at",
+ header: t("ProvinceHeadExpert.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("ProvinceHeadExpert.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+
+
+
+ );
+}
+
+export default DashboardProvinceHeadExpertComponent;
diff --git a/src/components/dashboard/refahi-province-manager/Form/ConfirmForm.jsx b/src/components/dashboard/refahi-province-manager/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..f14421c
--- /dev/null
+++ b/src/components/dashboard/refahi-province-manager/Form/ConfirmForm.jsx
@@ -0,0 +1,143 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import useDirection from "@/lib/app/hooks/useDirection";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useRequest from "@/lib/app/hooks/useRequest";
+import {CONFIRM_REFAHI_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ confirm_img: null
+ },
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ if (values.description != "") formData.append("description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_REFAHI_PROVINCE_MANAGER}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/refahi-province-manager/Form/RejectForm.jsx b/src/components/dashboard/refahi-province-manager/Form/RejectForm.jsx
new file mode 100644
index 0000000..f253844
--- /dev/null
+++ b/src/components/dashboard/refahi-province-manager/Form/RejectForm.jsx
@@ -0,0 +1,148 @@
+import {REJECT_REFAHI_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useDirection from "@/lib/app/hooks/useDirection";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_REFAHI_PROVINCE_MANAGER}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/refahi-province-manager/TableRowActions.jsx b/src/components/dashboard/refahi-province-manager/TableRowActions.jsx
new file mode 100644
index 0000000..601240f
--- /dev/null
+++ b/src/components/dashboard/refahi-province-manager/TableRowActions.jsx
@@ -0,0 +1,23 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+
+const TableRow = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+ );
+};
+
+export default TableRow;
diff --git a/src/components/dashboard/refahi-province-manager/TableTollbar.jsx b/src/components/dashboard/refahi-province-manager/TableTollbar.jsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/dashboard/refahi-province-manager/index.jsx b/src/components/dashboard/refahi-province-manager/index.jsx
new file mode 100644
index 0000000..8122fcf
--- /dev/null
+++ b/src/components/dashboard/refahi-province-manager/index.jsx
@@ -0,0 +1,204 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {faIR} from "@mui/x-date-pickers/locales";
+import {GET_REFAHI_PROVINCE_MANAGER} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import TableRowActions from "./TableRowActions";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import DataTable from "@/core/components/DataTable";
+
+function DashboardRefahiProvinceManagerComponent() {
+ const t = useTranslations();
+
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("RefahiProvinceManager.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("RefahiProvinceManager.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("RefahiProvinceManager.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("RefahiProvinceManager.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("RefahiProvinceManager.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => {
+ return {renderedCellValue};
+ },
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ actionbar: {actions: ["accept", "today"]},
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | YYYY/MM/DD"),
+ id: "updated_at",
+ header: t("RefahiProvinceManager.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("RefahiProvinceManager.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+ }
+ enableLastUpdate={true}
+ enablePinning={true}
+ enableDensityToggle={false}
+ initialState={{density: 'compact'}} //compact (small) //comfortable (medium) //spacious (large)
+ enableColumnFilters={true}
+ enableHiding={true}
+ enableFullScreenToggle={false}
+ enableGlobalFilter={false}
+ enableColumnResizing={false} // if you want true this you should change renderRowActions props ** see https://www.material-react-table.com/docs/guides/row-actions
+ enableRowActions={true}
+ TableRowAction={TableRowActions}
+ />
+
+
+ );
+}
+
+export default DashboardRefahiProvinceManagerComponent;
diff --git a/src/components/dashboard/transportation-assistance/Form/ConfirmForm.jsx b/src/components/dashboard/transportation-assistance/Form/ConfirmForm.jsx
new file mode 100644
index 0000000..7aba85c
--- /dev/null
+++ b/src/components/dashboard/transportation-assistance/Form/ConfirmForm.jsx
@@ -0,0 +1,143 @@
+import {useTranslations} from "next-intl";
+import {useState} from "react";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography
+} from "@mui/material";
+import ThumbUpAltIcon from "@mui/icons-material/ThumbUpAlt";
+import UploadSystem from "@/core/components/UploadSystem";
+import useDirection from "@/lib/app/hooks/useDirection";
+import {useFormik} from "formik";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import {CONFIRM_TRANSPORTATION_ASSISTANCE} from "@/core/data/apiRoutes";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Confirm = ({rowId, fetchUrl, mutate}) => {
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ confirm_img: null
+ },
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ if (values.description != "") formData.append("expert_description", values.description);
+ if (values.confirm_img != null) formData.append("attachment", values.confirm_img);
+
+ requestServer(`${CONFIRM_TRANSPORTATION_ASSISTANCE}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value)
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("confirm_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ {
+ setOpenConfirmDialog(true)
+ }}
+ >
+
+
+
+
+ >
+ );
+};
+export default Confirm;
\ No newline at end of file
diff --git a/src/components/dashboard/transportation-assistance/Form/RejectForm.jsx b/src/components/dashboard/transportation-assistance/Form/RejectForm.jsx
new file mode 100644
index 0000000..d7a41df
--- /dev/null
+++ b/src/components/dashboard/transportation-assistance/Form/RejectForm.jsx
@@ -0,0 +1,148 @@
+import {REJECT_TRANSPORTATION_ASSISTANCE} from "@/core/data/apiRoutes";
+import {
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ IconButton,
+ Stack,
+ TextField,
+ Tooltip,
+ Typography,
+} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useFormik} from "formik";
+import * as Yup from "yup";
+import {useState} from "react";
+import UploadSystem from "@/core/components/UploadSystem";
+import UploadFileNotification from "@/core/components/notifications/UploadFileNotification";
+import useDirection from "@/lib/app/hooks/useDirection";
+import ThumbDownIcon from "@mui/icons-material/ThumbDown";
+import useRequest from "@/lib/app/hooks/useRequest";
+import useNotification from "@/lib/app/hooks/useNotification";
+
+
+const Reject = ({rowId, fetchUrl, mutate}) => {
+ const [selectedImage, setSelectedImage] = useState("");
+ const [fileType, setfileType] = useState(null);
+ const [fileName, setfileName] = useState(null);
+ const [showAddIcon, setShowAddIcon] = useState(true);
+ const t = useTranslations();
+ const {directionApp} = useDirection();
+ const [openRejectDialog, setOpenRejectDialog] = useState(false);
+ const requestServer = useRequest({auth: true})
+ const {update_notification} = useNotification()
+
+ const validationSchema = Yup.object().shape({
+ description: Yup.string().required(t("RejectDialog.description_error")),
+ });
+
+ const formik = useFormik({
+ initialValues: {
+ description: "",
+ reject_img: null
+ },
+ validationSchema,
+ onSubmit: (values, {setSubmitting}) => {
+ const formData = new FormData();
+ formData.append("expert_description", values.description);
+ if (values.reject_img != null) formData.append("attachment", values.reject_img);
+
+ requestServer(`${REJECT_TRANSPORTATION_ASSISTANCE}/${rowId}`, 'post', {
+ data: formData,
+ }).then((response) => {
+ mutate(fetchUrl)
+ update_notification()
+ }).catch(() => {
+ }).finally(() => {
+ setSubmitting(false);
+ });
+ },
+ });
+
+ const handleDescriptionChange = (event) => {
+ formik.setFieldValue("description", event.target.value);
+ formik.handleChange(event);
+ };
+ const handleUploadChange = (event) => {
+ const uploadedFile = event.target?.files?.[0];
+ if (uploadedFile) {
+ const maxFileSize = 2 * 1024 * 1024;
+ if (uploadedFile.size > maxFileSize) {
+ UploadFileNotification(t);
+ event.target.value = "";
+ return;
+ }
+ const fileType = event.target?.files?.[0].type;
+ const fileName = event.target?.files?.[0].name;
+ setSelectedImage(URL.createObjectURL(uploadedFile));
+ setfileType(fileType);
+ setfileName(fileName);
+ formik.setFieldValue("reject_img", uploadedFile);
+ setShowAddIcon(false);
+ }
+ };
+ return (
+ <>
+
+ setOpenRejectDialog(true)}>
+
+
+
+
+ >
+ );
+};
+export default Reject;
\ No newline at end of file
diff --git a/src/components/dashboard/transportation-assistance/TableRowActions.jsx b/src/components/dashboard/transportation-assistance/TableRowActions.jsx
new file mode 100644
index 0000000..601240f
--- /dev/null
+++ b/src/components/dashboard/transportation-assistance/TableRowActions.jsx
@@ -0,0 +1,23 @@
+import {Box} from "@mui/material";
+import ConfirmForm from "./Form/ConfirmForm"
+import RejectForm from "./Form/RejectForm"
+
+const TableRow = ({row, mutate, fetchUrl}) => {
+
+ return (
+
+
+
+
+ );
+};
+
+export default TableRow;
diff --git a/src/components/dashboard/transportation-assistance/TableTollbar.jsx b/src/components/dashboard/transportation-assistance/TableTollbar.jsx
new file mode 100644
index 0000000..e267691
--- /dev/null
+++ b/src/components/dashboard/transportation-assistance/TableTollbar.jsx
@@ -0,0 +1,13 @@
+import {Stack, Tooltip} from "@mui/material";
+import {useTranslations} from "next-intl";
+
+function TableToolbar() {
+ const t = useTranslations();
+ return (
+
+
+
+ );
+}
+
+export default TableToolbar;
diff --git a/src/components/dashboard/transportation-assistance/index.jsx b/src/components/dashboard/transportation-assistance/index.jsx
new file mode 100644
index 0000000..8f96ed4
--- /dev/null
+++ b/src/components/dashboard/transportation-assistance/index.jsx
@@ -0,0 +1,233 @@
+import DashboardLayouts from "@/layouts/dashboardLayouts";
+import {Box, IconButton, Typography} from "@mui/material";
+import ClearIcon from "@mui/icons-material/Clear";
+import {useMemo} from "react";
+import {GET_TRANSPORTATION_ASSISTANCE} from "@/core/data/apiRoutes";
+import {useTranslations} from "next-intl";
+import TableRowActions from "./TableRowActions";
+import {LocalizationProvider, MobileDateTimePicker,} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import {faIR} from "@mui/x-date-pickers/locales";
+import moment from "jalali-moment";
+import DataTable from "@/core/components/DataTable";
+
+function DashboardTransportationAssistanceComponent() {
+ const t = useTranslations();
+ const columns = useMemo(
+ () => [
+ {
+ accessorFn: (row) => row.id,
+ id: "id",
+ header: t("TransportationAssistance.id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.name,
+ id: "name",
+ header: t("TransportationAssistance.name"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+
+ {
+ accessorFn: (row) => row.national_id,
+ id: "national_id",
+ header: t("TransportationAssistance.national_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.phone_number,
+ id: "phone_number",
+ header: t("TransportationAssistance.phone_number"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.created_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "created_at",
+ header: t("TransportationAssistance.created_at"),
+ enableColumnFilter: true,
+ datatype: "date",
+ filterFn: "lessThan",
+ columnFilterModeOptions: ["lessThan", "greaterThan"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ Header: ({column}) => {column.columnDef.header},
+ Filter: ({column}) => {
+ const filterFnValue = column.columnDef._filterFn;
+ return (
+
+
+ {
+ const date = new Date(newValue);
+ const formattedDate = moment(date)
+ .locale("en")
+ .format("YYYY-MM-DD HH:mm");
+ column.setFilterValue(formattedDate);
+ }}
+ slotProps={{
+ textField: {
+ placeholder: "تاریخ خود را وارد کنید",
+ helperText: `${t("filter_mode")}: ${t(filterFnValue)}`,
+ sx: {minWidth: "120px"},
+ variant: "standard",
+ },
+ }}
+ value={
+ column.getFilterValue()
+ ? new Date(column.getFilterValue())
+ : null
+ }
+ />
+
+ {
+ column.setFilterValue(null);
+ }}
+ sx={{
+ color: column.getFilterValue()
+ ? "rgba(0, 0, 0, 0.54)"
+ : "#bfbfbf",
+ }}
+ >
+
+
+
+ );
+ },
+ },
+ {
+ accessorFn: (row) =>
+ moment(row.updated_at).locale("fa").format("HH:mm | yyyy/MM/DD"),
+ id: "updated_at",
+ header: t("TransportationAssistance.updated_at"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.navgan_id,
+ id: "navgan_id",
+ header: t("TransportationAssistance.navgan_id"),
+ enableColumnFilter: true,
+ datatype: "numeric",
+ filterFn: "equals",
+ columnFilterModeOptions: [
+ "equals",
+ "notEquals",
+ "contains",
+ "lessThan",
+ "greaterThan",
+ "between",
+ ],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.vehicle_type,
+ id: "vehicle_type",
+ header: t("TransportationAssistance.vehicle_type"),
+ enableColumnFilter: true,
+ datatype: "text",
+ filterFn: "contains",
+ columnFilterModeOptions: ["contains", "equals", "notEquals"],
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ {
+ accessorFn: (row) => row.state_name,
+ id: "state_id",
+ header: t("TransportationAssistance.state_name"),
+ enableColumnFilter: false,
+ datatype: "numeric",
+ Cell: ({renderedCellValue}) => (
+ {renderedCellValue}
+ ),
+ },
+ ],
+ []
+ );
+ return (
+
+
+
+
+
+ );
+}
+
+export default DashboardTransportationAssistanceComponent;
diff --git a/src/components/errors/403.jsx b/src/components/errors/403.jsx
new file mode 100644
index 0000000..ce91443
--- /dev/null
+++ b/src/components/errors/403.jsx
@@ -0,0 +1,37 @@
+import CenterLayout from "@/layouts/CenterLayout";
+import FullPageLayout from "@/layouts/FullPageLayout";
+import {Button, Typography} from "@mui/material";
+import {NextLinkComposed} from "@/core/components/LinkRouting";
+import {useTranslations} from "next-intl";
+import TitlePage from "@/core/components/TitlePage";
+import Svg403 from "@/core/components/svgs/Svg403";
+
+const UnAuthorizedComponent = () => {
+ const t = useTranslations();
+
+ return (
+ <>
+
+
+
+
+
+ {t("ErrorPage.custom_403")}
+
+
+
+
+ >
+ );
+};
+
+export default UnAuthorizedComponent;
diff --git a/src/components/errors/404.jsx b/src/components/errors/404.jsx
new file mode 100644
index 0000000..acfd418
--- /dev/null
+++ b/src/components/errors/404.jsx
@@ -0,0 +1,37 @@
+import CenterLayout from "@/layouts/CenterLayout";
+import FullPageLayout from "@/layouts/FullPageLayout";
+import {Button, Typography} from "@mui/material";
+import {NextLinkComposed} from "@/core/components/LinkRouting";
+import {useTranslations} from "next-intl";
+import TitlePage from "@/core/components/TitlePage";
+import Svg404 from "@/core/components/svgs/Svg404";
+
+const NotFoundComponent = () => {
+ const t = useTranslations();
+
+ return (
+ <>
+
+
+
+
+
+ {t("ErrorPage.custom_404")}
+
+
+
+
+ >
+ );
+};
+
+export default NotFoundComponent;
diff --git a/src/components/errors/500.jsx b/src/components/errors/500.jsx
new file mode 100644
index 0000000..10e9d12
--- /dev/null
+++ b/src/components/errors/500.jsx
@@ -0,0 +1,48 @@
+import CenterLayout from "@/layouts/CenterLayout";
+import FullPageLayout from "@/layouts/FullPageLayout";
+import {Box, Button, Container, Stack, Typography} from "@mui/material";
+import {NextLinkComposed} from "@/core/components/LinkRouting";
+import {useTranslations} from "next-intl";
+import Image from "next/image";
+import TitlePage from "@/core/components/TitlePage";
+
+const ServerErrorComponent = () => {
+ const t = useTranslations();
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+ {t("ErrorPage.custom_500")}
+
+
+
+
+
+
+ >
+ );
+};
+
+export default ServerErrorComponent;
diff --git a/src/components/first/index.jsx b/src/components/first/index.jsx
index adf4393..cd5b5a5 100644
--- a/src/components/first/index.jsx
+++ b/src/components/first/index.jsx
@@ -1,53 +1,56 @@
-import dahsboardImage from "&/images/dashboard.svg";
-import { NextLinkComposed } from "@/core/components/LinkRouting";
-import StyledImage from "@/core/components/StyledImage";
+import {NextLinkComposed} from "@/core/components/LinkRouting";
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
import useUser from "@/lib/app/hooks/useUser";
-import { Button, Typography } from "@mui/material";
-import { useTranslations } from "next-intl";
+import {Button, Stack, Typography} from "@mui/material";
+import {useTranslations} from "next-intl";
+import SvgDashboard from "@/core/components/svgs/SvgDashboard";
+import process from "next/dist/build/webpack/loaders/resolve-url-loader/lib/postcss";
const FirstComponent = () => {
- const t = useTranslations();
- const { isAuth } = useUser();
+ const t = useTranslations();
+ const {isAuth} = useUser();
- return (
-
-
-
-
- {t("app_name")}
-
- {isAuth ? (
-
- ) : (
-
- )}
-
-
- );
+ return (
+
+
+
+
+ {t("app_name")}
+
+ {isAuth ? (
+
+ ) : (
+
+ )}
+
+
+ v{process.env.NEXT_PUBLIC_API_VERSION}
+
+
+ );
};
export default FirstComponent;
diff --git a/src/components/login-expert/index.jsx b/src/components/login-expert/index.jsx
index 92d4e36..2eaa3bd 100644
--- a/src/components/login-expert/index.jsx
+++ b/src/components/login-expert/index.jsx
@@ -1,170 +1,153 @@
import LinkRouting from "@/core/components/LinkRouting";
-// import Notifications from "@/core/components/notifications";
import PasswordField from "@/core/components/PasswordField";
import StyledForm from "@/core/components/StyledForm";
-// import { GET_USER_TOKEN } from "@/core/data/apiRoutes";
+import {GET_USER_TOKEN} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
-import useDirection from "@/lib/app/hooks/useDirection";
import useUser from "@/lib/app/hooks/useUser";
import LoginIcon from "@mui/icons-material/Login";
-import PersonAddIcon from "@mui/icons-material/PersonAdd";
-import {
- Box,
- Button,
- Container,
- Paper,
- Stack,
- TextField,
- Typography,
-} from "@mui/material";
-// import axios from "axios";
-import { Field, Formik } from "formik";
-import { useTranslations } from "next-intl";
-import Image from "next/image";
-import { useSearchParams } from "next/navigation";
+import {Box, Button, Container, Paper, Stack, TextField, Typography,} from "@mui/material";
+import {Field, Formik} from "formik";
+import {useTranslations} from "next-intl";
+import {useSearchParams} from "next/navigation";
import * as Yup from "yup";
+import useDirection from "@/lib/app/hooks/useDirection";
+import SvgLogin from "@/core/components/svgs/SvgLogin";
+import useRequest from "@/lib/app/hooks/useRequest";
const LoginComponent = () => {
- const t = useTranslations();
- const { directionApp } = useDirection();
- const { setToken } = useUser(); // pass token to set token
+ const t = useTranslations();
+ const {directionApp} = useDirection(); // should delete because we don't have direction anymore
+ const {setToken} = useUser(); // pass token to set token
+ const requestServer = useRequest()
- // gettin url query
- const searchParams = useSearchParams();
- const backUrlDecodedPath = searchParams.get("back_url");
+ // getting url query
+ const searchParams = useSearchParams();
+ const backUrlDecodedPath = searchParams.get("back_url");
- // formik properties
-// const handleSubmit = async (values, props) => {
-// await axios
-// .post(GET_USER_TOKEN, {
-// username: values.username,
-// password: values.password,
-// })
-// .then(function (response) {
-// setToken(response.data.token);
-// })
-// .catch(function (error) {
-// Notifications(directionApp, error.response, t);
-// props.setSubmitting(false);
-// });
-// };
- const initialValues = {
- username: "",
- password: "",
- };
- const validationSchema = Yup.object().shape({
- username: Yup.string().required(t("LoginPage.error_message_required")),
- password: Yup.string().required(t("LoginPage.error_message_required")),
- });
+ //formik properties
+ const handleSubmit = (values, props) => {
+ requestServer(GET_USER_TOKEN, 'post', {
+ data: {
+ username: values.username,
+ password: values.password,
+ },
+ success: {
+ notification: {show: false}
+ }
+ }).then((response) => {
+ setToken(response.data.token)
+ }).catch(() => {
+ props.setSubmitting(false)
+ })
+ };
+ const initialValues = {
+ username: "",
+ password: "",
+ };
+ const validationSchema = Yup.object().shape({
+ username: Yup.string().required(t("LoginPage.error_message_required")),
+ password: Yup.string().required(t("LoginPage.error_message_required")),
+ });
- return (
-
-
-
-
-
- {(props) => (
-
-
-
-
-
- {t("login_expert")}
-
-
-
-
-
-
-
- }
- disabled={props.isSubmitting ? true : false}
- >
- {t("LoginPage.button_make_account")}
-
-
- }
- disabled={props.isSubmitting ? true : false}
+ return (
+
+
+
+
+
- {t("LoginPage.button_submit")}
-
-
-
-
-
- )}
-
-
-
-
-
-
- {t("LoginPage.link_routing_back_to")}{" "}
- {backUrlDecodedPath
- ? t("LoginPage.link_routing_previuos_page")
- : t("LoginPage.link_routing_main_page")}
-
-
-
- );
+ {(props) => (
+
+
+
+
+
+ {t("login_expert")}
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+
+
+
+ {t("LoginPage.link_routing_back_to")}{" "}
+ {backUrlDecodedPath
+ ? t("LoginPage.link_routing_previuos_page")
+ : t("LoginPage.link_routing_main_page")}
+
+
+
+ );
};
export default LoginComponent;
diff --git a/src/core/components/AvatarUpload.jsx b/src/core/components/AvatarUpload.jsx
new file mode 100644
index 0000000..03a9cba
--- /dev/null
+++ b/src/core/components/AvatarUpload.jsx
@@ -0,0 +1,128 @@
+import {Avatar, Box, TextField} from "@mui/material";
+import {useState} from "react";
+import DeleteIcon from "@mui/icons-material/Delete";
+import AddIcon from "@mui/icons-material/Add";
+
+const AvatarUpload = ({user, setFieldValue, valueAvatar, changeFlag}) => {
+ const [selectedImage, setSelectedImage] = useState(user.expert_avatar);
+ const [isHovered, setIsHovered] = useState(false);
+
+ const handleImageChange = (event) => {
+ const newImage = event.target?.files?.[0];
+ if (newImage) {
+ setSelectedImage(URL.createObjectURL(newImage));
+ setFieldValue(valueAvatar, newImage);
+ setFieldValue(changeFlag, true);
+ } else {
+ setSelectedImage("");
+ setFieldValue(valueAvatar, null);
+ }
+ };
+
+ const handleDeleteImage = () => {
+ setSelectedImage("");
+ setFieldValue(valueAvatar, null);
+ setFieldValue(changeFlag, true);
+ };
+
+ const handleMouseEnter = () => {
+ setIsHovered(true);
+ };
+
+ const handleMouseLeave = () => {
+ setIsHovered(false);
+ };
+
+ return (
+
+
+
+
+ {isHovered && (
+
+ {selectedImage ? (
+
+ ) : (
+
+ )}
+
+ )}
+
+
+
+
+ );
+};
+
+export default AvatarUpload;
diff --git a/src/core/components/DataTable.jsx b/src/core/components/DataTable.jsx
new file mode 100644
index 0000000..b3b0f26
--- /dev/null
+++ b/src/core/components/DataTable.jsx
@@ -0,0 +1,176 @@
+import {useTranslations} from "next-intl";
+import useLanguage from "@/lib/app/hooks/useLanguage";
+import {useEffect, useMemo, useState} from "react";
+import moment from "moment-jalaali";
+import useSWR from "swr";
+import {Typography} from "@mui/material";
+import MaterialReactTable from "material-react-table";
+import useRequest from "@/lib/app/hooks/useRequest";
+
+function DataTable(props) {
+ const requestServer = useRequest({auth: true})
+ const fetcher = (...args) => {
+ return requestServer(args, 'get', {
+ pending: false,
+ success: {notification: {show: false}}
+ }).then((response) => {
+ setRowCount(response.data.meta.totalRowCount);
+ return response.data.data;
+ }).catch(() => {
+ })
+ };
+ const t = useTranslations();
+ const {languageApp, languageList} = useLanguage();
+ const [columnFilters, setColumnFilters] = useState([]);
+ const [sorting, setSorting] = useState([]);
+ const [pagination, setPagination] = useState({pageIndex: 0, pageSize: 10});
+ const [rowCount, setRowCount] = useState(0);
+ const [columnFilterFns, setColumnFilterFns] = useState(() => {
+ let output = {};
+ const list = props.columns.map((item) =>
+ item.enableColumnFilter ? {[item.id]: item.filterFn} : {[item.id]: ""}
+ );
+ for (var key in list) {
+ var nestedObj = list[key];
+ for (var nestedKey in nestedObj) {
+ output[nestedKey] = nestedObj[nestedKey];
+ }
+ }
+ return output;
+ });
+
+ const [updateTime, setupdateTime] = useState(
+ moment().format("HH:mm | jYYYY/jM/jD")
+ );
+
+ const tableLocalization = useMemo(
+ () =>
+ languageList.find((item) => item.key == languageApp).tableLocalization,
+ [languageApp, languageList]
+ );
+
+ const fetchUrl = useMemo(() => {
+ const url = new URL(props.tableUrl);
+ url.searchParams.set(
+ "start",
+ `${pagination.pageIndex * pagination.pageSize}`
+ );
+ const filters = columnFilters.map((filter) => {
+ let datatype;
+ for (const i in props.columns) {
+ if (props.columns[i].id == filter.id) {
+ datatype = props.columns[i].datatype;
+ }
+ }
+ return {
+ ...filter,
+ fn: columnFilterFns[filter.id],
+ datatype: datatype,
+ };
+ });
+ url.searchParams.set("size", pagination.pageSize);
+ url.searchParams.set("filters", JSON.stringify(filters ?? []));
+ url.searchParams.set("sorting", JSON.stringify(sorting ?? []));
+ return url;
+ }, [
+ props.tableUrl,
+ columnFilters,
+ columnFilterFns,
+ pagination,
+ sorting,
+ props.columns,
+ ]);
+
+ const {data, isValidating, mutate} = useSWR(fetchUrl, fetcher, {
+ revalidateIfStale: false,
+ revalidateOnFocus: false,
+ revalidateOnReconnect: false
+ });
+
+ useEffect(() => {
+ setupdateTime(moment().format("HH:mm | jYYYY/jM/jD"));
+ }, [isValidating, languageApp]);
+
+ return (
+ (
+ <>
+ {props.enableCustomToolbar /* send condition */
+ ? props.CustomToolbar /* send component */
+ : ""}
+ >
+ )}
+ renderBottomToolbarCustomActions={({table}) => (
+ <>
+ {props.enableLastUpdate /* send condition */ ? (
+
+ {t("last_updated_at")}: {updateTime}
+
+ ) : (
+ ""
+ )}
+ >
+ )}
+ state={{
+ isLoading: isValidating,
+ columnFilters,
+ columnFilterFns,
+ pagination,
+ sorting,
+ }}
+ positionActionsColumn={"last"}
+ enableRowActions={props.enableRowActions}
+ renderRowActions={({row}) => }
+ {...props}
+ />
+ );
+}
+
+export default DataTable;
\ No newline at end of file
diff --git a/src/core/components/GlobalHead.jsx b/src/core/components/GlobalHead.jsx
new file mode 100644
index 0000000..5d6186d
--- /dev/null
+++ b/src/core/components/GlobalHead.jsx
@@ -0,0 +1,58 @@
+import Head from "next/head";
+
+const GlobalHead = () => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default GlobalHead
\ No newline at end of file
diff --git a/src/core/components/ImageConvertor.jsx b/src/core/components/ImageConvertor.jsx
new file mode 100644
index 0000000..9f99bc1
--- /dev/null
+++ b/src/core/components/ImageConvertor.jsx
@@ -0,0 +1,22 @@
+import ImageResize from "image-resize";
+
+const ImageResizer = async (image) => {
+ const imageResize = new ImageResize({
+ quality: 1,
+ format: "jpg",
+ outputType: "base64",
+ width: 400,
+ });
+
+ const get = await imageResize.get(image);
+ const resize = await imageResize.resize(get).then();
+ const output = await imageResize.output(resize).then();
+
+ const avatar = await (await import("image-to-file-converter"))
+ .base64ToFile(output)
+ .then();
+
+ return avatar;
+};
+
+export default ImageResizer;
diff --git a/src/core/components/LinkRouting.jsx b/src/core/components/LinkRouting.jsx
index ff33c86..f8fac0a 100644
--- a/src/core/components/LinkRouting.jsx
+++ b/src/core/components/LinkRouting.jsx
@@ -1,116 +1,116 @@
import MuiLink from "@mui/material/Link";
-import { styled } from "@mui/material/styles";
+import {styled} from "@mui/material/styles";
import clsx from "clsx";
import NextLink from "next/link";
-import { useRouter } from "next/router";
+import {useRouter} from "next/router";
import * as React from "react";
// Add support for the sx prop for consistency with the other branches.
const Anchor = styled("a")({});
export const NextLinkComposed = React.forwardRef(function NextLinkComposed(
- props,
- ref
+ props,
+ ref
) {
- const {
- to,
- linkAs,
- replace,
- scroll,
- shallow,
- prefetch,
- legacyBehavior = true,
- locale,
- ...other
- } = props;
+ const {
+ to,
+ linkAs,
+ replace,
+ scroll,
+ shallow,
+ prefetch,
+ legacyBehavior = true,
+ locale,
+ ...other
+ } = props;
- return (
-
-
-
- );
+ return (
+
+
+
+ );
});
// A styled version of the Next.js Link component:
// https://nextjs.org/docs/api-reference/next/link
const LinkRouting = React.forwardRef(function Link(props, ref) {
- const {
- activeClassName = "active",
- as,
- className: classNameProps,
- href,
- legacyBehavior,
- linkAs: linkAsProp,
- locale,
- noLinkStyle,
- prefetch,
- replace,
- role, // Link don't have roles.
- scroll,
- shallow,
- ...other
- } = props;
+ const {
+ activeClassName = "active",
+ as,
+ className: classNameProps,
+ href,
+ legacyBehavior,
+ linkAs: linkAsProp,
+ locale,
+ noLinkStyle,
+ prefetch,
+ replace,
+ role, // Link don't have roles.
+ scroll,
+ shallow,
+ ...other
+ } = props;
- const router = useRouter();
- const pathname = typeof href === "string" ? href : href.pathname;
- const className = clsx(classNameProps, {
- [activeClassName]: router.pathname === pathname && activeClassName,
- });
+ const router = useRouter();
+ const pathname = typeof href === "string" ? href : href.pathname;
+ const className = clsx(classNameProps, {
+ [activeClassName]: router.pathname === pathname && activeClassName,
+ });
- const isExternal =
- typeof href === "string" &&
- (href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
+ const isExternal =
+ typeof href === "string" &&
+ (href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
- if (isExternal) {
- if (noLinkStyle) {
- return ;
+ if (isExternal) {
+ if (noLinkStyle) {
+ return ;
+ }
+
+ return ;
}
- return ;
- }
+ const linkAs = linkAsProp || as;
+ const nextjsProps = {
+ to: href,
+ linkAs,
+ replace,
+ scroll,
+ shallow,
+ prefetch,
+ legacyBehavior,
+ locale,
+ };
- const linkAs = linkAsProp || as;
- const nextjsProps = {
- to: href,
- linkAs,
- replace,
- scroll,
- shallow,
- prefetch,
- legacyBehavior,
- locale,
- };
+ if (noLinkStyle) {
+ return (
+
+ );
+ }
- if (noLinkStyle) {
return (
-
+
);
- }
-
- return (
-
- );
});
export default LinkRouting;
diff --git a/src/core/components/LoadingHardPage.jsx b/src/core/components/LoadingHardPage.jsx
index 5da632d..c3b24d6 100644
--- a/src/core/components/LoadingHardPage.jsx
+++ b/src/core/components/LoadingHardPage.jsx
@@ -1,44 +1,42 @@
-import { Backdrop, Fade, styled } from "@mui/material";
-import StyledImage from "./StyledImage";
+import {Backdrop, Box, styled} from "@mui/material";
+import SvgLoading from "@/core/components/svgs/SvgLoading";
-const LoadingImage = styled(StyledImage)({
- "@keyframes load": {
- "0%": {
- // opacity: 0,
- transform: "scale(1)",
+const LoadingImage = styled(Box)({
+ "@keyframes load": {
+ "0%": {
+ // opacity: 0,
+ transform: "scale(1)",
+ },
+ "50%": {
+ // opacity: 1,
+ transform: "scale(2)",
+ },
+ "100%": {
+ // opacity: 0,
+ transform: "scale(1)",
+ },
},
- "50%": {
- // opacity: 1,
- transform: "scale(2)",
- },
- "100%": {
- // opacity: 0,
- transform: "scale(1)",
- },
- },
- animation: "load 2s infinite",
+ animation: "load 2s infinite",
});
-const LoadingHardPage = ({ children, loading }) => {
- return (
- <>
- theme.zIndex.drawer + 1 }}
- open={loading}
- >
-
-
-
-
- {children}
- >
- );
+const LoadingHardPage = ({children, loading}) => {
+ return (
+ <>
+ theme.zIndex.drawer + 1}}
+ open={loading}
+ >
+
+
+
+
+ {children}
+ >
+ );
};
export default LoadingHardPage;
diff --git a/src/core/components/Messages.jsx b/src/core/components/Messages.jsx
index ea9cd29..8a5cfc9 100644
--- a/src/core/components/Messages.jsx
+++ b/src/core/components/Messages.jsx
@@ -1,22 +1,18 @@
import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout";
-import StyledImage from "./StyledImage";
+import SvgLoading from "@/core/components/svgs/SvgLoading";
-const Message = ({ text, actions }) => {
- return (
-
-
-
- {text}
- {actions}
-
-
- );
+const Message = ({text, actions}) => {
+ return (
+
+
+
+ {text}
+ {actions}
+
+
+ );
};
export default Message;
diff --git a/src/core/components/MuiDatePicker.jsx b/src/core/components/MuiDatePicker.jsx
new file mode 100644
index 0000000..de6c5d5
--- /dev/null
+++ b/src/core/components/MuiDatePicker.jsx
@@ -0,0 +1,35 @@
+import {DatePicker, LocalizationProvider} from "@mui/x-date-pickers";
+import {AdapterDateFnsJalali} from "@mui/x-date-pickers/AdapterDateFnsJalali";
+import moment from "jalali-moment";
+import {useTranslations} from "next-intl";
+
+export default function MuiDatePicker({
+ setFieldValue,
+ selectType,
+ error,
+ helperText,
+ }) {
+ const t = useTranslations();
+
+ const handleDateChange = (date) => {
+ const selectedDate = moment(date).locale("fa"); // should add .format() at the end to format the data
+ setFieldValue(selectType, selectedDate);
+ };
+
+ return (
+
+
+
+ );
+}
diff --git a/src/core/components/NetworkComponent.jsx b/src/core/components/NetworkComponent.jsx
new file mode 100644
index 0000000..8ebbb68
--- /dev/null
+++ b/src/core/components/NetworkComponent.jsx
@@ -0,0 +1,34 @@
+import useNetwork from "@/lib/app/hooks/useNetwork";
+import {useEffect, useRef} from "react";
+import {toast} from "react-toastify";
+import WifiIcon from '@mui/icons-material/Wifi';
+import WifiOffIcon from '@mui/icons-material/WifiOff';
+import {useTranslations} from "next-intl";
+
+const NetworkComponent = () => {
+ const toastId = useRef(null);
+ const network = useNetwork()
+ const t = useTranslations()
+
+ useEffect(() => {
+ if (network.online) {
+ toast.update(toastId.current, {
+ type: toast.TYPE.SUCCESS,
+ render: t('online_message'),
+ autoClose: 2000,
+ closeButton: true,
+ closeOnClick: true,
+ icon:
+ });
+ return
+ }
+ toast.dismiss()
+ toastId.current = toast.warn(t('offline_message'), {
+ autoClose: false, closeButton: false, closeOnClick: false, icon:
+ })
+ }, [network.online]);
+
+ return ''
+}
+
+export default NetworkComponent
\ No newline at end of file
diff --git a/src/core/components/NoSsrHandler.jsx b/src/core/components/NoSsrHandler.jsx
new file mode 100644
index 0000000..5a4c4e1
--- /dev/null
+++ b/src/core/components/NoSsrHandler.jsx
@@ -0,0 +1,8 @@
+import {NoSsr} from "@mui/material";
+
+const NoSsrHandler = ({isBot, children}) => {
+ if (isBot) return children;
+ return {children};
+};
+
+export default NoSsrHandler;
diff --git a/src/core/components/PasswordField.jsx b/src/core/components/PasswordField.jsx
index 5747bdb..d109b73 100644
--- a/src/core/components/PasswordField.jsx
+++ b/src/core/components/PasswordField.jsx
@@ -1,33 +1,33 @@
-import { useState } from "react";
-import { IconButton, InputAdornment, TextField } from "@mui/material";
-import { Visibility, VisibilityOff } from "@mui/icons-material";
-import { Field } from "formik";
+import {useState} from "react";
+import {IconButton, InputAdornment, TextField} from "@mui/material";
+import {Visibility, VisibilityOff} from "@mui/icons-material";
+import {Field} from "formik";
const PasswordField = (props) => {
- const [showPassword, setShowPassword] = useState(false);
+ const [showPassword, setShowPassword] = useState(false);
- const handleClickShowPassword = () => {
- setShowPassword(!showPassword);
- };
+ const handleClickShowPassword = () => {
+ setShowPassword(!showPassword);
+ };
- return (
-
-
- {showPassword ? : }
-
-
- ),
- }}
- />
- );
+ return (
+
+
+ {showPassword ? : }
+
+
+ ),
+ }}
+ />
+ );
};
export default PasswordField;
diff --git a/src/core/components/StyledForm.jsx b/src/core/components/StyledForm.jsx
index 1f299bb..41eeabc 100644
--- a/src/core/components/StyledForm.jsx
+++ b/src/core/components/StyledForm.jsx
@@ -1,5 +1,5 @@
-import { styled } from "@mui/material";
-import { Form } from "formik";
+import {styled} from "@mui/material";
+import {Form} from "formik";
const StyledForm = styled(Form)``;
diff --git a/src/core/components/StyledImage.jsx b/src/core/components/StyledImage.jsx
index 64391ad..58dd65f 100644
--- a/src/core/components/StyledImage.jsx
+++ b/src/core/components/StyledImage.jsx
@@ -1,4 +1,4 @@
-import { styled } from "@mui/material";
+import {styled} from "@mui/material";
import Image from "next/image";
const StyledImage = styled(Image)``;
diff --git a/src/core/components/TitlePage.jsx b/src/core/components/TitlePage.jsx
index 7bdcfc2..77c72ee 100644
--- a/src/core/components/TitlePage.jsx
+++ b/src/core/components/TitlePage.jsx
@@ -1,15 +1,15 @@
-import { useTranslations } from "next-intl";
+import {useTranslations} from "next-intl";
import Head from "next/head";
-const TitlePage = ({ text }) => {
- const t = useTranslations();
- return (
-
-
- {text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
-
-
- );
+const TitlePage = ({text}) => {
+ const t = useTranslations();
+ return (
+
+
+ {text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
+
+
+ );
};
export default TitlePage;
diff --git a/src/core/components/UploadSystem.jsx b/src/core/components/UploadSystem.jsx
new file mode 100644
index 0000000..b40fb46
--- /dev/null
+++ b/src/core/components/UploadSystem.jsx
@@ -0,0 +1,175 @@
+import {Box, Button, Paper, Typography} from "@mui/material";
+import {useTranslations} from "next-intl";
+import AddIcon from "@mui/icons-material/Add";
+import DeleteForeverIcon from "@mui/icons-material/DeleteForever";
+import {useRef} from "react";
+
+const UploadSystem = ({
+ selectedImage,
+ setselectedImage,
+ handleUploadChange,
+ fieldname,
+ setFieldValue,
+ imageAlt,
+ imageSize,
+ fileType,
+ fileName,
+ setShowAddIcon,
+ showAddIcon,
+ }) => {
+ const t = useTranslations();
+ const fileInputRef = useRef(null);
+
+ const handleClick = () => {
+ fileInputRef.current.click();
+ };
+
+ const handleDeleteImage = () => {
+ setselectedImage(null);
+ setFieldValue(fieldname, null);
+ setShowAddIcon(true);
+ if (fileInputRef.current) {
+ fileInputRef.current.value = "";
+ }
+ };
+
+ const isDocumentFormat = (fileType) => {
+ const documentFormats = [
+ "application/pdf",
+ "application/msword",
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+ "application/vnd.ms-excel",
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+ ];
+ return documentFormats.includes(fileType);
+ };
+
+ return (
+
+ {showAddIcon ? (
+ // Show the add icon and "Upload File" text when no image is selected
+ <>
+
+
+
+ {t("UploadSystem.upload_file")}
+
+
+ >
+ ) : (
+ // Show the uploaded content along with the delete button when an image or document is selected
+ <>
+ {fileType && fileType.startsWith("image/") ? (
+
+
+
+ ) : (
+ fileType &&
+ isDocumentFormat(fileType) && (
+
+
+ {fileName}
+
+
+ )
+ )}
+
+ >
+ )}
+
+
+ );
+};
+
+export default UploadSystem;
diff --git a/src/core/components/isBotHandler.jsx b/src/core/components/isBotHandler.jsx
deleted file mode 100644
index 0fde3e3..0000000
--- a/src/core/components/isBotHandler.jsx
+++ /dev/null
@@ -1,8 +0,0 @@
-import { NoSsr } from "@mui/material";
-
-const NoSsrHandler = ({ isBot, children }) => {
- if (isBot) return children;
- return {children};
-};
-
-export default NoSsrHandler;
diff --git a/src/core/components/notifications/ErrorNotification.jsx b/src/core/components/notifications/ErrorNotification.jsx
new file mode 100644
index 0000000..4ff1ab0
--- /dev/null
+++ b/src/core/components/notifications/ErrorNotification.jsx
@@ -0,0 +1,39 @@
+import DangerousIcon from "@mui/icons-material/Dangerous";
+import {Box, Typography} from "@mui/material";
+import {toast} from "react-toastify";
+
+const ErrorNotification = (t, status, message) => {
+ toast(
+ () => (
+ <>
+
+
+
+
+
+ {t("notifications.error")} ({t("notifications.code")}: {status})
+
+
+ {message || t("notifications.error_static_text")}
+
+
+
+
+ >
+ ),
+ {
+ autoClose: false,
+ closeOnClick: false,
+ draggable: false,
+ }
+ );
+};
+
+export default ErrorNotification;
diff --git a/src/core/components/notifications/PendingNotification.jsx b/src/core/components/notifications/PendingNotification.jsx
new file mode 100644
index 0000000..846b847
--- /dev/null
+++ b/src/core/components/notifications/PendingNotification.jsx
@@ -0,0 +1,12 @@
+import {toast} from "react-toastify";
+
+const PendingNotification = (t) => {
+ toast(t("notifications.pending"), {
+ autoClose: false,
+ closeButton: false,
+ closeOnClick: false,
+ draggable: false,
+ });
+};
+
+export default PendingNotification;
diff --git a/src/core/components/notifications/SuccessNotification.jsx b/src/core/components/notifications/SuccessNotification.jsx
new file mode 100644
index 0000000..998deaa
--- /dev/null
+++ b/src/core/components/notifications/SuccessNotification.jsx
@@ -0,0 +1,42 @@
+import BeenhereIcon from "@mui/icons-material/Beenhere";
+import {Box, Typography} from "@mui/material";
+import {toast} from "react-toastify";
+
+const SuccessNotification = (t, status) => {
+ toast(
+ () => (
+ <>
+
+
+
+
+
+ {t("notifications.success")} ({t("notifications.code")}:{" "}
+ {status})
+
+
+ {t("notifications.success_static_text")}
+
+
+
+
+ >
+ ),
+ {
+ autoClose: 3000,
+ hideProgressBar: true,
+ pauseOnHover: true,
+ closeOnClick: false,
+ draggable: true,
+ }
+ );
+};
+
+export default SuccessNotification;
diff --git a/src/core/components/notifications/UploadFileNotification.jsx b/src/core/components/notifications/UploadFileNotification.jsx
new file mode 100644
index 0000000..6556944
--- /dev/null
+++ b/src/core/components/notifications/UploadFileNotification.jsx
@@ -0,0 +1,38 @@
+import DangerousIcon from "@mui/icons-material/Dangerous";
+import {Box, Typography} from "@mui/material";
+import {toast} from "react-toastify";
+
+const UploadFileNotification = (t) => {
+ toast(
+ ({closeToast}) => (
+ <>
+
+
+
+
+
+ {t("UploadSystem.uploadfile_error")}
+
+
+
+
+ >
+ ),
+ {
+ autoClose: 3000,
+ hideProgressBar: true,
+ pauseOnHover: true,
+ closeOnClick: false,
+ draggable: true,
+ }
+ );
+};
+
+export default UploadFileNotification;
diff --git a/src/core/components/notifications/WarningNotification.jsx b/src/core/components/notifications/WarningNotification.jsx
new file mode 100644
index 0000000..8493180
--- /dev/null
+++ b/src/core/components/notifications/WarningNotification.jsx
@@ -0,0 +1,40 @@
+import ReportIcon from "@mui/icons-material/Report";
+import {Box, Typography} from "@mui/material";
+import {toast} from "react-toastify";
+
+const WarningNotification = (t, status) => {
+ toast(
+ () => (
+ <>
+
+
+
+
+
+ {t("notifications.warning")} ({t("notifications.code")}:{" "}
+ {status})
+
+
+ {t("notifications.warning_static_text")}
+
+
+
+
+ >
+ ),
+ {
+ autoClose: false,
+ closeOnClick: false,
+ draggable: false,
+ }
+ );
+};
+
+export default WarningNotification;
diff --git a/src/core/components/notifications/index.jsx b/src/core/components/notifications/index.jsx
new file mode 100644
index 0000000..bc8eb66
--- /dev/null
+++ b/src/core/components/notifications/index.jsx
@@ -0,0 +1,54 @@
+import {toast} from "react-toastify";
+import ErrorNotification from "./ErrorNotification";
+import WarningNotification from "./WarningNotification";
+import SuccessNotification from "./SuccessNotification";
+
+const Notifications = async (t, response) => {
+ const {status, data} = response != undefined ? response : ""
+ toast.dismiss();
+ switch (status) {
+ case 200:
+ SuccessNotification(t, status);
+ break;
+ case 400:
+ ErrorNotification(t, status);
+ break;
+ case 401:
+ ErrorNotification(t, status);
+ break;
+ case 403:
+ ErrorNotification(t, status);
+ break;
+ case 422:
+ ErrorNotification(t, status, data.message);
+ break;
+ case 500:
+ WarningNotification(t, status);
+ break;
+ case 503:
+ WarningNotification(t, status);
+ break;
+ case 504:
+ WarningNotification(t, status);
+ break;
+ default:
+ toast(t("notifications.pending"), {
+ autoClose: false,
+ closeOnClick: false,
+ draggable: false,
+ });
+ break;
+ }
+};
+
+export default Notifications;
+
+/*
+usage document
+
+** for pending use ( Notifications( t, undefined) ) this before your request.
+** for success use ( Notifications( t, response) ) this inside .then() of your request.
+** for Error and Warning use ( Notifications( t, error.response) ) this inside .catche() of your request.
+
+end usage document
+*/
diff --git a/src/core/components/svgs/Svg403.jsx b/src/core/components/svgs/Svg403.jsx
new file mode 100644
index 0000000..720828c
--- /dev/null
+++ b/src/core/components/svgs/Svg403.jsx
@@ -0,0 +1,131 @@
+import {useTheme} from "@mui/material";
+
+const Svg403 = ({width, height}) => {
+ const theme = useTheme()
+ const fillColor = theme.palette.primary.main
+
+ return (
+
+ )
+
+}
+
+export default Svg403
\ No newline at end of file
diff --git a/src/core/components/svgs/Svg404.jsx b/src/core/components/svgs/Svg404.jsx
new file mode 100644
index 0000000..e46ab12
--- /dev/null
+++ b/src/core/components/svgs/Svg404.jsx
@@ -0,0 +1,101 @@
+import {useTheme} from "@mui/material";
+
+const Svg404 = ({width, height}) => {
+ const theme = useTheme()
+ const fillColor = theme.palette.primary.main
+
+ return (
+
+ )
+}
+
+export default Svg404
\ No newline at end of file
diff --git a/src/core/components/svgs/SvgChangePassword.jsx b/src/core/components/svgs/SvgChangePassword.jsx
new file mode 100644
index 0000000..a7ee82f
--- /dev/null
+++ b/src/core/components/svgs/SvgChangePassword.jsx
@@ -0,0 +1,77 @@
+import {useTheme} from "@mui/material";
+
+const SvgChangePassword = ({width, height}) => {
+ const theme = useTheme()
+ const fillColor = theme.palette.primary.main
+
+ return (
+
+ )
+}
+
+export default SvgChangePassword
\ No newline at end of file
diff --git a/src/core/components/svgs/SvgDashboard.jsx b/src/core/components/svgs/SvgDashboard.jsx
new file mode 100644
index 0000000..a5b40e0
--- /dev/null
+++ b/src/core/components/svgs/SvgDashboard.jsx
@@ -0,0 +1,117 @@
+import {useTheme} from "@mui/material";
+
+const SvgDashboard = ({width, height}) => {
+ const theme = useTheme()
+ const fillColor = theme.palette.primary.main
+
+ return (
+
+ )
+}
+
+export default SvgDashboard
\ No newline at end of file
diff --git a/src/core/components/svgs/SvgLoading.jsx b/src/core/components/svgs/SvgLoading.jsx
new file mode 100644
index 0000000..f9cea4a
--- /dev/null
+++ b/src/core/components/svgs/SvgLoading.jsx
@@ -0,0 +1,136 @@
+import {useTheme} from "@mui/material";
+
+const SvgLoading = ({width, height}) => {
+ const theme = useTheme()
+ const fillColor = theme.palette.primary.main
+
+ return (
+
+ )
+}
+
+export default SvgLoading
\ No newline at end of file
diff --git a/src/core/components/svgs/SvgLogin.jsx b/src/core/components/svgs/SvgLogin.jsx
new file mode 100644
index 0000000..643c195
--- /dev/null
+++ b/src/core/components/svgs/SvgLogin.jsx
@@ -0,0 +1,75 @@
+import {useTheme} from "@mui/material";
+
+const SvgLogin = ({width, height}) => {
+ const theme = useTheme()
+ const fillColor = theme.palette.primary.main
+
+ return (
+
+ )
+
+}
+
+export default SvgLogin
\ No newline at end of file
diff --git a/src/core/data/apiRoutes.js b/src/core/data/apiRoutes.js
index e69de29..e430c68 100644
--- a/src/core/data/apiRoutes.js
+++ b/src/core/data/apiRoutes.js
@@ -0,0 +1,135 @@
+const BASE_URL = process.env.NEXT_PUBLIC_BASE_URL;
+
+//login
+export const GET_USER_TOKEN = BASE_URL + "/dashboard/login";
+//end login
+
+//change password
+export const SET_USER_PASSWORD = BASE_URL + "/dashboard/profile/change_password";
+//end change password
+
+//user data
+export const GET_USER_ROUTE = BASE_URL + "/dashboard/profile/info";
+//user data
+
+//passenger office
+export const GET_PASSENGER_OFFICE =
+ BASE_URL + "/dashboard/passenger_office_chief/show";
+
+export const CONFIRM_PASSENGER_OFFICE =
+ BASE_URL + "/dashboard/passenger_office_chief/confirm";
+
+export const REJECT_PASSENGER_OFFICE =
+ BASE_URL + "/dashboard/passenger_office_chief/reject";
+//passenger office
+
+//passenger boss
+export const GET_PASSENGER_BOSS =
+ BASE_URL + "/dashboard/province_working_group/show";
+
+export const CONFIRM_PASSENGER_BOSS =
+ BASE_URL + "/dashboard/province_working_group/confirm";
+
+export const REJECT_PASSENGER_BOSS =
+ BASE_URL + "/dashboard/province_working_group/reject";
+//passenger boss
+
+//transportation assistance
+export const GET_TRANSPORTATION_ASSISTANCE =
+ BASE_URL + "/dashboard/transportation_assistant/show";
+
+export const CONFIRM_TRANSPORTATION_ASSISTANCE =
+ BASE_URL + "/dashboard/transportation_assistant/confirm";
+
+export const REJECT_TRANSPORTATION_ASSISTANCE =
+ BASE_URL + "/dashboard/transportation_assistant/reject";
+//transportation assistance
+
+//machinary office
+export const GET_MACHINARY_OFFICE =
+ BASE_URL + "/dashboard/machinery_expert/show";
+
+export const CONFIRM_MACHINARY_OFFICE =
+ BASE_URL + "/dashboard/machinery_expert/confirm";
+
+export const REJECT_MACHINARY_OFFICE =
+ BASE_URL + "/dashboard/machinery_expert/reject";
+//machinary office
+
+//commercial chief
+export const GET_COMMERCIAL_CHIEF =
+ BASE_URL + "/dashboard/commercial_chief/show";
+
+export const CONFIRM_COMMERCIAL_CHIEF =
+ BASE_URL + "/dashboard/commercial_chief/confirm";
+
+export const REJECT_COMMERCIAL_CHIEF =
+ BASE_URL + "/dashboard/commercial_chief/reject";
+//commercial chief
+
+//navgan province manager
+export const GET_NAVGAN_PROVINCE_MANAGER =
+ BASE_URL + "/dashboard/province_manager/show";
+
+export const CONFIRM_NAVGAN_PROVINCE_MANAGER =
+ BASE_URL + "/dashboard/province_manager/confirm";
+
+export const REJECT_NAVGAN_PROVINCE_MANAGER =
+ BASE_URL + "/dashboard/province_manager/reject";
+//navgan province manager
+
+// refahi province manager
+export const GET_REFAHI_PROVINCE_MANAGER =
+ BASE_URL + "/dashboard/refahi_province_manager/show";
+
+export const CONFIRM_REFAHI_PROVINCE_MANAGER =
+ BASE_URL + "/dashboard/refahi_province_manager/confirm";
+
+export const REJECT_REFAHI_PROVINCE_MANAGER =
+ BASE_URL + "/dashboard/refahi_province_manager/reject";
+//refahi province manager
+
+// development assistant
+export const GET_DEVELOPMENT_ASSISTANT =
+ BASE_URL + "/dashboard/development_assistant/show";
+
+export const CONFIRM_DEVELOPMENT_ASSISTANT =
+ BASE_URL + "/dashboard/development_assistant/confirm";
+
+export const REJECT_DEVELOPMENT_ASSISTANT =
+ BASE_URL + "/dashboard/development_assistant/reject";
+//development assistant
+
+// inspector expert
+export const GET_INSPECTOR_EXPERT =
+ BASE_URL + "/dashboard/inspector_expert/show";
+
+export const CONFIRM_INSPECTOR_EXPERT =
+ BASE_URL + "/dashboard/inspector_expert/confirm";
+
+export const REJECT_INSPECTOR_EXPERT =
+ BASE_URL + "/dashboard/inspector_expert/reject";
+
+export const REVISE_INSPECTOR_EXPERT =
+ BASE_URL + "/dashboard/inspector_expert/revise"
+//inspector expert
+
+// province head expert
+export const GET_PROVINCE_HEAD_EXPERT =
+ BASE_URL + "/dashboard/province_head_expert/show";
+
+export const CONFIRM_PROVINCE_HEAD_EXPERT =
+ BASE_URL + "/dashboard/province_head_expert/confirm";
+
+export const REJECT_PROVINCE_HEAD_EXPERT =
+ BASE_URL + "/dashboard/province_head_expert/reject";
+
+export const REVISE_PROVINCE_HEAD_EXPERT =
+ BASE_URL + "/dashboard/province_head_expert/revise";
+//province head expert
+
+//sidebar notification
+export const GET_SIDEBAR_NOTIFICATION =
+ BASE_URL + "/dashboard/notification"
+//sidebar notification
+
diff --git a/src/core/data/headerProfileItems.jsx b/src/core/data/headerProfileItems.jsx
index 63e661a..577fba3 100644
--- a/src/core/data/headerProfileItems.jsx
+++ b/src/core/data/headerProfileItems.jsx
@@ -2,18 +2,18 @@ import BorderColorIcon from "@mui/icons-material/BorderColor";
import PasswordIcon from "@mui/icons-material/Password";
const headerProfileItems = [
- {
- key: 0,
- name: "header.edit_profile",
- route: "/dashboard/edit-profile",
- icon: ,
- },
- {
- key: 1,
- name: "header.change_password",
- route: "/dashboard/change-password",
- icon: ,
- },
+ {
+ key: 0,
+ name: "header.edit_profile",
+ route: "/dashboard/edit-profile",
+ icon: ,
+ },
+ {
+ key: 1,
+ name: "header.change_password",
+ route: "/dashboard/change-password",
+ icon: ,
+ },
];
export default headerProfileItems;
diff --git a/src/core/data/sidebarMenu.jsx b/src/core/data/sidebarMenu.jsx
index c8e6ed8..c2dc246 100644
--- a/src/core/data/sidebarMenu.jsx
+++ b/src/core/data/sidebarMenu.jsx
@@ -1,17 +1,121 @@
import SpaceDashboardIcon from "@mui/icons-material/SpaceDashboard";
-import BookmarkAddedIcon from "@mui/icons-material/BookmarkAdded";
-import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
+import DirectionsCarFilledIcon from "@mui/icons-material/DirectionsCarFilled";
+import AirlineSeatReclineNormalIcon from "@mui/icons-material/AirlineSeatReclineNormal";
+import DirectionsRailwayIcon from "@mui/icons-material/DirectionsRailway";
+import AssignmentIndIcon from "@mui/icons-material/AssignmentInd";
+import DesktopWindowsIcon from "@mui/icons-material/DesktopWindows";
+import GavelIcon from '@mui/icons-material/Gavel';
+import BusinessCenterIcon from '@mui/icons-material/BusinessCenter';
+import GradingIcon from '@mui/icons-material/Grading';
+import SupervisedUserCircleIcon from '@mui/icons-material/SupervisedUserCircle';
+import Diversity3Icon from '@mui/icons-material/Diversity3';
const sidebarMenu = [
- [
- {
- key: "sidebar.dashboard",
- type: "page",
- route: "/dashboard",
- icon: ,
- selected: false,
- },
- ],
+ [
+ {
+ key: "sidebar.dashboard",
+ type: "page",
+ route: "/dashboard",
+ icon: ,
+ selected: false,
+ permission: "all",
+ },
+ {
+ key: "sidebar.passenger-office-chief",
+ secondary: "secondary.passenger-office",
+ name: "passenger_office_chief",
+ type: "page",
+ route: "/dashboard/passenger-office-chief",
+ icon: ,
+ selected: false,
+ permission: "manage_passenger_office_navgan",
+ },
+ {
+ key: "sidebar.machinery-expert",
+ name: "machinery_expert",
+ type: "page",
+ route: "/dashboard/machinery-expert",
+ icon: ,
+ selected: false,
+ permission: "manage_machinery_navgan",
+ },
+ {
+ key: "sidebar.passenger-boss",
+ secondary: "secondary.passenger-boss",
+ name: "province_working_group",
+ type: "page",
+ route: "/dashboard/passenger-boss",
+ icon: ,
+ selected: false,
+ permission: "manage_province_working_group_navgan",
+ },
+
+ {
+ key: "sidebar.transportation-assistant",
+ name: "transportation_assistant",
+ type: "page",
+ route: "/dashboard/transportation-assistant",
+ icon: ,
+ selected: false,
+ permission: "manage_transportation_navgan",
+ },
+ {
+ key: "sidebar.navgan-province-manager",
+ secondary: "secondary.navgan-province-manager",
+ name: "province_manager_navgan",
+ type: "page",
+ route: "/dashboard/navgan-province-manager",
+ icon: ,
+ selected: false,
+ permission: "manage_province_affairs_navgan",
+ },
+ {
+ key: "sidebar.province-head-expert",
+ name: "province_head_expert",
+ type: "page",
+ route: "/dashboard/province-head-expert",
+ icon: ,
+ selected: false,
+ permission: "manage_province_headquarter_refahi",
+ },
+ {
+ key: "sidebar.inspector-expert",
+ name: "inspector_expert",
+ type: "page",
+ route: "/dashboard/inspector-expert",
+ icon: ,
+ selected: false,
+ permission: "manage_inspector_refahi",
+ },
+ {
+ key: "sidebar.commercial-chief",
+ name: "commercial_chief",
+ type: "page",
+ route: "/dashboard/commercial-chief",
+ icon: ,
+ selected: false,
+ permission: "manage_commercial_refahi",
+ },
+ {
+ key: "sidebar.development-assistant",
+ name: "development_assistant",
+ type: "page",
+ route: "/dashboard/development-assistant",
+ icon: ,
+ selected: false,
+ permission: "manage_development_refahi",
+ },
+ {
+ key: "sidebar.refahi-province-manager",
+ secondary: "secondary.refahi-province-manager",
+ name: "province_manager_refahi",
+ type: "page",
+ route: "/dashboard/refahi-province-manager",
+ icon: ,
+ selected: false,
+ permission: "manage_province_affairs_refahi",
+ },
+ ],
];
export default sidebarMenu;
diff --git a/src/core/utils/createEmotionCache.jsx b/src/core/utils/createEmotionCache.jsx
index 06add02..413fafe 100644
--- a/src/core/utils/createEmotionCache.jsx
+++ b/src/core/utils/createEmotionCache.jsx
@@ -1,38 +1,38 @@
import createCache from "@emotion/cache";
-import { prefixer } from "stylis";
+import {prefixer} from "stylis";
import stylisRTLPlugin from "stylis-plugin-rtl";
const isBrowser = typeof document !== "undefined";
export const createEmotionCacheLtr = () => {
- let insertionPoint;
+ let insertionPoint;
- if (isBrowser) {
- const emotionInsertionPoint = document.querySelector(
- 'meta[name="emotion-insertion-point"]'
- );
- insertionPoint = emotionInsertionPoint ?? undefined;
- }
+ if (isBrowser) {
+ const emotionInsertionPoint = document.querySelector(
+ 'meta[name="emotion-insertion-point"]'
+ );
+ insertionPoint = emotionInsertionPoint ?? undefined;
+ }
- return createCache({
- key: "mui-style",
- insertionPoint,
- });
+ return createCache({
+ key: "mui-style",
+ insertionPoint,
+ });
};
export const createEmotionCacheRtl = () => {
- let insertionPoint;
+ let insertionPoint;
- if (isBrowser) {
- const emotionInsertionPoint = document.querySelector(
- 'meta[name="emotion-insertion-point"]'
- );
- insertionPoint = emotionInsertionPoint ?? undefined;
- }
+ if (isBrowser) {
+ const emotionInsertionPoint = document.querySelector(
+ 'meta[name="emotion-insertion-point"]'
+ );
+ insertionPoint = emotionInsertionPoint ?? undefined;
+ }
- return createCache({
- key: "muirtl",
- stylisPlugins: [prefixer, stylisRTLPlugin],
- insertionPoint,
- });
+ return createCache({
+ key: "muirtl",
+ stylisPlugins: [prefixer, stylisRTLPlugin],
+ insertionPoint,
+ });
};
diff --git a/src/core/utils/errorHandler.js b/src/core/utils/errorHandler.js
new file mode 100644
index 0000000..9bd18f1
--- /dev/null
+++ b/src/core/utils/errorHandler.js
@@ -0,0 +1,62 @@
+import ErrorNotification from "@/core/components/notifications/ErrorNotification";
+import WarningNotification from "@/core/components/notifications/WarningNotification";
+import {toast} from "react-toastify";
+
+export const errorSetting = (t, notification) => {
+ if (notification) toast.dismiss();
+}
+
+export const errorRequest = (t, notification) => {
+ if (notification) toast.dismiss();
+}
+
+export const errorResponse = (response, clearToken, t, notification) => {
+ if (notification) toast.dismiss();
+ if (isServerError(response.status)) {
+ errorServer(response, t, notification)
+ } else if (isClientError(response.status)) {
+ errorClient(response, clearToken, t, notification)
+ }
+}
+
+const errorServer = (response, t, notification) => {
+ if (notification) WarningNotification(t, response.status);
+}
+const errorClient = (response, clearToken, t, notification) => {
+ switch (response.status) {
+ case 401:
+ clearToken()
+ if (notification) ErrorNotification(t, response.status)
+ break;
+ case 422:
+ if ('type' in response.data) {
+ errorLogic(response, t, notification)
+ break;
+ }
+ errorValidation(response, t, notification)
+ break;
+ case 429:
+ if (notification) ErrorNotification(t, response.status)
+ break
+ default:
+ if (notification) ErrorNotification(t, response.status)
+ break
+ }
+}
+
+const isServerError = status => status >= 500 && status <= 599;
+const isClientError = status => status >= 400 && status <= 499;
+
+const errorLogic = (response, t, notification) => {
+ if (notification) ErrorNotification(t, response.status)
+}
+const errorValidation = (response, t, notification) => {
+ if (notification) {
+ const errorsMap = Object.keys(response.data.errors)
+ const errorsArray = response.data.errors
+
+ errorsMap.map((item, index) => {
+ ErrorNotification(t, response.status, errorsArray[item][0]);
+ })
+ }
+}
\ No newline at end of file
diff --git a/src/core/utils/succesHandler.js b/src/core/utils/succesHandler.js
new file mode 100644
index 0000000..a61ac85
--- /dev/null
+++ b/src/core/utils/succesHandler.js
@@ -0,0 +1,9 @@
+import SuccessNotification from "@/core/components/notifications/SuccessNotification";
+import {toast} from "react-toastify";
+
+export const successRequest = (response, t, options) => {
+ if (options.notification && options.success.notification.show) {
+ toast.dismiss();
+ SuccessNotification(t, response.status)
+ }
+}
\ No newline at end of file
diff --git a/src/core/utils/theme-rtl.jsx b/src/core/utils/theme-rtl.jsx
index c36abeb..33a9ae7 100644
--- a/src/core/utils/theme-rtl.jsx
+++ b/src/core/utils/theme-rtl.jsx
@@ -1,12 +1,14 @@
-import { createTheme } from "@mui/material/styles";
+import {createTheme} from "@mui/material/styles";
import theme from "./theme";
+import {faIR} from "@mui/x-date-pickers/locales";
const themeRtl = createTheme({
- direction: "rtl",
- typography: {
- fontFamily: `IRANSans, sans-serif`,
- },
- ...theme,
+ direction: "rtl",
+ typography: {
+ fontFamily: `IRANSansFaNum, sans-serif`,
+ },
+ faIR,
+ ...theme,
});
export default themeRtl;
diff --git a/src/core/utils/theme.jsx b/src/core/utils/theme.jsx
index 0a36eee..672e8a8 100644
--- a/src/core/utils/theme.jsx
+++ b/src/core/utils/theme.jsx
@@ -1,18 +1,29 @@
+import {colord} from "colord";
+
const theme = {
- palette: {
- primary: {
- main: "#084070",
- contrastText: "#fff",
- light: "#2c6291",
- dark: "#11293e",
+ palette: {
+ primary: {
+ main: process.env.NEXT_PUBLIC_PRIMARY_MAIN,
+ contrastText: "#FFFFFF",
+ light: colord(process.env.NEXT_PUBLIC_PRIMARY_MAIN).lighten(0.1).toHex(),
+ dark: colord(process.env.NEXT_PUBLIC_PRIMARY_MAIN).darken(0.1).toHex(),
+ },
+ secondary: {
+ main: process.env.NEXT_PUBLIC_SECONDARY_MAIN,
+ contrastText: "#FFFFFF",
+ light: colord(process.env.NEXT_PUBLIC_SECONDARY_MAIN).lighten(0.1).toHex(),
+ dark: colord(process.env.NEXT_PUBLIC_SECONDARY_MAIN).darken(0.1).toHex(),
+ },
},
- secondary: {
- main: "#FF4E00",
- contrastText: "#fff",
- light: "#ed743e",
- dark: "#ad3a07",
+ components: {
+ MuiBackdrop: {
+ styleOverrides: {
+ root: {
+ backgroundColor: colord(process.env.NEXT_PUBLIC_PRIMARY_MAIN).darken(0.2).alpha(0.7).toHex(),
+ },
+ },
+ },
},
- },
};
export default theme;
diff --git a/src/layouts/AppLayout.jsx b/src/layouts/AppLayout.jsx
index 2f7988e..4fc5e1d 100644
--- a/src/layouts/AppLayout.jsx
+++ b/src/layouts/AppLayout.jsx
@@ -1,85 +1,56 @@
import theme from "@/core/utils/theme";
+import useLanguage from "@/lib/app/hooks/useLanguage";
import useLoading from "@/lib/app/hooks/useLoading";
import useUser from "@/lib/app/hooks/useUser";
-import Head from "next/head";
import NextNProgress from "nextjs-progressbar";
-import { useEffect } from "react";
+import {useEffect} from "react";
+import {ToastContainer} from "react-toastify";
+import useDirection from "@/lib/app/hooks/useDirection";
+import "react-toastify/dist/ReactToastify.css";
+import NetworkComponent from "@/core/components/NetworkComponent";
+import GlobalHead from "@/core/components/GlobalHead";
-function AppLayout({ children, isBot }) {
- const { setLoadingPage } = useLoading();
- const { token, isAuth } = useUser();
- useEffect(() => {
- if (token) {
- if (isAuth) {
- setLoadingPage(false);
- return;
+function AppLayout({children, isBot}) {
+ const {languageIsReady} = useLanguage();
+ const {setLoadingPage} = useLoading();
+ const {userChangedLanguage, token, isAuth} = useUser();
+ const {directionApp} = useDirection();
+
+ useEffect(() => {
+ if (languageIsReady) {
+ if (token) {
+ if (isAuth) {
+ if (userChangedLanguage) {
+ setLoadingPage(true);
+ return;
+ }
+ setLoadingPage(false);
+ return;
+ }
+ setLoadingPage(true);
+ return;
+ }
+ setLoadingPage(false);
+ return;
}
setLoadingPage(true);
- return;
- }
- setLoadingPage(false);
- return;
- }, [token, isAuth]);
+ }, [languageIsReady, token, isAuth, userChangedLanguage]);
- return (
- <>
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {children}
- >
- );
+
+
+ {children}
+ >);
}
export default AppLayout;
diff --git a/src/layouts/CenterLayout.jsx b/src/layouts/CenterLayout.jsx
index 4c8767f..1e1b8bf 100644
--- a/src/layouts/CenterLayout.jsx
+++ b/src/layouts/CenterLayout.jsx
@@ -1,18 +1,18 @@
-import { Fade, Stack } from "@mui/material";
+import {Fade, Stack} from "@mui/material";
const CenterLayout = (props) => {
- return (
-
-
- {props.children}
-
-
- );
+ return (
+
+
+ {props.children}
+
+
+ );
};
export default CenterLayout;
diff --git a/src/layouts/FullPageLayout.jsx b/src/layouts/FullPageLayout.jsx
index cbf2102..d6ed61e 100644
--- a/src/layouts/FullPageLayout.jsx
+++ b/src/layouts/FullPageLayout.jsx
@@ -1,21 +1,21 @@
-import { Stack } from "@mui/material";
+import {Stack} from "@mui/material";
const FullPageLayout = (props) => {
- return (
-
- {props.children}
-
- );
+ return (
+
+ {props.children}
+
+ );
};
export default FullPageLayout;
diff --git a/src/layouts/MuiLayout.jsx b/src/layouts/MuiLayout.jsx
index ba891d0..6dcd3ed 100644
--- a/src/layouts/MuiLayout.jsx
+++ b/src/layouts/MuiLayout.jsx
@@ -1,76 +1,73 @@
-import NoSsrHandler from "@/core/components/isBotHandler";
-import {
- createEmotionCacheRtl
-} from "@/core/utils/createEmotionCache";
+import NoSsrHandler from "@/core/components/NoSsrHandler";
+import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache";
import themeRtl from "@/core/utils/theme-rtl";
-import { CacheProvider } from "@emotion/react";
-import { GlobalStyles } from "@mui/material";
+import {CacheProvider} from "@emotion/react";
+import {GlobalStyles} from "@mui/material";
import CssBaseline from "@mui/material/CssBaseline";
-import { ThemeProvider } from "@mui/material/styles";
+import {ThemeProvider} from "@mui/material/styles";
import Head from "next/head";
const clientSideEmotionCacheRtl = createEmotionCacheRtl();
-const MuiLayout = ({ children, isBot }) => {
+const MuiLayout = ({children, isBot}) => {
+ const emotionCache = clientSideEmotionCacheRtl;
+ const theme = themeRtl;
- const emotionCache = clientSideEmotionCacheRtl;
+ return (
+
+
+
+
+
+
+
-
-
-
-
-
-
- body: {
- width: "100vw",
- height: "100vh",
- },
- "#__next": {
- width: "100%",
- height: "100%",
- },
- }}
- />
-
-
- {children}
-
-
-
- );
+
+ {children}
+
+
+
+ );
};
export default MuiLayout;
diff --git a/src/layouts/ScrollableLayout.jsx b/src/layouts/ScrollableLayout.jsx
index 5ab58ca..583edd7 100644
--- a/src/layouts/ScrollableLayout.jsx
+++ b/src/layouts/ScrollableLayout.jsx
@@ -1,25 +1,25 @@
-import { Box, Fade } from "@mui/material";
+import {Box, Fade} from "@mui/material";
const ScrollableLayout = (props) => {
- const overflowY = props?.y || "hidden";
- const overflowX = props?.x || "hidden";
+ const overflowY = props?.y || "hidden";
+ const overflowX = props?.x || "hidden";
- return (
-
-
- {props.children}
-
-
- );
+ return (
+
+
+ {props.children}
+
+
+ );
};
export default ScrollableLayout;
diff --git a/src/layouts/dashboardLayouts/breadcrumbs/BreadcrumbItem.jsx b/src/layouts/dashboardLayouts/breadcrumbs/BreadcrumbItem.jsx
index ccff4c9..c233be3 100644
--- a/src/layouts/dashboardLayouts/breadcrumbs/BreadcrumbItem.jsx
+++ b/src/layouts/dashboardLayouts/breadcrumbs/BreadcrumbItem.jsx
@@ -1,19 +1,19 @@
import LinkRouting from "@/core/components/LinkRouting";
-import { Typography } from "@mui/material";
-import { useTranslations } from "next-intl";
+import {Typography} from "@mui/material";
+import {useTranslations} from "next-intl";
export default function BreadcrumbItem(props) {
- const t = useTranslations();
- const isLast = props.index === props.RouterArray.length - 1;
- const url = `/${props.RouterArray.slice(0, props.index + 1).join("/")}`;
+ const t = useTranslations();
+ const isLast = props.index === props.RouterArray.length - 1;
+ const url = `/${props.RouterArray.slice(0, props.index + 1).join("/")}`;
- return isLast ? (
-
- {t("sidebar." + props.label)}
-
- ) : (
-
- {t("sidebar." + props.label)}
-
- );
+ return isLast ? (
+
+ {t("sidebar." + props.label)}
+
+ ) : (
+
+ {t("sidebar." + props.label)}
+
+ );
}
diff --git a/src/layouts/dashboardLayouts/breadcrumbs/index.jsx b/src/layouts/dashboardLayouts/breadcrumbs/index.jsx
index 3123a12..9ab234e 100644
--- a/src/layouts/dashboardLayouts/breadcrumbs/index.jsx
+++ b/src/layouts/dashboardLayouts/breadcrumbs/index.jsx
@@ -1,49 +1,49 @@
-import { useRouter } from "next/router";
-import { Box, Breadcrumbs } from "@mui/material";
-import { useTheme } from "@mui/material/styles";
-import { NavigateBefore, NavigateNext } from "@mui/icons-material";
+import {useRouter} from "next/router";
+import {Box, Breadcrumbs} from "@mui/material";
+import {useTheme} from "@mui/material/styles";
+import {NavigateBefore, NavigateNext} from "@mui/icons-material";
import BreadcrumbItem from "./BreadcrumbItem";
const BreadCrumbs = (props) => {
- const { isVisible } = props;
- const theme = useTheme();
- const router = useRouter();
+ const {isVisible} = props;
+ const theme = useTheme();
+ const router = useRouter();
- if (!isVisible) {
- return null;
- }
+ if (!isVisible) {
+ return null;
+ }
- const { pathname } = router;
- const RouterArray = pathname.split("/").filter((segment) => segment !== "");
+ const {pathname} = router;
+ const RouterArray = pathname.split("/").filter((segment) => segment !== "");
- if (RouterArray.length === 1) {
- return null;
- }
+ if (RouterArray.length === 1) {
+ return null;
+ }
- return (
-
-
- ) : (
-
- )
- }
- aria-label="breadcrumb"
- >
- {RouterArray.map((segment, index) => (
-
- ))}
-
-
- );
+ return (
+
+
+ ) : (
+
+ )
+ }
+ aria-label="breadcrumb"
+ >
+ {RouterArray.map((segment, index) => (
+
+ ))}
+
+
+ );
};
export default BreadCrumbs;
diff --git a/src/layouts/dashboardLayouts/header/ProfileData.jsx b/src/layouts/dashboardLayouts/header/ProfileData.jsx
index c3fdf58..548378b 100644
--- a/src/layouts/dashboardLayouts/header/ProfileData.jsx
+++ b/src/layouts/dashboardLayouts/header/ProfileData.jsx
@@ -1,18 +1,18 @@
-import { Avatar, Stack, Typography } from "@mui/material";
+import {Avatar, Stack, Typography} from "@mui/material";
import useUser from "@/lib/app/hooks/useUser";
export default function ProfileData() {
- const { user } = useUser();
- return (
-
-
-
- {user.user_username}
-
-
- );
+ const {user} = useUser();
+ return (
+
+
+
+ {user.username}
+
+
+ );
}
diff --git a/src/layouts/dashboardLayouts/header/ProfileMenu.jsx b/src/layouts/dashboardLayouts/header/ProfileMenu.jsx
index 50f34db..415d501 100644
--- a/src/layouts/dashboardLayouts/header/ProfileMenu.jsx
+++ b/src/layouts/dashboardLayouts/header/ProfileMenu.jsx
@@ -1,61 +1,62 @@
-import { Avatar, Menu, IconButton, Tooltip } from "@mui/material";
-import { useState } from "react";
+import {Avatar, IconButton, Menu, Tooltip} from "@mui/material";
+import {useState} from "react";
import ProfileData from "./ProfileData";
import ProfileOptions from "./ProfileOptions";
-import { useTranslations } from "next-intl";
+import {useTranslations} from "next-intl";
import useUser from "@/lib/app/hooks/useUser";
function ProfileMenu() {
- const t = useTranslations();
- const [anchorElUser, setAnchorElUser] = useState(null);
- const { user } = useUser();
+ const t = useTranslations();
+ const [anchorElUser, setAnchorElUser] = useState(null);
+ const {user} = useUser();
- const handleOpenUserMenu = (event) => {
- setAnchorElUser(event.currentTarget);
- };
- const handleCloseUserMenu = () => {
- setAnchorElUser(null);
- };
+ const handleOpenUserMenu = (event) => {
+ setAnchorElUser(event.currentTarget);
+ };
+ const handleCloseUserMenu = () => {
+ setAnchorElUser(null);
+ };
- return (
- <>
-
-
-
-
-
-
- >
- );
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
}
+
export default ProfileMenu;
diff --git a/src/layouts/dashboardLayouts/header/ProfileOptionLogOut.jsx b/src/layouts/dashboardLayouts/header/ProfileOptionLogOut.jsx
index f56db6c..2a6cf85 100644
--- a/src/layouts/dashboardLayouts/header/ProfileOptionLogOut.jsx
+++ b/src/layouts/dashboardLayouts/header/ProfileOptionLogOut.jsx
@@ -1,49 +1,49 @@
-import { Box, Button, MenuItem, Typography } from "@mui/material";
+import {Box, Button, MenuItem, Typography} from "@mui/material";
import MeetingRoomIcon from "@mui/icons-material/MeetingRoom";
import useUser from "@/lib/app/hooks/useUser";
-import { useTranslations } from "next-intl";
+import {useTranslations} from "next-intl";
-export default function ProfileOptionLogOut({ handleCloseUserMenu }) {
- const t = useTranslations();
- const { clearToken } = useUser();
- const handleClickLogOut = () => {
- handleCloseUserMenu();
- clearToken();
- };
- return (
- <>
-
- >
- );
+export default function ProfileOptionLogOut({handleCloseUserMenu}) {
+ const t = useTranslations();
+ const {clearToken} = useUser();
+ const handleClickLogOut = () => {
+ handleCloseUserMenu();
+ clearToken();
+ };
+ return (
+ <>
+
+ >
+ );
}
diff --git a/src/layouts/dashboardLayouts/header/ProfileOptions.jsx b/src/layouts/dashboardLayouts/header/ProfileOptions.jsx
index bf63212..6e7bdba 100644
--- a/src/layouts/dashboardLayouts/header/ProfileOptions.jsx
+++ b/src/layouts/dashboardLayouts/header/ProfileOptions.jsx
@@ -1,49 +1,49 @@
-import { Box, MenuItem, Typography } from "@mui/material";
-import { NextLinkComposed } from "@/core/components/LinkRouting";
-import { useTranslations } from "next-intl";
+import {Box, MenuItem, Typography} from "@mui/material";
+import {NextLinkComposed} from "@/core/components/LinkRouting";
+import {useTranslations} from "next-intl";
import headerProfileItems from "@/core/data/headerProfileItems";
import ProfileOptionLogOut from "./ProfileOptionLogOut";
-export default function ProfileOptions({ handleCloseUserMenu }) {
- const t = useTranslations();
+export default function ProfileOptions({handleCloseUserMenu}) {
+ const t = useTranslations();
- return (
- <>
- {headerProfileItems.map((profile_item) => (
-
- ))}
-
- >
- );
+ return (
+ <>
+ {headerProfileItems.map((profile_item) => (
+
+ ))}
+
+ >
+ );
}
diff --git a/src/layouts/dashboardLayouts/header/index.jsx b/src/layouts/dashboardLayouts/header/index.jsx
index cd1e4a0..8760960 100644
--- a/src/layouts/dashboardLayouts/header/index.jsx
+++ b/src/layouts/dashboardLayouts/header/index.jsx
@@ -1,80 +1,72 @@
import MenuIcon from "@mui/icons-material/Menu";
-import {
- AppBar,
- Box,
- Container,
- CssBaseline,
- IconButton,
- Stack,
- Toolbar,
- useTheme
-} from "@mui/material";
+import {AppBar, Box, Container, CssBaseline, IconButton, Stack, Toolbar, useTheme} from "@mui/material";
import ProfileMenu from "./ProfileMenu";
-function Header({ drawerWidth, handleDrawerToggle }) {
- const theme = useTheme();
+function Header({drawerWidth, handleDrawerToggle}) {
+ const theme = useTheme();
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
- >
- );
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
}
+
export default Header;
diff --git a/src/layouts/dashboardLayouts/index.jsx b/src/layouts/dashboardLayouts/index.jsx
index f1478bf..fae51d2 100644
--- a/src/layouts/dashboardLayouts/index.jsx
+++ b/src/layouts/dashboardLayouts/index.jsx
@@ -1,50 +1,45 @@
-import { useState } from "react";
+import {useState} from "react";
import FullPageLayout from "../FullPageLayout";
import Header from "./header";
import Sidebar from "./sidebar";
-import { Toolbar } from "@mui/material";
+import {Toolbar} from "@mui/material";
import BreadCrumbs from "./breadcrumbs";
-import { ToastContainer } from "react-toastify";
-import "react-toastify/dist/ReactToastify.css";
-import useDirection from "@/lib/app/hooks/useDirection";
const drawerWidth = 240;
const DashboardLayouts = (props) => {
- const { directionApp } = useDirection();
- const { window } = props;
- const [mobileOpen, setMobileOpen] = useState(false);
- const container =
- window !== undefined ? () => window().document.body : undefined;
+ const {window} = props;
+ const [mobileOpen, setMobileOpen] = useState(false);
+ const container =
+ window !== undefined ? () => window().document.body : undefined;
- const handleDrawerToggle = () => {
- setMobileOpen(!mobileOpen);
- };
- return (
-
-
-
-
-
-
-
- {props.children}
+ const handleDrawerToggle = () => {
+ setMobileOpen(!mobileOpen);
+ };
+ return (
+
+
+
+
+
+
+
+ {props.children}
+
+
-
- {directionApp === "rtl" ? : }
-
- );
+ );
};
export default DashboardLayouts;
diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarDrawer.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarDrawer.jsx
index 6eb5e60..f155dce 100644
--- a/src/layouts/dashboardLayouts/sidebar/SidebarDrawer.jsx
+++ b/src/layouts/dashboardLayouts/sidebar/SidebarDrawer.jsx
@@ -1,29 +1,27 @@
-import { Divider, Stack, Toolbar, Typography } from "@mui/material";
-import { useTranslations } from "next-intl";
+import {Divider, Stack, Toolbar, Typography} from "@mui/material";
+import {useTranslations} from "next-intl";
import SidebarList from "./SidebarList";
-import StyledImage from "@/core/components/StyledImage";
+import useUser from "@/lib/app/hooks/useUser";
-const SidebarDrawer = ({ handleDrawerToggle }) => {
- const t = useTranslations();
- return (
- <>
-
-
-
- {t("app_short_name")}
-
-
- {
- t("expert") /* make if on thease t("user_welfare_services")
- t("user_navy") */
- }
-
-
-
-
-
- >
- );
+const SidebarDrawer = ({handleDrawerToggle}) => {
+ const {user} = useUser()
+ const t = useTranslations();
+ return (
+ <>
+
+
+
+ {t("app_short_name")}
+
+
+ {user.name} | {user.position}
+
+
+
+
+
+ >
+ );
};
export default SidebarDrawer;
diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarList.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarList.jsx
index 79dd93e..a030b52 100644
--- a/src/layouts/dashboardLayouts/sidebar/SidebarList.jsx
+++ b/src/layouts/dashboardLayouts/sidebar/SidebarList.jsx
@@ -1,56 +1,57 @@
-import { Divider, List } from "@mui/material";
-import { Fragment, useEffect, useReducer } from "react";
+import {Divider, List} from "@mui/material";
+import {useEffect, useReducer} from "react";
import SidebarListItem from "./SidebarListItem";
import sidebarMenu from "@/core/data/sidebarMenu";
-import { useRouter } from "next/router";
+import {useRouter} from "next/router";
+import useUser from "@/lib/app/hooks/useUser";
function reducer(state, action) {
- switch (action.type) {
- case "COLLAPSE_MENU":
- return state.map((itemsArr) =>
- itemsArr.map((item) =>
- action.key == item.key
- ? { ...item, showSubItem: !item.showSubItem }
- : item
- )
- );
- case "SELECTED":
- return state.map((itemsArr) =>
- itemsArr.map((item) =>
- action.route == item.route
- ? { ...item, selected: true }
- : { ...item, selected: false }
- )
- );
- default:
- throw new Error();
- }
+ switch (action.type) {
+ case "COLLAPSE_MENU":
+ return state.map((itemsArr) =>
+ itemsArr.map((item) =>
+ action.key == item.key
+ ? {...item, showSubItem: !item.showSubItem}
+ : item
+ )
+ );
+ case "SELECTED":
+ return state.map((itemsArr) =>
+ itemsArr.map((item) =>
+ action.route == item.route
+ ? {...item, selected: true}
+ : {...item, selected: false}
+ )
+ );
+ default:
+ throw new Error();
+ }
}
-export default function SidebarList({ handleDrawerToggle }) {
- const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
+export default function SidebarList({handleDrawerToggle}) {
+ const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
+ const {user} = useUser();
+ const router = useRouter();
- // activate current page in menu
- const router = useRouter();
- useEffect(() => {
- dispatch({ type: "SELECTED", route: router.pathname });
- }, [router.pathname]);
+ useEffect(() => {
+ dispatch({type: "SELECTED", route: router.pathname});
+ }, [router.pathname]);
- return (
-
- {itemMenu.map((itemArr, index) => (
-
- {itemArr.map((item) => (
-
- ))}
-
-
- ))}
-
- );
+ const filteredItemMenu = itemMenu[0].filter(
+ (item) => user.permissions.includes(item.permission) || item.permission === "all"
+ );
+
+ return (
+
+ {filteredItemMenu.map((item, index) => (
+
+ ))}
+ {filteredItemMenu.length > 0 && }
+
+ );
}
diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx
index ba270a5..ebeb14c 100644
--- a/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx
+++ b/src/layouts/dashboardLayouts/sidebar/SidebarListItem.jsx
@@ -1,64 +1,84 @@
-import { NextLinkComposed } from "@/core/components/LinkRouting";
+import {NextLinkComposed} from "@/core/components/LinkRouting";
import ExpandLess from "@mui/icons-material/ExpandLess";
import ExpandMore from "@mui/icons-material/ExpandMore";
-import {
- ListItem,
- ListItemButton,
- ListItemIcon,
- ListItemText,
-} from "@mui/material";
-import { useTranslations } from "next-intl";
-import { Fragment } from "react";
+import {Badge, IconButton, ListItem, ListItemButton, ListItemIcon, ListItemText, Typography,} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {Fragment} from "react";
import SidebarListSubItem from "./SidebarListSubItem";
+import useNotification from "@/lib/app/hooks/useNotification";
-const SidebarListItem = ({ item, dispatch, handleDrawerToggle }) => {
- const t = useTranslations();
+const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
+ const t = useTranslations();
+ const {notification_count} = useNotification()
- return (
-
-
- {
- if (item.type == "menu") {
- dispatch({ type: "COLLAPSE_MENU", key: item.key });
- }
- handleDrawerToggle();
- }}
- sx={{
- minHeight: 48,
- }}
- >
-
- {item.icon}
-
-
+ return (
+
+
+
+
+ }>
+ {
+ if (item.type == "menu") {
+ dispatch({type: "COLLAPSE_MENU", key: item.key});
+ }
+ handleDrawerToggle();
+ }}
+ sx={{
+ minHeight: 48,
+ }}
- {item.type == "menu" &&
- (item.showSubItem ? : )}
-
-
- {item.subItem && (
-
- )}
-
- );
+ >
+
+ {item.icon}
+
+
+ {t(item.secondary)}
+
+ ) : null
+ }
+ />
+
+
+ {item.type == "menu" &&
+ (item.showSubItem ? : )}
+
+
+ {item.subItem && (
+
+ )}
+
+ );
};
export default SidebarListItem;
diff --git a/src/layouts/dashboardLayouts/sidebar/SidebarListSubItem.jsx b/src/layouts/dashboardLayouts/sidebar/SidebarListSubItem.jsx
index f960efb..3407081 100644
--- a/src/layouts/dashboardLayouts/sidebar/SidebarListSubItem.jsx
+++ b/src/layouts/dashboardLayouts/sidebar/SidebarListSubItem.jsx
@@ -1,54 +1,48 @@
-import { NextLinkComposed } from "@/core/components/LinkRouting";
+import {NextLinkComposed} from "@/core/components/LinkRouting";
import InboxIcon from "@mui/icons-material/MoveToInbox";
-import {
- Collapse,
- List,
- ListItemButton,
- ListItemIcon,
- ListItemText,
-} from "@mui/material";
-import { useTranslations } from "next-intl";
-import { Fragment } from "react";
+import {Collapse, List, ListItemButton, ListItemIcon, ListItemText,} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {Fragment} from "react";
-const SidebarListSubItem = ({ item, handleDrawerToggle }) => {
- const t = useTranslations();
+const SidebarListSubItem = ({item, handleDrawerToggle}) => {
+ const t = useTranslations();
- return (
-
-
- {item.subItem.map((subitem, index) => (
-
- {
- if (item.type == "menu") {
- dispatch({ type: "COLLAPSE_MENU", key: item.key });
- }
- handleDrawerToggle();
- }}
- >
-
-
-
-
-
-
- ))}
-
-
- );
+ return (
+
+
+ {item.subItem.map((subitem, index) => (
+
+ {
+ if (item.type == "menu") {
+ dispatch({type: "COLLAPSE_MENU", key: item.key});
+ }
+ handleDrawerToggle();
+ }}
+ >
+
+
+
+
+
+
+ ))}
+
+
+ );
};
export default SidebarListSubItem;
diff --git a/src/layouts/dashboardLayouts/sidebar/index.jsx b/src/layouts/dashboardLayouts/sidebar/index.jsx
index dcf7fe2..2498dfd 100644
--- a/src/layouts/dashboardLayouts/sidebar/index.jsx
+++ b/src/layouts/dashboardLayouts/sidebar/index.jsx
@@ -1,46 +1,46 @@
-import { Box, Drawer } from "@mui/material";
+import {Box, Drawer} from "@mui/material";
import SidebarDrawer from "./SidebarDrawer";
const Sidebar = (props) => {
- return (
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+ );
};
export default Sidebar;
diff --git a/src/lib/app/contexts/language.jsx b/src/lib/app/contexts/language.jsx
index c8ac313..e3f41f4 100644
--- a/src/lib/app/contexts/language.jsx
+++ b/src/lib/app/contexts/language.jsx
@@ -1,99 +1,99 @@
-import { FA_DATATABLE_LOCALIZATION } from "&/locales/fa/datatable";
-import { useRouter } from "next/router";
-import { createContext, useEffect, useState } from "react";
+import {FA_DATATABLE_LOCALIZATION} from "&/locales/fa/datatable";
+import {useRouter} from "next/router";
+import {createContext, useEffect, useState} from "react";
import useUser from "../hooks/useUser";
export const LanguageContext = createContext();
-export const LanguageProvider = ({ children }) => {
- const router = useRouter();
- const languageList = [
- {
- key: "fa",
- dir: "rtl",
- name: "فارسی",
- fontFamily: `IRANSans, sans-serif`,
- tableLocalization: FA_DATATABLE_LOCALIZATION,
- }
- ];
- const { user, userChangedLanguage, changeLanguageState } = useUser();
- const [languageIsReady, setLanguageIsReady] = useState(false);
- const [languageApp, setLanguageApp] = useState();
- const [directionApp, setDirectionApp] = useState(
- process.env.NEXT_PUBLIC_DEFAULT_DIRECTION
- );
-
- useEffect(() => {
- const lang = localStorage.getItem("_language");
-
- if (!lang && !languageApp) {
- setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
- } else if (lang) {
- setLanguageApp(lang);
- }
- }, []);
-
- useEffect(() => {
- if (!languageApp) return;
-
- const lang = localStorage.getItem("_language");
-
- if (!lang) {
- localStorage.setItem("_language", languageApp);
- } else {
- if (languageApp != lang) {
- localStorage.setItem("_language", languageApp);
- }
- }
- }, [languageApp]);
-
- useEffect(() => {
- if (!router.isReady) return;
- if (user.user_language) {
- if (user.user_language != languageApp) {
- setLanguageApp(user.user_language);
- return;
- }
- }
-
- if (languageApp != router.locale) {
- router.replace(
- { pathname: router.pathname, query: router.query },
- router.asPath,
+export const LanguageProvider = ({children}) => {
+ const router = useRouter();
+ const languageList = [
{
- locale: languageApp,
+ key: "fa",
+ dir: "rtl",
+ name: "فارسی",
+ fontFamily: `IRANSans, sans-serif`,
+ tableLocalization: FA_DATATABLE_LOCALIZATION,
}
- );
- return;
- }
- for (const lang of languageList) {
- if (languageApp != lang.key) continue;
- setDirectionApp(lang.dir);
- document.dir = lang.dir;
- }
+ ];
+ const {user, userChangedLanguage, changeLanguageState} = useUser();
+ const [languageIsReady, setLanguageIsReady] = useState(false);
+ const [languageApp, setLanguageApp] = useState();
+ const [directionApp, setDirectionApp] = useState(
+ process.env.NEXT_PUBLIC_DEFAULT_DIRECTION
+ );
- const timer = setTimeout(() => {
- changeLanguageState(false);
- setLanguageIsReady(true);
- }, 1000);
+ useEffect(() => {
+ const lang = localStorage.getItem("_language");
- return () => {
- clearTimeout(timer);
- };
- }, [router.locale, router.isReady, userChangedLanguage, languageApp]);
+ if (!lang && !languageApp) {
+ setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
+ } else if (lang) {
+ setLanguageApp(lang);
+ }
+ }, []);
- return (
-
- {children}
-
- );
+ useEffect(() => {
+ if (!languageApp) return;
+
+ const lang = localStorage.getItem("_language");
+
+ if (!lang) {
+ localStorage.setItem("_language", languageApp);
+ } else {
+ if (languageApp != lang) {
+ localStorage.setItem("_language", languageApp);
+ }
+ }
+ }, [languageApp]);
+
+ useEffect(() => {
+ if (!router.isReady) return;
+ if (user.user_language) {
+ if (user.user_language != languageApp) {
+ setLanguageApp(user.user_language);
+ return;
+ }
+ }
+
+ if (languageApp != router.locale) {
+ router.replace(
+ {pathname: router.pathname, query: router.query},
+ router.asPath,
+ {
+ locale: languageApp,
+ }
+ );
+ return;
+ }
+ for (const lang of languageList) {
+ if (languageApp != lang.key) continue;
+ setDirectionApp(lang.dir);
+ document.dir = lang.dir;
+ }
+
+ const timer = setTimeout(() => {
+ changeLanguageState(false);
+ setLanguageIsReady(true);
+ }, 1000);
+
+ return () => {
+ clearTimeout(timer);
+ };
+ }, [router.locale, router.isReady, userChangedLanguage, languageApp]);
+
+ return (
+
+ {children}
+
+ );
};
diff --git a/src/lib/app/contexts/loading.jsx b/src/lib/app/contexts/loading.jsx
index 6e95a8c..f5b8a47 100644
--- a/src/lib/app/contexts/loading.jsx
+++ b/src/lib/app/contexts/loading.jsx
@@ -1,14 +1,14 @@
import LoadingHardPage from "@/core/components/LoadingHardPage";
-import { createContext, useState } from "react";
+import {createContext, useState} from "react";
export const LoadingContext = createContext();
-export const LoadingProvider = ({ children }) => {
- const [loadingPage, setLoadingPage] = useState(false);
- return (
-
-
- {children}
-
- );
+export const LoadingProvider = ({children}) => {
+ const [loadingPage, setLoadingPage] = useState(false);
+ return (
+
+
+ {children}
+
+ );
};
diff --git a/src/lib/app/contexts/user.jsx b/src/lib/app/contexts/user.jsx
index 49d55af..10611b8 100644
--- a/src/lib/app/contexts/user.jsx
+++ b/src/lib/app/contexts/user.jsx
@@ -1,144 +1,132 @@
-import {
- GET_USER_ROUTE,
- SET_LANGUAGE
-} from "@/core/data/apiRoutes";
+import {GET_USER_ROUTE} from "@/core/data/apiRoutes";
import axios from "axios";
-import { createContext, useCallback, useEffect, useReducer } from "react";
+import {createContext, useCallback, useEffect, useReducer} from "react";
+import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler";
const initialUser = {
- isAuth: false,
- userChangedLanguage: false,
- token: null,
- user: {},
+ isAuth: false,
+ userChangedLanguage: false,
+ token: null,
+ user: {},
};
const reducer = (state, action) => {
- switch (action.type) {
- case "CLEAR_USER":
- return { ...state, user: {} };
- case "CHANGE_USER":
- return { ...state, user: action.user };
- case "CHANGE_USER_LANGUAGE":
- return {
- ...state,
- user: { ...state.user, user_language: action.language },
- };
- case "CHANGE_AUTH_STATE":
- return { ...state, isAuth: action.isAuth };
- case "CHANGE_LANGUAGE_STATE":
- return { ...state, userChangedLanguage: action.userChangedLanguage };
- case "CLEAR_TOKEN":
- localStorage.removeItem("_token");
- return { ...state, token: null };
- case "SET_TOKEN":
- localStorage.setItem("_token", action.token);
- return { ...state, token: action.token };
- default:
- return state;
- }
+ switch (action.type) {
+ case "CLEAR_USER":
+ return {...state, user: {}};
+ case "CHANGE_USER":
+ return {...state, user: action.user};
+ case "CHANGE_USER_LANGUAGE":
+ return {
+ ...state,
+ user: {...state.user, user_language: action.language},
+ };
+ case "CHANGE_AUTH_STATE":
+ return {...state, isAuth: action.isAuth};
+ case "CHANGE_LANGUAGE_STATE":
+ return {...state, userChangedLanguage: action.userChangedLanguage};
+ case "CLEAR_TOKEN":
+ localStorage.removeItem("_token");
+ return {...state, token: null};
+ case "SET_TOKEN":
+ localStorage.setItem("_token", action.token);
+ return {...state, token: action.token};
+ default:
+ return state;
+ }
};
export const UserContext = createContext();
-export const UserProvider = ({ children }) => {
- const [state, dispatch] = useReducer(reducer, initialUser);
+export const UserProvider = ({children}) => {
+ const [state, dispatch] = useReducer(reducer, initialUser);
- const clearUser = useCallback(() => {
- dispatch({ type: "CLEAR_USER" });
- }, []);
+ const clearUser = useCallback(() => {
+ dispatch({type: "CLEAR_USER"});
+ }, []);
- const changeUser = useCallback((user) => {
- dispatch({ type: "CHANGE_USER", user });
- }, []);
+ const changeUser = useCallback((user) => {
+ dispatch({type: "CHANGE_USER", user});
+ }, []);
- const changeUserLanguage = useCallback(
- (language) => {
- dispatch({ type: "CHANGE_USER_LANGUAGE", language });
- axios
- .post(
- SET_LANGUAGE,
- { language: language },
- {
- headers: {
- authorization: `Bearer ${state.token}`,
- },
- }
- )
- .then(() => {
- getUser((data) => {
+ const changeUserLanguage = useCallback(/* use in multi language app */);
+
+ const changeAuthState = useCallback((isAuth) => {
+ dispatch({type: "CHANGE_AUTH_STATE", isAuth});
+ }, []);
+
+ const changeLanguageState = useCallback((userChangedLanguage) => {
+ dispatch({type: "CHANGE_LANGUAGE_STATE", userChangedLanguage});
+ }, []);
+
+ const clearToken = useCallback(() => {
+ dispatch({type: "CLEAR_TOKEN"});
+ }, []);
+
+ const setToken = useCallback((token) => {
+ dispatch({type: "SET_TOKEN", token});
+ }, []);
+
+ const getUser = useCallback(
+ (callback = () => {
+ }) => {
+ axios
+ .get(GET_USER_ROUTE, {
+ headers: {authorization: `Bearer ${state.token}`},
+ })
+ .then(({data}) => {
+ if (typeof callback === "function") callback(data);
+ })
+ .catch(error => {
+ if (error.response) {
+ errorResponse(error.response, clearToken, null, false)
+ } else if (error.request) {
+ errorRequest(null, false)
+ } else {
+ errorSetting(null, false)
+ }
+ })
+ },
+ [state.token]
+ );
+
+ useEffect(() => {
+ const localToken = localStorage.getItem("_token");
+ if (localToken) dispatch({type: "SET_TOKEN", token: localToken});
+ }, []);
+
+ useEffect(() => {
+ if (!state.token) {
+ clearUser();
+ changeAuthState(false);
+ changeLanguageState(false);
+ return;
+ }
+ getUser((data) => {
changeUser(data);
- });
+ changeAuthState(true);
+ changeLanguageState(true);
});
- },
- [state.token]
- );
+ }, [state.token]);
- const changeAuthState = useCallback((isAuth) => {
- dispatch({ type: "CHANGE_AUTH_STATE", isAuth });
- }, []);
-
- const changeLanguageState = useCallback((userChangedLanguage) => {
- dispatch({ type: "CHANGE_LANGUAGE_STATE", userChangedLanguage });
- }, []);
-
- const clearToken = useCallback(() => {
- dispatch({ type: "CLEAR_TOKEN" });
- }, []);
-
- const setToken = useCallback((token) => {
- dispatch({ type: "SET_TOKEN", token });
- }, []);
-
- const getUser = useCallback(
- (callback = () => {}) => {
- axios
- .get(GET_USER_ROUTE, {
- headers: { authorization: `Bearer ${state.token}` },
- })
- .then(({ data }) => {
- if (typeof callback === "function") callback(data);
- });
- },
- [state.token]
- );
-
- useEffect(() => {
- const localToken = localStorage.getItem("_token");
- if (localToken) dispatch({ type: "SET_TOKEN", token: localToken });
- }, []);
-
- useEffect(() => {
- if (!state.token) {
- clearUser();
- changeAuthState(false);
- changeLanguageState(false);
- return;
- }
- getUser((data) => {
- changeUser(data);
- changeAuthState(true);
- changeLanguageState(true);
- });
- }, [state.token]);
-
- return (
-
- {children}
-
- );
+ return (
+
+ {children}
+
+ );
};
diff --git a/src/lib/app/hooks/useDirection.jsx b/src/lib/app/hooks/useDirection.jsx
index e45cb24..b2e01fe 100644
--- a/src/lib/app/hooks/useDirection.jsx
+++ b/src/lib/app/hooks/useDirection.jsx
@@ -1,10 +1,10 @@
-import { useContext } from "react";
-import { LanguageContext } from "../contexts/language";
+import {useContext} from "react";
+import {LanguageContext} from "../contexts/language";
const useDirection = () => {
- const { directionApp } = useContext(LanguageContext);
+ const {directionApp} = useContext(LanguageContext);
- return { directionApp };
+ return {directionApp};
};
export default useDirection;
diff --git a/src/lib/app/hooks/useLanguage.jsx b/src/lib/app/hooks/useLanguage.jsx
index 66e2ee0..d663835 100644
--- a/src/lib/app/hooks/useLanguage.jsx
+++ b/src/lib/app/hooks/useLanguage.jsx
@@ -1,28 +1,28 @@
-import { useContext } from "react";
-import { LanguageContext } from "../contexts/language";
+import {useContext} from "react";
+import {LanguageContext} from "../contexts/language";
import useUser from "./useUser";
const useLanguage = () => {
- const { isAuth, changeUserLanguage } = useUser();
- const {
- languageApp,
- setLanguageApp,
- languageIsReady,
- setLanguageIsReady,
- languageList,
- } = useContext(LanguageContext);
+ const {isAuth, changeUserLanguage} = useUser();
+ const {
+ languageApp,
+ setLanguageApp,
+ languageIsReady,
+ setLanguageIsReady,
+ languageList,
+ } = useContext(LanguageContext);
- const changeLanguage = (lang) => {
- if (lang == languageApp) return;
+ const changeLanguage = (lang) => {
+ if (lang == languageApp) return;
- setLanguageIsReady(false);
- setLanguageApp(lang);
- if (isAuth) {
- changeUserLanguage(lang);
- }
- };
+ setLanguageIsReady(false);
+ setLanguageApp(lang);
+ if (isAuth) {
+ changeUserLanguage(lang);
+ }
+ };
- return { languageApp, changeLanguage, languageIsReady, languageList };
+ return {languageApp, changeLanguage, languageIsReady, languageList};
};
export default useLanguage;
diff --git a/src/lib/app/hooks/useLoading.jsx b/src/lib/app/hooks/useLoading.jsx
index d74a87e..a691bd7 100644
--- a/src/lib/app/hooks/useLoading.jsx
+++ b/src/lib/app/hooks/useLoading.jsx
@@ -1,10 +1,10 @@
-import { useContext } from "react";
-import { LoadingContext } from "../contexts/loading";
+import {useContext} from "react";
+import {LoadingContext} from "../contexts/loading";
const useLoading = () => {
- const { setLoadingPage } = useContext(LoadingContext);
+ const {setLoadingPage} = useContext(LoadingContext);
- return { setLoadingPage };
+ return {setLoadingPage};
};
export default useLoading;
diff --git a/src/lib/app/hooks/useNetwork.jsx b/src/lib/app/hooks/useNetwork.jsx
new file mode 100644
index 0000000..84e2950
--- /dev/null
+++ b/src/lib/app/hooks/useNetwork.jsx
@@ -0,0 +1,58 @@
+import {useEffect, useState} from "react";
+
+function getNetworkConnection() {
+ return (
+ navigator.connection ||
+ navigator.mozConnection ||
+ navigator.webkitConnection ||
+ null
+ );
+}
+
+function getNetworkConnectionInfo() {
+ const connection = getNetworkConnection();
+ if (!connection) {
+ return {};
+ }
+ return {
+ rtt: connection.rtt,
+ type: connection.type,
+ saveData: connection.saveData,
+ downLink: connection.downLink,
+ downLinkMax: connection.downLinkMax,
+ effectiveType: connection.effectiveType,
+ };
+}
+
+function useNetwork() {
+ const [state, setState] = useState(() => {
+ return {
+ online: navigator.onLine,
+ };
+ });
+ useEffect(() => {
+ const handleOnline = () => {
+ setState((prevState) => ({
+ ...prevState,
+ online: true,
+ }));
+ };
+ const handleOffline = () => {
+ setState((prevState) => ({
+ ...prevState,
+ online: false,
+ }));
+ };
+
+ window.addEventListener("online", handleOnline);
+ window.addEventListener("offline", handleOffline);
+ return () => {
+ window.removeEventListener("online", handleOnline);
+ window.removeEventListener("offline", handleOffline);
+ };
+ }, []);
+
+ return state;
+}
+
+export default useNetwork;
\ No newline at end of file
diff --git a/src/lib/app/hooks/useNotification.jsx b/src/lib/app/hooks/useNotification.jsx
new file mode 100644
index 0000000..e32f829
--- /dev/null
+++ b/src/lib/app/hooks/useNotification.jsx
@@ -0,0 +1,23 @@
+import useSWR from 'swr'
+import {GET_SIDEBAR_NOTIFICATION} from "@/core/data/apiRoutes";
+import useRequest from "@/lib/app/hooks/useRequest";
+
+const useNotification = () => {
+ const requestServer = useRequest({auth: true, notification: false})
+
+ //swr config
+ const fetcher = (...args) => {
+ return requestServer(args, 'get').then((response) => {
+ return response.data.data;
+ }).catch(() => {
+ })
+ };
+
+ const {data, mutate} = useSWR(GET_SIDEBAR_NOTIFICATION, fetcher)
+ const notification_count = data
+ //swr config
+
+ // render data
+ return {notification_count, update_notification: mutate}
+}
+export default useNotification
\ No newline at end of file
diff --git a/src/lib/app/hooks/useRequest.jsx b/src/lib/app/hooks/useRequest.jsx
new file mode 100644
index 0000000..d361e08
--- /dev/null
+++ b/src/lib/app/hooks/useRequest.jsx
@@ -0,0 +1,66 @@
+import axios from "axios";
+import {successRequest} from "@/core/utils/succesHandler";
+import PendingNotification from "@/core/components/notifications/PendingNotification";
+import {useTranslations} from "next-intl";
+import useUser from "@/lib/app/hooks/useUser";
+import {errorRequest, errorResponse, errorSetting} from "@/core/utils/errorHandler";
+import useNetwork from "@/lib/app/hooks/useNetwork";
+
+const defaultOptions = {
+ auth: false, data: {}, requestOptions: {
+ headers: {}
+ }, notification: true, pending: true, success: {
+ notification: {
+ show: true,
+ },
+ }, failed: {
+ notification: {
+ show: true,
+ },
+ },
+}
+const useRequest = (initOptions) => {
+ const network = useNetwork()
+ const t = useTranslations()
+ const {token, clearToken} = useUser()
+ let _options = {...defaultOptions, ...initOptions}
+
+ function requestServer(url = '', method = 'get', options) {
+ _options = {..._options, ...options}
+ if (_options.auth) _options = {
+ ..._options, requestOptions: {
+ ..._options.requestOptions,
+ headers: {..._options.requestOptions.headers, authorization: `Bearer ${token}`}
+ }
+ }
+
+ return new Promise((resolve, reject) => {
+ if (!network.online) {
+ reject()
+ return
+ }
+ if (_options.notification && _options.failed.notification.show && _options.pending) PendingNotification(t)
+ axios({
+ url: url, method: method, data: _options.data, ..._options.requestOptions
+ })
+ .then(response => {
+ successRequest(response, t, _options)
+ resolve(response)
+ })
+ .catch(error => {
+ if (error.response) {
+ errorResponse(error.response, clearToken, t, _options.notification && _options.failed.notification.show)
+ } else if (error.request) {
+ errorRequest(t, _options.notification && _options.failed.notification.show)
+ } else {
+ errorSetting(t, _options.notification && _options.failed.notification.show)
+ }
+ reject(error)
+ })
+ });
+ }
+
+ return requestServer
+}
+
+export default useRequest
\ No newline at end of file
diff --git a/src/lib/app/hooks/useUser.jsx b/src/lib/app/hooks/useUser.jsx
index baa0aaa..b0bbc1a 100644
--- a/src/lib/app/hooks/useUser.jsx
+++ b/src/lib/app/hooks/useUser.jsx
@@ -1,36 +1,34 @@
-import { useContext } from "react";
-import { UserContext } from "../contexts/user";
+import {useContext} from "react";
+import {UserContext} from "../contexts/user";
const useUser = () => {
- const {
- isAuth,
- userChangedLanguage,
- token,
- user,
- getUser,
- clearUser,
- changeUser,
- changeUserLanguage,
- changeAuthState,
- changeLanguageState,
- clearToken,
- setToken,
- } = useContext(UserContext);
+ const {
+ isAuth,
+ userChangedLanguage,
+ token,
+ user,
+ getUser,
+ clearUser,
+ changeUser,
+ changeAuthState,
+ changeLanguageState,
+ clearToken,
+ setToken,
+ } = useContext(UserContext);
- return {
- isAuth,
- userChangedLanguage,
- token,
- user,
- getUser,
- clearUser,
- changeUser,
- changeUserLanguage,
- changeAuthState,
- changeLanguageState,
- clearToken,
- setToken,
- };
+ return {
+ isAuth,
+ userChangedLanguage,
+ token,
+ user,
+ getUser,
+ clearUser,
+ changeUser,
+ changeAuthState,
+ changeLanguageState,
+ clearToken,
+ setToken,
+ };
};
export default useUser;
diff --git a/src/middlewares/RolePermission.jsx b/src/middlewares/RolePermission.jsx
new file mode 100644
index 0000000..67fc3f1
--- /dev/null
+++ b/src/middlewares/RolePermission.jsx
@@ -0,0 +1,43 @@
+import {NextLinkComposed} from "@/core/components/LinkRouting";
+import Message from "@/core/components/Messages";
+import useUser from "@/lib/app/hooks/useUser";
+import {Button, Typography} from "@mui/material";
+import {useTranslations} from "next-intl";
+
+const RolePermissionMiddleware = ({children, requiredPermissions}) => {
+ const {user} = useUser();
+ const t = useTranslations();
+
+ const hasPermission = requiredPermissions.some((permission) =>
+ user?.permissions?.includes(permission)
+ );
+
+ if (!hasPermission) {
+ return (
+
+ {t("Permission.typography_you_dont_have_access")}
+
+ }
+ actions={
+ <>
+
+ >
+ }
+ />
+ );
+ }
+
+ return <>{children}>;
+};
+
+export default RolePermissionMiddleware;
diff --git a/src/middlewares/WithAuth.jsx b/src/middlewares/WithAuth.jsx
index d158bf3..b20d8b3 100644
--- a/src/middlewares/WithAuth.jsx
+++ b/src/middlewares/WithAuth.jsx
@@ -1,42 +1,42 @@
-import { NextLinkComposed } from "@/core/components/LinkRouting";
+import {NextLinkComposed} from "@/core/components/LinkRouting";
import Message from "@/core/components/Messages";
import useUser from "@/lib/app/hooks/useUser";
-import { Button, Typography } from "@mui/material";
-import { useTranslations } from "next-intl";
-import { useRouter } from "next/router";
+import {Button, Typography} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useRouter} from "next/router";
-const WithAuthMiddleware = ({ children }) => {
- const { isAuth } = useUser();
- const t = useTranslations();
- const router = useRouter();
+const WithAuthMiddleware = ({children}) => {
+ const {isAuth} = useUser();
+ const t = useTranslations();
+ const router = useRouter();
- if (!isAuth)
- return (
-
- {t(
- "typography_your_access_to_this_page_has_expired_Please_login_again"
- )}
-
- }
- actions={
- <>
-
- >
- }
- />
- );
- return <>{children}>;
+ if (!isAuth)
+ return (
+
+ {t(
+ "Authorization.typography_your_access_to_this_page_has_expired_Please_login_again"
+ )}
+
+ }
+ actions={
+ <>
+
+ >
+ }
+ />
+ );
+ return <>{children}>;
};
export default WithAuthMiddleware;
diff --git a/src/middlewares/WithoutAuth.jsx b/src/middlewares/WithoutAuth.jsx
index 5fb4f93..594ffc5 100644
--- a/src/middlewares/WithoutAuth.jsx
+++ b/src/middlewares/WithoutAuth.jsx
@@ -1,56 +1,56 @@
import Message from "@/core/components/Messages";
import useUser from "@/lib/app/hooks/useUser";
-import { Stack, Typography } from "@mui/material";
-import { useTranslations } from "next-intl";
-import { useSearchParams } from "next/navigation";
-import { useRouter } from "next/router";
-import { useEffect } from "react";
+import {Stack, Typography} from "@mui/material";
+import {useTranslations} from "next-intl";
+import {useSearchParams} from "next/navigation";
+import {useRouter} from "next/router";
+import {useEffect} from "react";
-const WithoutAuthMiddleware = ({ children }) => {
- const { isAuth } = useUser();
- const t = useTranslations();
- const router = useRouter();
+const WithoutAuthMiddleware = ({children}) => {
+ const {isAuth} = useUser();
+ const t = useTranslations();
+ const router = useRouter();
- // gettin url query
- const searchParams = useSearchParams();
- const backUrlDecodedPath = searchParams.get("back_url");
+ // gettin url query
+ const searchParams = useSearchParams();
+ const backUrlDecodedPath = searchParams.get("back_url");
- useEffect(() => {
- if (!isAuth) return;
- const timer = setTimeout(() => {
- router.replace(
- backUrlDecodedPath
- ? decodeURIComponent(backUrlDecodedPath)
- : "/dashboard"
- );
- }, 2000);
+ useEffect(() => {
+ if (!isAuth) return;
+ const timer = setTimeout(() => {
+ router.replace(
+ backUrlDecodedPath
+ ? decodeURIComponent(backUrlDecodedPath)
+ : "/dashboard"
+ );
+ }, 2000);
- return () => {
- clearTimeout(timer);
- };
- }, [isAuth]);
+ return () => {
+ clearTimeout(timer);
+ };
+ }, [isAuth]);
- if (isAuth)
- return (
-
-
- {t(
- "typography_your_login_is_valid_and_you_do_not_need_to_login_again"
- )}
-
-
- {t("typography_redirect_to")}{" "}
- {backUrlDecodedPath
- ? t("typography_routing_previuos_page")
- : t("typography_routing_dashbaord_page")}
-
-
- }
- />
- );
- return <>{children}>;
+ if (isAuth)
+ return (
+
+
+ {t(
+ "Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again"
+ )}
+
+
+ {t("Authorization.typography_redirect_to")}{" "}
+ {backUrlDecodedPath
+ ? t("Authorization.typography_routing_previuos_page")
+ : t("Authorization.typography_routing_dashbaord_page")}
+
+
+ }
+ />
+ );
+ return <>{children}>;
};
export default WithoutAuthMiddleware;
diff --git a/src/pages/403.jsx b/src/pages/403.jsx
new file mode 100644
index 0000000..15ba915
--- /dev/null
+++ b/src/pages/403.jsx
@@ -0,0 +1,24 @@
+import {useEffect, useState} from "react";
+import {useRouter} from "next/router";
+import {NextIntlProvider} from "next-intl";
+import UnAuthorizedComponent from "@/components/errors/403";
+
+export default function Custom404() {
+ const router = useRouter()
+ const [messages, setMessages] = useState(null)
+ useEffect(() => {
+ const fetch = async () => {
+ const tempMessages = (await import(`&/locales/${router.locale}/app.json`)).default
+ setMessages(tempMessages)
+ }
+ fetch()
+ }, []);
+
+ if (!messages) return
+
+ return (
+
+
+
+ );
+}
diff --git a/src/pages/404.jsx b/src/pages/404.jsx
new file mode 100644
index 0000000..26de038
--- /dev/null
+++ b/src/pages/404.jsx
@@ -0,0 +1,25 @@
+import {useEffect, useState} from "react";
+import {useRouter} from "next/router";
+import {NextIntlProvider} from "next-intl";
+import NotFoundComponent from "@/components/errors/404";
+
+export default function Custom404() {
+ const router = useRouter()
+ const [messages, setMessages] = useState(null)
+ useEffect(() => {
+
+ const fetch = async () => {
+ const tempMessages = (await import(`&/locales/${router.locale}/app.json`)).default
+ setMessages(tempMessages)
+ }
+ fetch()
+ }, []);
+
+ if (!messages) return
+
+ return (
+
+
+
+ );
+}
diff --git a/src/pages/500.jsx b/src/pages/500.jsx
new file mode 100644
index 0000000..4b85bc2
--- /dev/null
+++ b/src/pages/500.jsx
@@ -0,0 +1,24 @@
+import {useEffect, useState} from "react";
+import {useRouter} from "next/router";
+import {NextIntlProvider} from "next-intl";
+import ServerErrorComponent from "@/components/errors/500";
+
+export default function Custom500() {
+ const router = useRouter()
+ const [messages, setMessages] = useState(null)
+ useEffect(() => {
+ const fetch = async () => {
+ const tempMessages = (await import(`&/locales/${router.locale}/app.json`)).default
+ setMessages(tempMessages)
+ }
+ fetch()
+ }, []);
+
+ if (!messages) return
+
+ return (
+
+
+
+ );
+}
diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx
index be5d828..29ec464 100644
--- a/src/pages/_app.jsx
+++ b/src/pages/_app.jsx
@@ -1,30 +1,33 @@
import "&/fontiran.scss";
import AppLayout from "@/layouts/AppLayout";
import MuiLayout from "@/layouts/MuiLayout";
-import { LanguageProvider } from "@/lib/app/contexts/language";
-import { LoadingProvider } from "@/lib/app/contexts/loading";
-import { UserProvider } from "@/lib/app/contexts/user";
+import {LanguageProvider} from "@/lib/app/contexts/language";
+import {LoadingProvider} from "@/lib/app/contexts/loading";
+import {UserProvider} from "@/lib/app/contexts/user";
import "moment/locale/fa";
-import { NextIntlProvider } from "next-intl";
+import {NextIntlProvider} from "next-intl";
+import TitlePage from "@/core/components/TitlePage";
-const App = ({ Component, pageProps }) => {
- return (
- <>
-
-
-
-
-
-
-
-
-
-
-
-
-
- >
- );
+const App = ({Component, pageProps}) => {
+
+ return (
+ <>
+
+
+
+
+ {pageProps.messages ? : ''}
+
+
+
+
+
+
+
+
+
+ >
+ );
};
export default App;
diff --git a/src/pages/_document.jsx b/src/pages/_document.jsx
index e763884..474e29b 100644
--- a/src/pages/_document.jsx
+++ b/src/pages/_document.jsx
@@ -1,67 +1,61 @@
-import {
- createEmotionCacheLtr
-} from "@/core/utils/createEmotionCache";
+import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache";
import theme from "@/core/utils/theme";
import createEmotionServer from "@emotion/server/create-instance";
-import Document, { Head, Html, Main, NextScript } from "next/document";
+import Document, {Head, Html, Main, NextScript} from "next/document";
export default function MyDocument(props) {
- const { emotionStyleTags } = props;
+ const {emotionStyleTags} = props;
- return (
-
-
-
-
-
-
-
- {emotionStyleTags}
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+
+
+ {emotionStyleTags}
+
+
+
+
+
+
+ );
}
MyDocument.getInitialProps = async (ctx) => {
- const originalRenderPage = ctx.renderPage;
- let cache;
- switch (ctx.locale) {
- case "fa":
- cache = createEmotionCacheLtr();
- break;
- }
+ const originalRenderPage = ctx.renderPage;
+ let cache;
+ switch (ctx.locale) {
+ case "fa":
+ cache = createEmotionCacheRtl();
+ break;
+ }
- const { extractCriticalToChunks } = createEmotionServer(cache);
+ const {extractCriticalToChunks} = createEmotionServer(cache);
- ctx.renderPage = () =>
- originalRenderPage({
- enhanceApp: (App) =>
- function EnhanceApp(props) {
- return ;
- },
- });
+ ctx.renderPage = () =>
+ originalRenderPage({
+ enhanceApp: (App) =>
+ function EnhanceApp(props) {
+ return ;
+ },
+ });
- const initialProps = await Document.getInitialProps(ctx);
+ const initialProps = await Document.getInitialProps(ctx);
- const emotionStyles = extractCriticalToChunks(initialProps.html);
- const emotionStyleTags = emotionStyles.styles.map((style) => (
-
- ));
+ const emotionStyles = extractCriticalToChunks(initialProps.html);
+ const emotionStyleTags = emotionStyles.styles.map((style) => (
+
+ ));
- return {
- ...initialProps,
- emotionStyleTags,
- };
+ return {
+ ...initialProps,
+ emotionStyleTags,
+ };
};
diff --git a/src/pages/dashboard/change-password/index.jsx b/src/pages/dashboard/change-password/index.jsx
new file mode 100644
index 0000000..670e184
--- /dev/null
+++ b/src/pages/dashboard/change-password/index.jsx
@@ -0,0 +1,22 @@
+import DashboardChangePasswordComponent from "@/components/dashboard/change-password";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+
+export default function LoanFollowUp() {
+ return (
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.change_password",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/commercial-chief/index.jsx b/src/pages/dashboard/commercial-chief/index.jsx
new file mode 100644
index 0000000..841d668
--- /dev/null
+++ b/src/pages/dashboard/commercial-chief/index.jsx
@@ -0,0 +1,26 @@
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+import DashboardCommercialChiefComponent from "@/components/dashboard/commercial-chief";
+
+const requiredPermissions = ["manage_commercial_refahi"];
+export default function CommercialChief() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.commercial_chief_page",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/development-assistant/index.jsx b/src/pages/dashboard/development-assistant/index.jsx
new file mode 100644
index 0000000..aaaea39
--- /dev/null
+++ b/src/pages/dashboard/development-assistant/index.jsx
@@ -0,0 +1,26 @@
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+import DashboardDevelopmentAssistantComponent from "@/components/dashboard/development-assistant";
+
+const requiredPermissions = ["manage_development_refahi"];
+export default function DevelopmentAssistant() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.development_assistant_page",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/edit-profile/index.jsx b/src/pages/dashboard/edit-profile/index.jsx
new file mode 100644
index 0000000..9460506
--- /dev/null
+++ b/src/pages/dashboard/edit-profile/index.jsx
@@ -0,0 +1,22 @@
+import DashboardEditProfile from "@/components/dashboard/edit-profile";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+
+export default function LoanFollowUp() {
+ return (
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.edit_profile",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/index.jsx b/src/pages/dashboard/index.jsx
index 5ebc479..af824d5 100644
--- a/src/pages/dashboard/index.jsx
+++ b/src/pages/dashboard/index.jsx
@@ -1,23 +1,22 @@
import DashboardFirstComponent from "@/components/dashboard/first";
-import TitlePage from "@/core/components/TitlePage";
-import WithAuthMiddleware from "@/middlewares/WithoutAuth";
-import { parse } from "next-useragent";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
export default function Dashboard() {
- return (
-
-
-
-
- );
+ return (
+
+
+
+ );
}
-export async function getServerSideProps({ req, locale }) {
- const { isBot } = parse(req.headers["user-agent"]);
- return {
- props: {
- messages: (await import(`&/locales/${locale}/app.json`)).default,
- isBot,
- },
- };
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.dashboard_page",
+ isBot,
+ },
+ };
}
diff --git a/src/pages/dashboard/inspector-expert/index.jsx b/src/pages/dashboard/inspector-expert/index.jsx
new file mode 100644
index 0000000..902a7ec
--- /dev/null
+++ b/src/pages/dashboard/inspector-expert/index.jsx
@@ -0,0 +1,26 @@
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+import DashboardInspectorExpertComponent from "@/components/dashboard/inspector-expert";
+
+const requiredPermissions = ["manage_inspector_refahi"];
+export default function InspectorExpert() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.inspector_expert_page",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/loan-follow-up/index.jsx b/src/pages/dashboard/loan-follow-up/index.jsx
deleted file mode 100644
index fc299c4..0000000
--- a/src/pages/dashboard/loan-follow-up/index.jsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import DashboardLoanFollowUpComponent from "@/components/dashboard/loan-follow-up";
-import TitlePage from "@/core/components/TitlePage";
-import WithAuthMiddleware from "@/middlewares/WithoutAuth";
-import { parse } from "next-useragent";
-
-export default function LoanFollowUp() {
- return (
-
-
-
-
- );
-}
-
-export async function getServerSideProps({ req, locale }) {
- const { isBot } = parse(req.headers["user-agent"]);
- return {
- props: {
- messages: (await import(`&/locales/${locale}/app.json`)).default,
- isBot,
- },
- };
-}
diff --git a/src/pages/dashboard/loan-request/index.jsx b/src/pages/dashboard/loan-request/index.jsx
deleted file mode 100644
index b76f172..0000000
--- a/src/pages/dashboard/loan-request/index.jsx
+++ /dev/null
@@ -1,23 +0,0 @@
-import DashboardLoanRequestComponent from "@/components/dashboard/loan-request";
-import TitlePage from "@/core/components/TitlePage";
-import WithAuthMiddleware from "@/middlewares/WithoutAuth";
-import { parse } from "next-useragent";
-
-export default function LoanRequest() {
- return (
-
-
-
-
- );
-}
-
-export async function getServerSideProps({ req, locale }) {
- const { isBot } = parse(req.headers["user-agent"]);
- return {
- props: {
- messages: (await import(`&/locales/${locale}/app.json`)).default,
- isBot,
- },
- };
-}
diff --git a/src/pages/dashboard/machinery-expert/index.jsx b/src/pages/dashboard/machinery-expert/index.jsx
new file mode 100644
index 0000000..fc0c248
--- /dev/null
+++ b/src/pages/dashboard/machinery-expert/index.jsx
@@ -0,0 +1,26 @@
+import DashboardMachineryOfficeComponent from "@/components/dashboard/machinary-office";
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+
+const requiredPermissions = ["manage_machinery_navgan"];
+export default function PassengerOffice() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.machinary_office_page",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/navgan-province-manager/index.jsx b/src/pages/dashboard/navgan-province-manager/index.jsx
new file mode 100644
index 0000000..fde7e8c
--- /dev/null
+++ b/src/pages/dashboard/navgan-province-manager/index.jsx
@@ -0,0 +1,26 @@
+import DashboardNavganProvinceManagerComponent from "src/components/dashboard/navgan-province-manager";
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+
+const requiredPermissions = ["manage_province_affairs_navgan"];
+export default function PassengerOffice() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.province_manager_page",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/passenger-boss/index.jsx b/src/pages/dashboard/passenger-boss/index.jsx
new file mode 100644
index 0000000..839488e
--- /dev/null
+++ b/src/pages/dashboard/passenger-boss/index.jsx
@@ -0,0 +1,26 @@
+import DashboardPassengerBossComponent from "@/components/dashboard/passenger-boss";
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+
+const requiredPermissions = ["manage_province_working_group_navgan"];
+export default function PassengerBoss() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.passenger_boss_page",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/passenger-office-chief/index.jsx b/src/pages/dashboard/passenger-office-chief/index.jsx
new file mode 100644
index 0000000..f92ae2f
--- /dev/null
+++ b/src/pages/dashboard/passenger-office-chief/index.jsx
@@ -0,0 +1,26 @@
+import DashboardPassengerOfficeComponent from "@/components/dashboard/passenger-office";
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+
+const requiredPermissions = ["manage_passenger_office_navgan"];
+export default function PassengerOffice() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.passenger_office_page",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/province-head-expert/index.jsx b/src/pages/dashboard/province-head-expert/index.jsx
new file mode 100644
index 0000000..e288c37
--- /dev/null
+++ b/src/pages/dashboard/province-head-expert/index.jsx
@@ -0,0 +1,26 @@
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+import DashboardProvinceHeadExpertComponent from "@/components/dashboard/province-head-expert";
+
+const requiredPermissions = ["manage_province_headquarter_refahi"];
+export default function ProvinceHeadExpertOffice() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.province_head_expert",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/refahi-province-manager/index.jsx b/src/pages/dashboard/refahi-province-manager/index.jsx
new file mode 100644
index 0000000..baac91b
--- /dev/null
+++ b/src/pages/dashboard/refahi-province-manager/index.jsx
@@ -0,0 +1,26 @@
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+import DashboardRefahiProvinceManagerComponent from "@/components/dashboard/refahi-province-manager";
+
+const requiredPermissions = ["manage_province_affairs_refahi"];
+export default function RefahiProvinceManager() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.province_manager_page",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/dashboard/transportation-assistant/index.jsx b/src/pages/dashboard/transportation-assistant/index.jsx
new file mode 100644
index 0000000..ea58847
--- /dev/null
+++ b/src/pages/dashboard/transportation-assistant/index.jsx
@@ -0,0 +1,26 @@
+import DashboardTransportationAssistanceComponent from "@/components/dashboard/transportation-assistance";
+import RolePermissionMiddleware from "@/middlewares/RolePermission";
+import WithAuthMiddleware from "@/middlewares/WithAuth";
+import {parse} from "next-useragent";
+
+const requiredPermissions = ["manage_transportation_navgan"];
+export default function TransportationAssistance() {
+ return (
+
+
+
+
+
+ );
+}
+
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Dashboard.transportation_assistance",
+ isBot,
+ },
+ };
+}
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index a2abc38..2e146c6 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -1,22 +1,21 @@
import FirstComponent from "@/components/first";
-import TitlePage from "@/core/components/TitlePage";
-import { parse } from "next-useragent";
+import {parse} from "next-useragent";
export default function Home() {
- return (
- <>
-
-
- >
- );
+ return (
+ <>
+
+ >
+ );
}
-export async function getServerSideProps({ req, locale }) {
- const { isBot } = parse(req.headers["user-agent"]);
- return {
- props: {
- messages: (await import(`&/locales/${locale}/app.json`)).default,
- isBot,
- },
- };
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "first_page",
+ isBot,
+ },
+ };
}
diff --git a/src/pages/login-expert.jsx b/src/pages/login-expert.jsx
index c9e4e7e..1cc6abf 100644
--- a/src/pages/login-expert.jsx
+++ b/src/pages/login-expert.jsx
@@ -1,28 +1,22 @@
import LoginComponent from "@/components/login-expert";
-import TitlePage from "@/core/components/TitlePage";
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
-import { parse } from "next-useragent";
-import "react-toastify/dist/ReactToastify.css";
-import { ToastContainer } from "react-toastify";
-import useDirection from "@/lib/app/hooks/useDirection";
+import {parse} from "next-useragent";
export default function Login() {
- const { directionApp } = useDirection();
- return (
-
-
-
- {directionApp === "rtl" ? : }
-
- );
+ return (
+
+
+
+ );
}
-export async function getServerSideProps({ req, locale }) {
- const { isBot } = parse(req.headers["user-agent"]);
- return {
- props: {
- messages: (await import(`&/locales/${locale}/app.json`)).default,
- isBot,
- },
- };
+export async function getServerSideProps({req, locale}) {
+ const {isBot} = parse(req.headers["user-agent"]);
+ return {
+ props: {
+ messages: (await import(`&/locales/${locale}/app.json`)).default,
+ title: "Titles.title_login_expert_page",
+ isBot,
+ },
+ };
}