recode and add editor config

This commit is contained in:
Amirhossein Mahmoodi
2023-07-31 15:27:34 +03:30
parent 8a3e82bb9a
commit 51228f3c02
88 changed files with 5121 additions and 4138 deletions

485
.editorconfig Normal file
View File

@@ -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

3
.gitignore vendored
View File

@@ -1,3 +1,4 @@
node_modules node_modules
.next .next
.env.local .env.local
.idea

View File

@@ -1,17 +1,18 @@
# loan-facilities-user # loan-facilities-user
## Getting started ## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps. To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! Already a pro? Just edit this README.md and make it your own. Want to make it
easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files ## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files - [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file)
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line)
or push an existing Git repository with the following command:
``` ```
cd existing_repo cd existing_repo
@@ -46,47 +47,82 @@ Use the built-in continuous integration in GitLab.
# Editing this README # Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template. When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to
structure it however you want - this is just a starting point!). Thank you
to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README ## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
Every project is different, so consider which of these sections apply to yours. The sections used in the template are
suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long
is better than too short. If you think your README is too long, consider utilizing another form of documentation rather
than cutting out information.
## Name ## Name
Choose a self-explaining name for your project. Choose a self-explaining name for your project.
## Description ## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be
unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your
project, this is a good place to list differentiating factors.
## Badges ## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the
project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals ## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see
GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation ## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew.
However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing
specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a
specific context like a particular programming language version or operating system or has dependencies that have to be
installed manually, also add a Requirements subsection.
## Usage ## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of
usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably
include in the README.
## Support ## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address,
etc.
## Roadmap ## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README. If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing ## Contributing
State if you are open to contributions and what your requirements are for accepting them. State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. For people who want to make changes to your project, it's helpful to have some documentation on how to get started.
Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps
explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce
the likelihood that the changes inadvertently break something. Having instructions for running tests is especially
helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment ## Authors and acknowledgment
Show your appreciation to those who have contributed to the project. Show your appreciation to those who have contributed to the project.
## License ## License
For open source projects, say how it is licensed. For open source projects, say how it is licensed.
## Project status ## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
If you have run out of energy or time for your project, put a note at the top of the README saying that development has
slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or
owner, allowing your project to keep going. You can also make an explicit request for maintainers.

View File

@@ -1,8 +1,12 @@
{ {
"compilerOptions": { "compilerOptions": {
"paths": { "paths": {
"@/*": ["./src/*"], "@/*": [
"&/*": ["./public/*"], "./src/*"
],
"&/*": [
"./public/*"
]
} }
} }
} }

View File

@@ -1,12 +1,12 @@
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
const nextConfig = { const nextConfig = {
reactStrictMode: true, reactStrictMode: true,
i18n: { i18n: {
defaultLocale: 'fa', defaultLocale: 'fa',
locales: ['fa'], locales: ['fa'],
localeDetection: false, localeDetection: false,
}, },
} }
module.exports = nextConfig module.exports = nextConfig

View File

@@ -17,80 +17,87 @@ This set of fonts are used in this project under the license: (.....)
* *
**/ **/
@font-face { @font-face {
font-family: IRANSans; font-family: IRANSans;
font-style: normal; font-style: normal;
font-weight: 900; font-weight: 900;
src: url('./fonts/eot/IRANSansWeb_Black.eot'); src: url('./fonts/eot/IRANSansWeb_Black.eot');
src: url('./fonts/eot/IRANSansWeb_Black.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ 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/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/woff/IRANSansWeb_Black.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./fonts/ttf/IRANSansWeb_Black.ttf') format('truetype'); url('./fonts/ttf/IRANSansWeb_Black.ttf') format('truetype');
} }
@font-face { @font-face {
font-family: IRANSans; font-family: IRANSans;
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
src: url('./fonts/eot/IRANSansWeb_Bold.eot'); src: url('./fonts/eot/IRANSansWeb_Bold.eot');
src: url('./fonts/eot/IRANSansWeb_Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ 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/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/woff/IRANSansWeb_Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./fonts/ttf/IRANSansWeb_Bold.ttf') format('truetype'); url('./fonts/ttf/IRANSansWeb_Bold.ttf') format('truetype');
} }
@font-face { @font-face {
font-family: IRANSans; font-family: IRANSans;
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
src: url('./fonts/eot/IRANSansWeb_Medium.eot'); src: url('./fonts/eot/IRANSansWeb_Medium.eot');
src: url('./fonts/eot/IRANSansWeb_Medium.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ 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/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/woff/IRANSansWeb_Medium.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./fonts/ttf/IRANSansWeb_Medium.ttf') format('truetype'); url('./fonts/ttf/IRANSansWeb_Medium.ttf') format('truetype');
} }
@font-face { @font-face {
font-family: IRANSans; font-family: IRANSans;
font-style: normal; font-style: normal;
font-weight: 300; font-weight: 300;
src: url('./fonts/eot/IRANSansWeb_Light.eot'); src: url('./fonts/eot/IRANSansWeb_Light.eot');
src: url('./fonts/eot/IRANSansWeb_Light.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ 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/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/woff/IRANSansWeb_Light.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./fonts/ttf/IRANSansWeb_Light.ttf') format('truetype'); url('./fonts/ttf/IRANSansWeb_Light.ttf') format('truetype');
} }
@font-face { @font-face {
font-family: IRANSans; font-family: IRANSans;
font-style: normal; font-style: normal;
font-weight: 200; font-weight: 200;
src: url('./fonts/eot/IRANSansWeb_UltraLight.eot'); src: url('./fonts/eot/IRANSansWeb_UltraLight.eot');
src: url('./fonts/eot/IRANSansWeb_UltraLight.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ 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/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/woff/IRANSansWeb_UltraLight.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./fonts/ttf/IRANSansWeb_UltraLight.ttf') format('truetype'); url('./fonts/ttf/IRANSansWeb_UltraLight.ttf') format('truetype');
} }
@font-face { @font-face {
font-family: IRANSans; font-family: IRANSans;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
src: url('./fonts/eot/IRANSansWeb.eot'); src: url('./fonts/eot/IRANSansWeb.eot');
src: url('./fonts/eot/IRANSansWeb.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ src: url('./fonts/eot/IRANSansWeb.eot?#iefix') format('embedded-opentype'), /* IE6-8 */
url('./fonts/woff2/IRANSansWeb.woff2') format('woff2'), /* FF39+,Chrome36+, Opera24+*/ 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/woff/IRANSansWeb.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./fonts/ttf/IRANSansWeb.ttf') format('truetype'); url('./fonts/ttf/IRANSansWeb.ttf') format('truetype');
} }
@font-face { @font-face {
font-family: Parastoo; font-family: Parastoo;
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
src: url('./fonts/eot/Parastoo.eot'); src: url('./fonts/eot/Parastoo.eot');
src: url('./fonts/eot/Parastoo.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ 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/woff/Parastoo.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./fonts/ttf/Parastoo.ttf') format('truetype'); url('./fonts/ttf/Parastoo.ttf') format('truetype');
} }
@font-face { @font-face {
font-family: Parastoo; font-family: Parastoo;
font-style: normal; font-style: normal;
font-weight: bold; font-weight: bold;
src: url('./fonts/eot/Parastoo-Bold.eot'); src: url('./fonts/eot/Parastoo-Bold.eot');
src: url('./fonts/eot/Parastoo-Bold.eot?#iefix') format('embedded-opentype'), /* IE6-8 */ 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/woff/Parastoo-Bold.woff') format('woff'), /* FF3.6+, IE9, Chrome6+, Saf5.1+*/
url('./fonts/ttf/Parastoo-Bold.ttf') format('truetype'); url('./fonts/ttf/Parastoo-Bold.ttf') format('truetype');
} }

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1 +1,42 @@
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="430.91406" height="559.70956" viewBox="0 0 430.91406 559.70956" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M689.29823,324.68445q0,4.785-.31006,9.49a143.75442,143.75442,0,0,1-13.46973,52.19c-.06006.14-.13037.27-.18994.4-.36035.76-.73047,1.52-1.11035,2.27a142.03868,142.03868,0,0,1-7.6499,13.5,144.462,144.462,0,0,1-118.56006,66.72l1.43018,82.24,18.6499-9.82,3.33008,6.33-21.83985,11.5,2.66992,152.74.02979,2.04-14.41992,1.21.02978-.05,4.54-246.18a144.17482,144.17482,0,0,1-102-44.38c-.90967-.94-1.81006-1.91-2.68994-2.87-.04-.04-.06982-.08-.1001-.11a144.76758,144.76758,0,0,1-26.33984-40.76c.14014.16.29.31.43017.47a144.642,144.642,0,0,1,68.57959-186.38c.5-.25,1.01026-.49,1.51026-.74a144.75207,144.75207,0,0,1,187.52978,56.93c.88037,1.48005,1.73047,2.99006,2.5503,4.51A143.85218,143.85218,0,0,1,689.29823,324.68445Z" transform="translate(-384.54297 -170.14522)" fill="#e5e5e5"/><circle cx="198.2848" cy="502.61836" r="43.06733" fill="#2f2e41"/><rect x="210.6027" y="532.22265" width="38.58356" height="13.08374" fill="#2f2e41"/><ellipse cx="249.45884" cy="534.4033" rx="4.08868" ry="10.90314" fill="#2f2e41"/><rect x="201.6027" y="531.22265" width="38.58356" height="13.08374" fill="#2f2e41"/><ellipse cx="240.45884" cy="533.4033" rx="4.08868" ry="10.90314" fill="#2f2e41"/><path d="M541.051,632.71229c-3.47748-15.5738,7.63866-31.31043,24.82866-35.14881s33.94421,5.67511,37.42169,21.2489-7.91492,21.31769-25.10486,25.156S544.5285,648.28608,541.051,632.71229Z" transform="translate(-384.54297 -170.14522)" fill="#084070"/><path d="M599.38041,670.31119a10.75135,10.75135,0,0,1-10.33984-7.12305,1,1,0,0,1,1.896-.63672c1.51416,4.50782,6.69825,6.86524,11.55457,5.25342a9.60826,9.60826,0,0,0,5.57251-4.74756,8.23152,8.23152,0,0,0,.48547-6.33789,1,1,0,0,1,1.896-.63672,10.217,10.217,0,0,1-.59229,7.86817,11.62362,11.62362,0,0,1-6.73218,5.75244A11.87976,11.87976,0,0,1,599.38041,670.31119Z" transform="translate(-384.54297 -170.14522)" fill="#fff"/><path d="M618.56452,676.16463a9.57244,9.57244,0,1,1-17.04506,8.71737h0l-.00855-.01674c-2.40264-4.70921.91734-7.63227,5.62657-10.03485S616.162,671.45547,618.56452,676.16463Z" transform="translate(-384.54297 -170.14522)" fill="#fff"/><path d="M772.27559,716.2189h-381a1,1,0,0,1,0-2h381a1,1,0,0,1,0,2Z" transform="translate(-384.54297 -170.14522)" fill="#3f3d56"/><ellipse cx="567.22606" cy="706.64241" rx="7.50055" ry="23.89244" transform="translate(-543.03826 -6.10526) rotate(-14.4613)" fill="#2f2e41"/><path d="M645.50888,621.42349H629.12323a.77274.77274,0,0,1-.51881-1.3455l14.90017-13.49467h-13.7669a.77274.77274,0,0,1,0-1.54548h15.77119a.77275.77275,0,0,1,.51881,1.34551L631.12753,619.878h14.38135a.77274.77274,0,1,1,0,1.54548Z" transform="translate(-384.54297 -170.14522)" fill="#cbcbcb"/><path d="M666.37288,597.46853H649.98723a.77275.77275,0,0,1-.51881-1.34551l14.90017-13.49466h-13.7669a.77274.77274,0,0,1,0-1.54548h15.77119a.77274.77274,0,0,1,.51881,1.3455l-14.90016,13.49467h14.38135a.77274.77274,0,1,1,0,1.54548Z" transform="translate(-384.54297 -170.14522)" fill="#cbcbcb"/><path d="M657.1,571.19534H640.71434a.77274.77274,0,0,1-.51881-1.3455l14.90017-13.49467H641.3288a.77274.77274,0,0,1,0-1.54548H657.1a.77275.77275,0,0,1,.51881,1.34551l-14.90016,13.49466H657.1a.77274.77274,0,0,1,0,1.54548Z" transform="translate(-384.54297 -170.14522)" fill="#cbcbcb"/><path d="M770.66217,347.522,783.457,337.28854c-9.93976-1.09662-14.0238,4.32429-15.69525,8.615-7.76532-3.22446-16.21881,1.00136-16.21881,1.00136l25.6001,9.29375A19.37209,19.37209,0,0,0,770.66217,347.522Z" transform="translate(-384.54297 -170.14522)" fill="#3f3d56"/><path d="M403.66217,180.522,416.457,170.28854c-9.93976-1.09662-14.0238,4.32429-15.69525,8.615-7.76532-3.22446-16.21881,1.00136-16.21881,1.00136l25.6001,9.29375A19.37209,19.37209,0,0,0,403.66217,180.522Z" transform="translate(-384.54297 -170.14522)" fill="#3f3d56"/><path d="M802.66217,215.522,815.457,205.28854c-9.93976-1.09662-14.0238,4.32429-15.69525,8.615-7.76532-3.22446-16.21881,1.00136-16.21881,1.00136l25.6001,9.29375A19.37209,19.37209,0,0,0,802.66217,215.522Z" transform="translate(-384.54297 -170.14522)" fill="#3f3d56"/></svg> <svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="430.91406" height="559.70956"
viewBox="0 0 430.91406 559.70956">
<path
d="M689.29823,324.68445q0,4.785-.31006,9.49a143.75442,143.75442,0,0,1-13.46973,52.19c-.06006.14-.13037.27-.18994.4-.36035.76-.73047,1.52-1.11035,2.27a142.03868,142.03868,0,0,1-7.6499,13.5,144.462,144.462,0,0,1-118.56006,66.72l1.43018,82.24,18.6499-9.82,3.33008,6.33-21.83985,11.5,2.66992,152.74.02979,2.04-14.41992,1.21.02978-.05,4.54-246.18a144.17482,144.17482,0,0,1-102-44.38c-.90967-.94-1.81006-1.91-2.68994-2.87-.04-.04-.06982-.08-.1001-.11a144.76758,144.76758,0,0,1-26.33984-40.76c.14014.16.29.31.43017.47a144.642,144.642,0,0,1,68.57959-186.38c.5-.25,1.01026-.49,1.51026-.74a144.75207,144.75207,0,0,1,187.52978,56.93c.88037,1.48005,1.73047,2.99006,2.5503,4.51A143.85218,143.85218,0,0,1,689.29823,324.68445Z"
transform="translate(-384.54297 -170.14522)" fill="#e5e5e5"/>
<circle cx="198.2848" cy="502.61836" r="43.06733" fill="#2f2e41"/>
<rect x="210.6027" y="532.22265" width="38.58356" height="13.08374" fill="#2f2e41"/>
<ellipse cx="249.45884" cy="534.4033" rx="4.08868" ry="10.90314" fill="#2f2e41"/>
<rect x="201.6027" y="531.22265" width="38.58356" height="13.08374" fill="#2f2e41"/>
<ellipse cx="240.45884" cy="533.4033" rx="4.08868" ry="10.90314" fill="#2f2e41"/>
<path
d="M541.051,632.71229c-3.47748-15.5738,7.63866-31.31043,24.82866-35.14881s33.94421,5.67511,37.42169,21.2489-7.91492,21.31769-25.10486,25.156S544.5285,648.28608,541.051,632.71229Z"
transform="translate(-384.54297 -170.14522)" fill="#084070"/>
<path
d="M599.38041,670.31119a10.75135,10.75135,0,0,1-10.33984-7.12305,1,1,0,0,1,1.896-.63672c1.51416,4.50782,6.69825,6.86524,11.55457,5.25342a9.60826,9.60826,0,0,0,5.57251-4.74756,8.23152,8.23152,0,0,0,.48547-6.33789,1,1,0,0,1,1.896-.63672,10.217,10.217,0,0,1-.59229,7.86817,11.62362,11.62362,0,0,1-6.73218,5.75244A11.87976,11.87976,0,0,1,599.38041,670.31119Z"
transform="translate(-384.54297 -170.14522)" fill="#fff"/>
<path
d="M618.56452,676.16463a9.57244,9.57244,0,1,1-17.04506,8.71737h0l-.00855-.01674c-2.40264-4.70921.91734-7.63227,5.62657-10.03485S616.162,671.45547,618.56452,676.16463Z"
transform="translate(-384.54297 -170.14522)" fill="#fff"/>
<path d="M772.27559,716.2189h-381a1,1,0,0,1,0-2h381a1,1,0,0,1,0,2Z" transform="translate(-384.54297 -170.14522)"
fill="#3f3d56"/>
<ellipse cx="567.22606" cy="706.64241" rx="7.50055" ry="23.89244"
transform="translate(-543.03826 -6.10526) rotate(-14.4613)" fill="#2f2e41"/>
<path
d="M645.50888,621.42349H629.12323a.77274.77274,0,0,1-.51881-1.3455l14.90017-13.49467h-13.7669a.77274.77274,0,0,1,0-1.54548h15.77119a.77275.77275,0,0,1,.51881,1.34551L631.12753,619.878h14.38135a.77274.77274,0,1,1,0,1.54548Z"
transform="translate(-384.54297 -170.14522)" fill="#cbcbcb"/>
<path
d="M666.37288,597.46853H649.98723a.77275.77275,0,0,1-.51881-1.34551l14.90017-13.49466h-13.7669a.77274.77274,0,0,1,0-1.54548h15.77119a.77274.77274,0,0,1,.51881,1.3455l-14.90016,13.49467h14.38135a.77274.77274,0,1,1,0,1.54548Z"
transform="translate(-384.54297 -170.14522)" fill="#cbcbcb"/>
<path
d="M657.1,571.19534H640.71434a.77274.77274,0,0,1-.51881-1.3455l14.90017-13.49467H641.3288a.77274.77274,0,0,1,0-1.54548H657.1a.77275.77275,0,0,1,.51881,1.34551l-14.90016,13.49466H657.1a.77274.77274,0,0,1,0,1.54548Z"
transform="translate(-384.54297 -170.14522)" fill="#cbcbcb"/>
<path
d="M770.66217,347.522,783.457,337.28854c-9.93976-1.09662-14.0238,4.32429-15.69525,8.615-7.76532-3.22446-16.21881,1.00136-16.21881,1.00136l25.6001,9.29375A19.37209,19.37209,0,0,0,770.66217,347.522Z"
transform="translate(-384.54297 -170.14522)" fill="#3f3d56"/>
<path
d="M403.66217,180.522,416.457,170.28854c-9.93976-1.09662-14.0238,4.32429-15.69525,8.615-7.76532-3.22446-16.21881,1.00136-16.21881,1.00136l25.6001,9.29375A19.37209,19.37209,0,0,0,403.66217,180.522Z"
transform="translate(-384.54297 -170.14522)" fill="#3f3d56"/>
<path
d="M802.66217,215.522,815.457,205.28854c-9.93976-1.09662-14.0238,4.32429-15.69525,8.615-7.76532-3.22446-16.21881,1.00136-16.21881,1.00136l25.6001,9.29375A19.37209,19.37209,0,0,0,802.66217,215.522Z"
transform="translate(-384.54297 -170.14522)" fill="#3f3d56"/>
</svg>

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -1,92 +1,92 @@
export const FA_DATATABLE_LOCALIZATION = { export const FA_DATATABLE_LOCALIZATION = {
actions: "Actions", actions: "Actions",
and: "and", and: "and",
cancel: "Cancel", cancel: "Cancel",
changeFilterMode: "Change filter mode", changeFilterMode: "Change filter mode",
changeSearchMode: "Change search mode", changeSearchMode: "Change search mode",
clearFilter: "Clear filter", clearFilter: "Clear filter",
clearSearch: "Clear search", clearSearch: "Clear search",
clearSort: "Clear sort", clearSort: "Clear sort",
clickToCopy: "Click to copy", clickToCopy: "Click to copy",
collapse: "Collapse", collapse: "Collapse",
collapseAll: "Collapse all", collapseAll: "Collapse all",
columnActions: "Column Actions", columnActions: "Column Actions",
copiedToClipboard: "Copied to clipboard", copiedToClipboard: "Copied to clipboard",
dropToGroupBy: "Drop to group by {column}", dropToGroupBy: "Drop to group by {column}",
edit: "Edit", edit: "Edit",
expand: "Expand", expand: "Expand",
expandAll: "Expand all", expandAll: "Expand all",
filterArrIncludes: "Includes", filterArrIncludes: "Includes",
filterArrIncludesAll: "Includes all", filterArrIncludesAll: "Includes all",
filterArrIncludesSome: "Includes", filterArrIncludesSome: "Includes",
filterBetween: "Between", filterBetween: "Between",
filterBetweenInclusive: "Between Inclusive", filterBetweenInclusive: "Between Inclusive",
filterByColumn: "Filter by {column}", filterByColumn: "Filter by {column}",
filterContains: "Contains", filterContains: "Contains",
filterEmpty: "Empty", filterEmpty: "Empty",
filterEndsWith: "Ends With", filterEndsWith: "Ends With",
filterEquals: "Equals", filterEquals: "Equals",
filterEqualsString: "Equals", filterEqualsString: "Equals",
filterFuzzy: "Fuzzy", filterFuzzy: "Fuzzy",
filterGreaterThan: "Greater Than", filterGreaterThan: "Greater Than",
filterGreaterThanOrEqualTo: "Greater Than Or Equal To", filterGreaterThanOrEqualTo: "Greater Than Or Equal To",
filterInNumberRange: "Between", filterInNumberRange: "Between",
filterIncludesString: "Contains", filterIncludesString: "Contains",
filterIncludesStringSensitive: "Contains", filterIncludesStringSensitive: "Contains",
filterLessThan: "Less Than", filterLessThan: "Less Than",
filterLessThanOrEqualTo: "Less Than Or Equal To", filterLessThanOrEqualTo: "Less Than Or Equal To",
filterMode: "Filter Mode: {filterType}", filterMode: "Filter Mode: {filterType}",
filterNotEmpty: "Not Empty", filterNotEmpty: "Not Empty",
filterNotEquals: "Not Equals", filterNotEquals: "Not Equals",
filterStartsWith: "Starts With", filterStartsWith: "Starts With",
filterWeakEquals: "Equals", filterWeakEquals: "Equals",
filteringByColumn: "Filtering by {column} - {filterType} {filterValue}", filteringByColumn: "Filtering by {column} - {filterType} {filterValue}",
goToFirstPage: "Go to first page", goToFirstPage: "Go to first page",
goToLastPage: "Go to last page", goToLastPage: "Go to last page",
goToNextPage: "Go to next page", goToNextPage: "Go to next page",
goToPreviousPage: "Go to previous page", goToPreviousPage: "Go to previous page",
grab: "Grab", grab: "Grab",
groupByColumn: "Group by {column}", groupByColumn: "Group by {column}",
groupedBy: "Grouped by ", groupedBy: "Grouped by ",
hideAll: "Hide all", hideAll: "Hide all",
hideColumn: "Hide {column} column", hideColumn: "Hide {column} column",
max: "Max", max: "Max",
min: "Min", min: "Min",
move: "Move", move: "Move",
noRecordsToDisplay: "No records to display", noRecordsToDisplay: "No records to display",
noResultsFound: "No results found", noResultsFound: "No results found",
of: "of", of: "of",
or: "or", or: "or",
pinToLeft: "Pin to left", pinToLeft: "Pin to left",
pinToRight: "Pin to right", pinToRight: "Pin to right",
resetColumnSize: "Reset column size", resetColumnSize: "Reset column size",
resetOrder: "Reset order", resetOrder: "Reset order",
rowActions: "Row Actions", rowActions: "Row Actions",
rowNumber: "#", rowNumber: "#",
rowNumbers: "Row Numbers", rowNumbers: "Row Numbers",
rowsPerPage: "Rows per page", rowsPerPage: "Rows per page",
save: "Save", save: "Save",
search: "Search", search: "Search",
selectedCountOfRowCountRowsSelected: selectedCountOfRowCountRowsSelected:
"{selectedCount} of {rowCount} row(s) selected", "{selectedCount} of {rowCount} row(s) selected",
select: "Select", select: "Select",
showAll: "Show all", showAll: "Show all",
showAllColumns: "Show all columns", showAllColumns: "Show all columns",
showHideColumns: "Show/Hide columns", showHideColumns: "Show/Hide columns",
showHideFilters: "Show/Hide filters", showHideFilters: "Show/Hide filters",
showHideSearch: "Show/Hide search", showHideSearch: "Show/Hide search",
sortByColumnAsc: "Sort by {column} ascending", sortByColumnAsc: "Sort by {column} ascending",
sortByColumnDesc: "Sort by {column} descending", sortByColumnDesc: "Sort by {column} descending",
sortedByColumnAsc: "Sorted by {column} ascending", sortedByColumnAsc: "Sorted by {column} ascending",
sortedByColumnDesc: "Sorted by {column} descending", sortedByColumnDesc: "Sorted by {column} descending",
thenBy: ", then by ", thenBy: ", then by ",
toggleDensity: "Toggle density", toggleDensity: "Toggle density",
toggleFullScreen: "Toggle full screen", toggleFullScreen: "Toggle full screen",
toggleSelectAll: "Toggle select all", toggleSelectAll: "Toggle select all",
toggleSelectRow: "Toggle select row", toggleSelectRow: "Toggle select row",
toggleVisibility: "Toggle visibility", toggleVisibility: "Toggle visibility",
ungroupByColumn: "Ungroup by {column}", ungroupByColumn: "Ungroup by {column}",
unpin: "Unpin", unpin: "Unpin",
unpinAll: "Unpin all", unpinAll: "Unpin all",
unsorted: "Unsorted", unsorted: "Unsorted",
}; };

View File

@@ -1,7 +1,7 @@
import DashboardLayouts from "@/layouts/dashboardLayouts"; import DashboardLayouts from "@/layouts/dashboardLayouts";
const DashboardFirstComponent = () => { const DashboardFirstComponent = () => {
return <DashboardLayouts></DashboardLayouts>; return <DashboardLayouts></DashboardLayouts>;
}; };
export default DashboardFirstComponent; export default DashboardFirstComponent;

View File

@@ -2,121 +2,122 @@ import DashboardLayouts from "@/layouts/dashboardLayouts";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
import { import {
Avatar, Card, Avatar,
CardActions, Card,
CardContent, CardActions,
CardHeader, CardContent,
Collapse, CardHeader,
Grid, Collapse,
IconButton, Grid,
Stack, IconButton,
Typography Stack,
Typography
} from "@mui/material"; } from "@mui/material";
import { styled } from "@mui/material/styles"; import {styled} from "@mui/material/styles";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import { useState } from "react"; import {useState} from "react";
const ExpandMore = styled((props) => { const ExpandMore = styled((props) => {
const { expand, ...other } = props; const {expand, ...other} = props;
return <IconButton {...other} />; return <IconButton {...other} />;
})(({ theme, expand }) => ({ })(({theme, expand}) => ({
transform: !expand ? "rotate(0deg)" : "rotate(180deg)", transform: !expand ? "rotate(0deg)" : "rotate(180deg)",
marginLeft: "auto", marginLeft: "auto",
transition: theme.transitions.create("transform", { transition: theme.transitions.create("transform", {
duration: theme.transitions.duration.shortest, duration: theme.transitions.duration.shortest,
}), }),
})); }));
const data = [ const data = [
{ {
name: "جان دو", name: "جان دو",
date: "۱۳۹۹/۰۴/۲۵", date: "۱۳۹۹/۰۴/۲۵",
description: description:
"لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.", "لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است.",
}, },
{ {
name: "جین اسمیت", name: "جین اسمیت",
date: "۱۳۹۹/۰۴/۲۶", date: "۱۳۹۹/۰۴/۲۶",
description: "نُلا ویته الیت لیبرو آ، آ فارِترا آوگوه.", description: "نُلا ویته الیت لیبرو آ، آ فارِترا آوگوه.",
}, },
{ {
name: "مایک جانسون", name: "مایک جانسون",
date: "۱۳۹۹/۰۴/۲۷", date: "۱۳۹۹/۰۴/۲۷",
description: description:
"دوئیس مولیس، است نُن کُمُدو لُکتوس، نیسی ارات پورتیتور لیگولا.", "دوئیس مولیس، است نُن کُمُدو لُکتوس، نیسی ارات پورتیتور لیگولا.",
}, },
]; ];
const DashboardLoanFollowUpComponent = () => { const DashboardLoanFollowUpComponent = () => {
const t = useTranslations(); const t = useTranslations();
const { token } = useUser(); const {token} = useUser();
const [expanded, setExpanded] = useState([]); const [expanded, setExpanded] = useState([]);
const handleExpandClick = (index) => { const handleExpandClick = (index) => {
setExpanded((prevExpanded) => { setExpanded((prevExpanded) => {
const newExpanded = [...prevExpanded]; const newExpanded = [...prevExpanded];
newExpanded[index] = !newExpanded[index]; newExpanded[index] = !newExpanded[index];
return newExpanded; return newExpanded;
}); });
}; };
return ( return (
<DashboardLayouts> <DashboardLayouts>
<Stack <Stack
spacing={2} spacing={2}
sx={{ sx={{
p: 4, p: 4,
width: "100%", width: "100%",
}} }}
> >
<Grid <Grid
container container
columnSpacing={2} columnSpacing={2}
rowSpacing={2} rowSpacing={2}
sx={{ alignItems: "start", justifyContent: "center" }} sx={{alignItems: "start", justifyContent: "center"}}
> >
{data.map((item, index) => ( {data.map((item, index) => (
<Grid item xs={12} md={6} lg={4} key={index}> <Grid item xs={12} md={6} lg={4} key={index}>
<Card sx={{ width: "100%" }}> <Card sx={{width: "100%"}}>
<CardHeader <CardHeader
avatar={ avatar={
<Avatar <Avatar
sx={{ bgcolor: "primary.main" }} sx={{bgcolor: "primary.main"}}
aria-label="recipe" aria-label="recipe"
></Avatar> ></Avatar>
} }
title={item.name} title={item.name}
subheader={item.date} subheader={item.date}
/> />
<CardContent> <CardContent>
<Typography variant="body2" color="text.secondary"> <Typography variant="body2" color="text.secondary">
متن تست متن تست
</Typography> </Typography>
</CardContent> </CardContent>
<CardActions disableSpacing> <CardActions disableSpacing>
<ExpandMore <ExpandMore
expand={expanded[index]} expand={expanded[index]}
onClick={() => handleExpandClick(index)} onClick={() => handleExpandClick(index)}
aria-expanded={expanded[index]} aria-expanded={expanded[index]}
aria-label="show more" aria-label="show more"
> >
<ExpandMoreIcon /> <ExpandMoreIcon/>
</ExpandMore> </ExpandMore>
</CardActions> </CardActions>
<Collapse in={expanded[index]} timeout="auto" unmountOnExit> <Collapse in={expanded[index]} timeout="auto" unmountOnExit>
<CardContent> <CardContent>
<Typography paragraph>اطلاعات تکمیلی:</Typography> <Typography paragraph>اطلاعات تکمیلی:</Typography>
<Typography paragraph>{item.description}</Typography> <Typography paragraph>{item.description}</Typography>
</CardContent> </CardContent>
</Collapse> </Collapse>
</Card> </Card>
</Grid> </Grid>
))} ))}
</Grid> </Grid>
</Stack> </Stack>
</DashboardLayouts> </DashboardLayouts>
); );
}; };
export default DashboardLoanFollowUpComponent; export default DashboardLoanFollowUpComponent;

View File

@@ -2,490 +2,487 @@ import Notifications from "@/core/components/notifications";
import SelectBox from "@/core/components/SelectBox"; import SelectBox from "@/core/components/SelectBox";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
import UploadSystem from "@/core/components/UploadSystem"; import UploadSystem from "@/core/components/UploadSystem";
import { import {GET_PROVINCE_LIST, SEND_LOAN_REQUEST_NAVGAN,} from "@/core/data/apiRoutes";
GET_PROVINCE_LIST,
SEND_LOAN_REQUEST_NAVGAN,
} from "@/core/data/apiRoutes";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn"; import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
import { Box, Button, Stack, TextField } from "@mui/material"; import {Box, Button, Stack, TextField} from "@mui/material";
import axios from "axios"; import axios from "axios";
import { Field, Formik } from "formik"; import {Field, Formik} from "formik";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import { useEffect, useState } from "react"; import {useEffect, useState} from "react";
import * as Yup from "yup"; import * as Yup from "yup";
const NavyForm = () => { const NavyForm = () => {
const t = useTranslations(); const t = useTranslations();
const { directionApp } = useDirection(); const {directionApp} = useDirection();
const { token } = useUser(); const {token} = useUser();
// get province list // get province list
const [provinceList, setProvinceList] = useState([]); const [provinceList, setProvinceList] = useState([]);
useEffect(() => { useEffect(() => {
axios axios
.get(GET_PROVINCE_LIST, { .get(GET_PROVINCE_LIST, {
headers: { Authorization: `Bearer ${token}` }, headers: {Authorization: `Bearer ${token}`},
}) })
.then(({ data }) => { .then(({data}) => {
const formattedData = data.map((province, index) => ({ const formattedData = data.map((province, index) => ({
id: index, id: index,
name: province.name, name: province.name,
value: province.id, value: province.id,
})); }));
setProvinceList(formattedData); setProvinceList(formattedData);
}) })
.catch((error) => { .catch((error) => {
Notifications(directionApp, t, error.response); Notifications(directionApp, t, error.response);
}); });
}, []); }, []);
// end get province list // end get province list
// upload files // upload files
const [selectedImageShenasname, setSelectedImageShenasname] = useState( const [selectedImageShenasname, setSelectedImageShenasname] = useState(
"/images/upload-image.svg" "/images/upload-image.svg"
); );
const [fileTypeShenasname, setFileTypeShenasname] = useState(null); const [fileTypeShenasname, setFileTypeShenasname] = useState(null);
const [fileNameShenasname, setFileNameShenasname] = useState(null); const [fileNameShenasname, setFileNameShenasname] = useState(null);
const [selectedImageNationalCard, setSelectedImageNationalCard] = useState( const [selectedImageNationalCard, setSelectedImageNationalCard] = useState(
"/images/upload-image.svg" "/images/upload-image.svg"
); );
const [fileTypeNationalCard, setFileTypeNationalCard] = useState(null); const [fileTypeNationalCard, setFileTypeNationalCard] = useState(null);
const [fileNameNationalCard, setFileNameNationalCard] = useState(null); const [fileNameNationalCard, setFileNameNationalCard] = useState(null);
const handleUploadChangeShenasname = (event, setFieldValue) => { const handleUploadChangeShenasname = (event, setFieldValue) => {
const uploadedFile = event.target?.files?.[0]; const uploadedFile = event.target?.files?.[0];
if (uploadedFile) { if (uploadedFile) {
const fileType = event.target?.files?.[0].type; const fileType = event.target?.files?.[0].type;
const fileName = event.target?.files?.[0].name; const fileName = event.target?.files?.[0].name;
setSelectedImageShenasname(URL.createObjectURL(uploadedFile)); setSelectedImageShenasname(URL.createObjectURL(uploadedFile));
setFileTypeShenasname(fileType); setFileTypeShenasname(fileType);
setFileNameShenasname(fileName); setFileNameShenasname(fileName);
setFieldValue("shenasname_img", uploadedFile); setFieldValue("shenasname_img", uploadedFile);
} }
}; };
const handleUploadChangeNationalCard = (event, setFieldValue) => { const handleUploadChangeNationalCard = (event, setFieldValue) => {
const uploadedFile = event.target?.files?.[0]; const uploadedFile = event.target?.files?.[0];
const fileType = event.target.files[0].type; const fileType = event.target.files[0].type;
const fileName = event.target.files[0].name; const fileName = event.target.files[0].name;
if (uploadedFile) { if (uploadedFile) {
setSelectedImageNationalCard(URL.createObjectURL(uploadedFile)); setSelectedImageNationalCard(URL.createObjectURL(uploadedFile));
setFileTypeNationalCard(fileType); setFileTypeNationalCard(fileType);
setFileNameNationalCard(fileName); setFileNameNationalCard(fileName);
setFieldValue("national_card_img", uploadedFile); setFieldValue("national_card_img", uploadedFile);
} }
}; };
// end upload files // end upload files
// initial values // initial values
const initialValues = { const initialValues = {
name: "", name: "",
phone_number: "", phone_number: "",
vehicle_type: "", vehicle_type: "",
plate_number: "", plate_number: "",
province: "", province: "",
navgan_id: "", navgan_id: "",
national_code: "", national_code: "",
shenasname_id: "", shenasname_id: "",
national_card_img: null, national_card_img: null,
shenasname_img: null, shenasname_img: null,
}; };
// end initial values // end initial values
// validation // validation
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
name: Yup.string().required(t("LoanRequest.error_message_required")), name: Yup.string().required(t("LoanRequest.error_message_required")),
phone_number: Yup.string().required( phone_number: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
vehicle_type: Yup.string().required( vehicle_type: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
plate_number: Yup.string().required( plate_number: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
navgan_id: Yup.string().required(t("LoanRequest.error_message_required")), navgan_id: Yup.string().required(t("LoanRequest.error_message_required")),
province: Yup.string().required(t("LoanRequest.error_message_required")), province: Yup.string().required(t("LoanRequest.error_message_required")),
national_code: Yup.string().required( national_code: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
shenasname_id: Yup.string().required( shenasname_id: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
}); });
// end validation // end validation
// submit // submit
const handleSubmit = async (values, props) => { const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined); Notifications(directionApp, t, undefined);
const formData = new FormData(); const formData = new FormData();
formData.append("name", values.name); formData.append("name", values.name);
formData.append("phone_number", values.phone_number); formData.append("phone_number", values.phone_number);
formData.append("vehicle_type", values.vehicle_type); formData.append("vehicle_type", values.vehicle_type);
formData.append("plate_number", values.plate_number); formData.append("plate_number", values.plate_number);
formData.append("province_id", values.province); formData.append("province_id", values.province);
formData.append("navgan_id", values.navgan_id); formData.append("navgan_id", values.navgan_id);
formData.append("national_code", values.national_code); formData.append("national_code", values.national_code);
formData.append("shenasname_id", values.shenasname_id); formData.append("shenasname_id", values.shenasname_id);
if (values.shenasname_img != null) if (values.shenasname_img != null)
formData.append("shenasname_image", values.shenasname_img); formData.append("shenasname_image", values.shenasname_img);
if (values.national_card_img != null) if (values.national_card_img != null)
formData.append("national_card_image", values.national_card_img); formData.append("national_card_image", values.national_card_img);
await axios await axios
.post(SEND_LOAN_REQUEST_NAVGAN, formData, { .post(SEND_LOAN_REQUEST_NAVGAN, formData, {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
"Content-Type": "multipart/form-data", "Content-Type": "multipart/form-data",
}, },
}) })
.then(function (response) { .then(function (response) {
Notifications(directionApp, t, response); Notifications(directionApp, t, response);
}) })
.catch(function (error) { .catch(function (error) {
Notifications(directionApp, t, error.response); Notifications(directionApp, t, error.response);
props.setSubmitting(false); props.setSubmitting(false);
}); });
}; };
// end submit // end submit
return ( return (
<Formik <Formik
initialValues={initialValues} initialValues={initialValues}
onSubmit={handleSubmit} onSubmit={handleSubmit}
validationSchema={validationSchema} validationSchema={validationSchema}
>
{(props) => (
<Stack
spacing={2}
sx={{
p: 1,
width: "100%",
}}
> >
<StyledForm sx={{ width: "100%" }}> {(props) => (
<Box <Stack
sx={{ spacing={2}
display: "flex", sx={{
flexDirection: { xs: "column", sm: "row" }, p: 1,
alignItems: "start", width: "100%",
justifyContent: "center", }}
width: "100%", >
}} <StyledForm sx={{width: "100%"}}>
> <Box
<Box sx={{
sx={{ display: "flex",
mx: { xs: 0, sm: 2 }, flexDirection: {xs: "column", sm: "row"},
my: 2, alignItems: "start",
width: "100%", justifyContent: "center",
}} width: "100%",
> }}
<Field >
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="name" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_name")} }}
placeholder={t("LoanRequest.text_field_enter_your_name")} >
type={"text"} <Field
error={props.touched.name && props.errors.name ? true : false} as={TextField}
fullWidth sx={{width: "100%"}}
helperText={props.touched.name ? props.errors.name : null} name="name"
/> variant="outlined"
</Box> size="small"
<Box label={t("LoanRequest.text_field_name")}
sx={{ placeholder={t("LoanRequest.text_field_enter_your_name")}
mx: { xs: 0, sm: 2 }, type={"text"}
my: 2, error={props.touched.name && props.errors.name ? true : false}
width: "100%", fullWidth
}} helperText={props.touched.name ? props.errors.name : null}
> />
<Field </Box>
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="phone_number" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_phone_number")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_phone_number" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="phone_number"
props.touched.phone_number && props.errors.phone_number variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_phone_number")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_phone_number"
helperText={ )}
props.touched.phone_number type={"text"}
? props.errors.phone_number error={
: null props.touched.phone_number && props.errors.phone_number
} ? true
/> : false
</Box> }
</Box> fullWidth
<Box helperText={
sx={{ props.touched.phone_number
display: "flex", ? props.errors.phone_number
flexDirection: { xs: "column", sm: "row" }, : null
alignItems: "start", }
justifyContent: "center", />
width: "100%", </Box>
}} </Box>
> <Box
<Box sx={{
sx={{ display: "flex",
mx: { xs: 0, sm: 2 }, flexDirection: {xs: "column", sm: "row"},
my: 2, alignItems: "start",
width: "100%", justifyContent: "center",
}} width: "100%",
> }}
<Field >
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="vehicle_type" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_vehicle_type")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_vehicle_type" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="vehicle_type"
props.touched.vehicle_type && props.errors.vehicle_type variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_vehicle_type")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_vehicle_type"
helperText={ )}
props.touched.vehicle_type type={"text"}
? props.errors.vehicle_type error={
: null props.touched.vehicle_type && props.errors.vehicle_type
} ? true
/> : false
</Box> }
<Box fullWidth
sx={{ helperText={
mx: { xs: 0, sm: 2 }, props.touched.vehicle_type
my: 2, ? props.errors.vehicle_type
width: "100%", : null
}} }
> />
<Field </Box>
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="plate_number" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_plate_number")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_plate_number" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="plate_number"
props.touched.plate_number && props.errors.plate_number variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_plate_number")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_plate_number"
helperText={ )}
props.touched.plate_number type={"text"}
? props.errors.plate_number error={
: null props.touched.plate_number && props.errors.plate_number
} ? true
/> : false
</Box> }
<Box fullWidth
sx={{ helperText={
mx: { xs: 0, sm: 2 }, props.touched.plate_number
my: 2, ? props.errors.plate_number
width: "100%", : null
}} }
> />
<Field </Box>
name="province" <Box
label={t("LoanRequest.text_field_province")} // t("LoanRequest.text_field_enter_your_province") sx={{
size="small" mx: {xs: 0, sm: 2},
selectType="province" my: 2,
component={SelectBox} width: "100%",
selectors={provinceList} }}
select={props.values.province} >
setFieldValue={props.setFieldValue} <Field
setFieldTouched={props.setFieldTouched} name="province"
error={ label={t("LoanRequest.text_field_province")} // t("LoanRequest.text_field_enter_your_province")
props.touched.gender && props.errors.province ? true : false size="small"
} selectType="province"
helperText={ component={SelectBox}
props.touched.gender ? props.errors.province : null selectors={provinceList}
} select={props.values.province}
/> setFieldValue={props.setFieldValue}
</Box> setFieldTouched={props.setFieldTouched}
</Box> error={
<Box props.touched.gender && props.errors.province ? true : false
sx={{ }
display: "flex", helperText={
flexDirection: { xs: "column", sm: "row" }, props.touched.gender ? props.errors.province : null
alignItems: "start", }
justifyContent: "center", />
width: "100%", </Box>
}} </Box>
> <Box
<Box sx={{
sx={{ display: "flex",
mx: { xs: 0, sm: 2 }, flexDirection: {xs: "column", sm: "row"},
my: 2, alignItems: "start",
width: "100%", justifyContent: "center",
}} width: "100%",
> }}
<Field >
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="navgan_id" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_navgan_id")} }}
placeholder={t("LoanRequest.text_field_enter_your_navgan_id")} >
type={"text"} <Field
error={ as={TextField}
props.touched.navgan_id && props.errors.navgan_id sx={{width: "100%"}}
? true name="navgan_id"
: false variant="outlined"
} size="small"
fullWidth label={t("LoanRequest.text_field_navgan_id")}
helperText={ placeholder={t("LoanRequest.text_field_enter_your_navgan_id")}
props.touched.navgan_id ? props.errors.navgan_id : null type={"text"}
} error={
/> props.touched.navgan_id && props.errors.navgan_id
</Box> ? true
<Box : false
sx={{ }
mx: { xs: 0, sm: 2 }, fullWidth
my: 2, helperText={
width: "100%", props.touched.navgan_id ? props.errors.navgan_id : null
}} }
> />
<Field </Box>
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="national_code" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_national_code")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_national_code" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="national_code"
props.touched.national_code && props.errors.national_code variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_national_code")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_national_code"
helperText={ )}
props.touched.national_code type={"text"}
? props.errors.national_code error={
: null props.touched.national_code && props.errors.national_code
} ? true
/> : false
</Box> }
<Box fullWidth
sx={{ helperText={
mx: { xs: 0, sm: 2 }, props.touched.national_code
my: 2, ? props.errors.national_code
width: "100%", : null
}} }
> />
<Field </Box>
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="shenasname_id" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_shenasname_id")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_shenasname_id" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="shenasname_id"
props.touched.shenasname_id && props.errors.shenasname_id variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_shenasname_id")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_shenasname_id"
helperText={ )}
props.touched.shenasname_id type={"text"}
? props.errors.shenasname_id error={
: null props.touched.shenasname_id && props.errors.shenasname_id
} ? true
/> : false
</Box> }
</Box> fullWidth
<Box helperText={
sx={{ props.touched.shenasname_id
display: "flex", ? props.errors.shenasname_id
flexDirection: { xs: "column", sm: "row" }, : null
alignItems: "center", }
justifyContent: "space-around", />
width: "100%", </Box>
}} </Box>
> <Box
<UploadSystem sx={{
selectedImage={selectedImageShenasname} display: "flex",
handleUploadChange={(e) => flexDirection: {xs: "column", sm: "row"},
handleUploadChangeShenasname(e, props.setFieldValue) alignItems: "center",
} justifyContent: "space-around",
setselectedImage={setSelectedImageShenasname} width: "100%",
setFieldValue={props.setFieldValue} }}
fieldname="shenasname_img" >
fileType={fileTypeShenasname} <UploadSystem
fileName={fileNameShenasname} selectedImage={selectedImageShenasname}
imageAlt={t("app_name")} handleUploadChange={(e) =>
imageSize={[300 /*width*/, 150 /*height*/]} handleUploadChangeShenasname(e, props.setFieldValue)
label={t("LoanRequest.file_field_shenasname_image")} }
/> setselectedImage={setSelectedImageShenasname}
<UploadSystem setFieldValue={props.setFieldValue}
selectedImage={selectedImageNationalCard} fieldname="shenasname_img"
handleUploadChange={(e) => fileType={fileTypeShenasname}
handleUploadChangeNationalCard(e, props.setFieldValue) fileName={fileNameShenasname}
} imageAlt={t("app_name")}
setselectedImage={setSelectedImageNationalCard} imageSize={[300 /*width*/, 150 /*height*/]}
setFieldValue={props.setFieldValue} label={t("LoanRequest.file_field_shenasname_image")}
fieldname="national_card_img" />
fileType={fileTypeNationalCard} <UploadSystem
fileName={fileNameNationalCard} selectedImage={selectedImageNationalCard}
imageAlt={t("app_name")} handleUploadChange={(e) =>
imageSize={[300 /*width*/, 150 /*height*/]} handleUploadChangeNationalCard(e, props.setFieldValue)
label={t("LoanRequest.file_field_national_card_image")} }
/> setselectedImage={setSelectedImageNationalCard}
</Box> setFieldValue={props.setFieldValue}
<Box fieldname="national_card_img"
sx={{ fileType={fileTypeNationalCard}
display: "flex", fileName={fileNameNationalCard}
flexDirection: { xs: "column", sm: "row" }, imageAlt={t("app_name")}
alignItems: "center", imageSize={[300 /*width*/, 150 /*height*/]}
mx: "auto", label={t("LoanRequest.file_field_national_card_image")}
width: { xs: "100%", sm: "30%", md: "25%" }, />
}} </Box>
> <Box
<Button sx={{
fullWidth display: "flex",
type="submit" flexDirection: {xs: "column", sm: "row"},
variant="contained" alignItems: "center",
size="large" mx: "auto",
endIcon={<DataSaverOnIcon />} width: {xs: "100%", sm: "30%", md: "25%"},
disabled={props.isSubmitting ? true : false} }}
> >
{t("LoanRequest.button_submit")} <Button
</Button> fullWidth
</Box> type="submit"
</StyledForm> variant="contained"
</Stack> size="large"
)} endIcon={<DataSaverOnIcon/>}
</Formik> disabled={props.isSubmitting ? true : false}
); >
{t("LoanRequest.button_submit")}
</Button>
</Box>
</StyledForm>
</Stack>
)}
</Formik>
);
}; };
export default NavyForm; export default NavyForm;

View File

@@ -1,435 +1,435 @@
import Notifications from "@/core/components/notifications"; import Notifications from "@/core/components/notifications";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
import UploadSystem from "@/core/components/UploadSystem"; import UploadSystem from "@/core/components/UploadSystem";
import { SEND_LOAN_REQUEST_WELFARE } from "@/core/data/apiRoutes"; import {SEND_LOAN_REQUEST_WELFARE} from "@/core/data/apiRoutes";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn"; import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
import { Box, Button, Stack, TextField } from "@mui/material"; import {Box, Button, Stack, TextField} from "@mui/material";
import axios from "axios"; import axios from "axios";
import { Field, Formik } from "formik"; import {Field, Formik} from "formik";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import { useState } from "react"; import {useState} from "react";
import * as Yup from "yup"; import * as Yup from "yup";
const WelfareServicesForm = () => { const WelfareServicesForm = () => {
const t = useTranslations(); const t = useTranslations();
const { directionApp } = useDirection(); const {directionApp} = useDirection();
const { token } = useUser(); const {token} = useUser();
// upload files // upload files
const [selectedImageShenasname, setSelectedImageShenasname] = useState( const [selectedImageShenasname, setSelectedImageShenasname] = useState(
"/images/upload-image.svg" "/images/upload-image.svg"
); );
const [fileTypeShenasname, setFileTypeShenasname] = useState(null); const [fileTypeShenasname, setFileTypeShenasname] = useState(null);
const [fileNameShenasname, setFileNameShenasname] = useState(null); const [fileNameShenasname, setFileNameShenasname] = useState(null);
const [selectedImageNationalCard, setSelectedImageNationalCard] = useState( const [selectedImageNationalCard, setSelectedImageNationalCard] = useState(
"/images/upload-image.svg" "/images/upload-image.svg"
); );
const [fileTypeNationalCard, setFileTypeNationalCard] = useState(null); const [fileTypeNationalCard, setFileTypeNationalCard] = useState(null);
const [fileNameNationalCard, setFileNameNationalCard] = useState(null); const [fileNameNationalCard, setFileNameNationalCard] = useState(null);
const handleUploadChangeShenasname = (event, setFieldValue) => { const handleUploadChangeShenasname = (event, setFieldValue) => {
const uploadedFile = event.target?.files?.[0]; const uploadedFile = event.target?.files?.[0];
if (uploadedFile) { if (uploadedFile) {
const fileType = event.target?.files?.[0].type; const fileType = event.target?.files?.[0].type;
const fileName = event.target?.files?.[0].name; const fileName = event.target?.files?.[0].name;
setSelectedImageShenasname(URL.createObjectURL(uploadedFile)); setSelectedImageShenasname(URL.createObjectURL(uploadedFile));
setFileTypeShenasname(fileType); setFileTypeShenasname(fileType);
setFileNameShenasname(fileName); setFileNameShenasname(fileName);
setFieldValue("shenasname_img", uploadedFile); setFieldValue("shenasname_img", uploadedFile);
} }
}; };
const handleUploadChangeNationalCard = (event, setFieldValue) => { const handleUploadChangeNationalCard = (event, setFieldValue) => {
const uploadedFile = event.target?.files?.[0]; const uploadedFile = event.target?.files?.[0];
const fileType = event.target.files[0].type; const fileType = event.target.files[0].type;
const fileName = event.target.files[0].name; const fileName = event.target.files[0].name;
if (uploadedFile) { if (uploadedFile) {
setSelectedImageNationalCard(URL.createObjectURL(uploadedFile)); setSelectedImageNationalCard(URL.createObjectURL(uploadedFile));
setFileTypeNationalCard(fileType); setFileTypeNationalCard(fileType);
setFileNameNationalCard(fileName); setFileNameNationalCard(fileName);
setFieldValue("national_card_img", uploadedFile); setFieldValue("national_card_img", uploadedFile);
} }
}; };
// end upload files // end upload files
// initial values, validation and request action of form // initial values, validation and request action of form
const initialValues = { const initialValues = {
name: "", name: "",
phone_number: "", phone_number: "",
vehicle_type: "", vehicle_type: "",
plate_number: "", plate_number: "",
province: "", province: "",
national_code: "", national_code: "",
shenasname_id: "", shenasname_id: "",
national_card_img: null, national_card_img: null,
shenasname_img: null, shenasname_img: null,
}; };
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
name: Yup.string().required(t("LoanRequest.error_message_required")), name: Yup.string().required(t("LoanRequest.error_message_required")),
phone_number: Yup.string().required( phone_number: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
vehicle_type: Yup.string().required( vehicle_type: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
plate_number: Yup.string().required( plate_number: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
province: Yup.string().required(t("LoanRequest.error_message_required")), province: Yup.string().required(t("LoanRequest.error_message_required")),
national_code: Yup.string().required( national_code: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
shenasname_id: Yup.string().required( shenasname_id: Yup.string().required(
t("LoanRequest.error_message_required") t("LoanRequest.error_message_required")
), ),
}); });
const handleSubmit = async (values, props) => { const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined); Notifications(directionApp, t, undefined);
const formData = new FormData(); const formData = new FormData();
formData.append("name", values.name); formData.append("name", values.name);
formData.append("phone_number", values.phone_number); formData.append("phone_number", values.phone_number);
formData.append("vehicle_type", values.vehicle_type); formData.append("vehicle_type", values.vehicle_type);
formData.append("plate_number", values.plate_number); formData.append("plate_number", values.plate_number);
formData.append("province_id", values.province); formData.append("province_id", values.province);
formData.append("national_code", values.national_code); formData.append("national_code", values.national_code);
formData.append("shenasname_id", values.shenasname_id); formData.append("shenasname_id", values.shenasname_id);
if (values.shenasname_img != null) if (values.shenasname_img != null)
formData.append("shenasname_image", values.shenasname_img); formData.append("shenasname_image", values.shenasname_img);
if (values.national_card_img != null) if (values.national_card_img != null)
formData.append("national_card_image", values.national_card_img); formData.append("national_card_image", values.national_card_img);
await axios await axios
.post(SEND_LOAN_REQUEST_WELFARE, formData, { .post(SEND_LOAN_REQUEST_WELFARE, formData, {
headers: { headers: {
Authorization: `Bearer ${token}`, Authorization: `Bearer ${token}`,
"Content-Type": "multipart/form-data", "Content-Type": "multipart/form-data",
}, },
}) })
.then(function (response) { .then(function (response) {
Notifications(directionApp, t, response); Notifications(directionApp, t, response);
}) })
.catch(function (error) { .catch(function (error) {
Notifications(directionApp, t, error.response); Notifications(directionApp, t, error.response);
props.setSubmitting(false); props.setSubmitting(false);
}); });
}; };
// end initial values, validation and request action of form // end initial values, validation and request action of form
return ( return (
<Formik <Formik
initialValues={initialValues} initialValues={initialValues}
onSubmit={handleSubmit} onSubmit={handleSubmit}
validationSchema={validationSchema} validationSchema={validationSchema}
>
{(props) => (
<Stack
spacing={2}
sx={{
p: 1,
width: "100%",
}}
> >
<StyledForm sx={{ width: "100%" }}> {(props) => (
<Box <Stack
sx={{ spacing={2}
display: "flex", sx={{
flexDirection: { xs: "column", sm: "row" }, p: 1,
alignItems: "start", width: "100%",
justifyContent: "center", }}
width: "100%", >
}} <StyledForm sx={{width: "100%"}}>
> <Box
<Box sx={{
sx={{ display: "flex",
mx: { xs: 0, sm: 2 }, flexDirection: {xs: "column", sm: "row"},
my: 2, alignItems: "start",
width: "100%", justifyContent: "center",
}} width: "100%",
> }}
<Field >
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="name" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_name")} }}
placeholder={t("LoanRequest.text_field_enter_your_name")} >
type={"text"} <Field
error={props.touched.name && props.errors.name ? true : false} as={TextField}
fullWidth sx={{width: "100%"}}
helperText={props.touched.name ? props.errors.name : null} name="name"
/> variant="outlined"
</Box> size="small"
<Box label={t("LoanRequest.text_field_name")}
sx={{ placeholder={t("LoanRequest.text_field_enter_your_name")}
mx: { xs: 0, sm: 2 }, type={"text"}
my: 2, error={props.touched.name && props.errors.name ? true : false}
width: "100%", fullWidth
}} helperText={props.touched.name ? props.errors.name : null}
> />
<Field </Box>
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="phone_number" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_phone_number")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_phone_number" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="phone_number"
props.touched.phone_number && props.errors.phone_number variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_phone_number")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_phone_number"
helperText={ )}
props.touched.phone_number type={"text"}
? props.errors.phone_number error={
: null props.touched.phone_number && props.errors.phone_number
} ? true
/> : false
</Box> }
</Box> fullWidth
<Box helperText={
sx={{ props.touched.phone_number
display: "flex", ? props.errors.phone_number
flexDirection: { xs: "column", sm: "row" }, : null
alignItems: "start", }
justifyContent: "center", />
width: "100%", </Box>
}} </Box>
> <Box
<Box sx={{
sx={{ display: "flex",
mx: { xs: 0, sm: 2 }, flexDirection: {xs: "column", sm: "row"},
my: 2, alignItems: "start",
width: "100%", justifyContent: "center",
}} width: "100%",
> }}
<Field >
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="vehicle_type" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_vehicle_type")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_vehicle_type" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="vehicle_type"
props.touched.vehicle_type && props.errors.vehicle_type variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_vehicle_type")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_vehicle_type"
helperText={ )}
props.touched.vehicle_type type={"text"}
? props.errors.vehicle_type error={
: null props.touched.vehicle_type && props.errors.vehicle_type
} ? true
/> : false
</Box> }
<Box fullWidth
sx={{ helperText={
mx: { xs: 0, sm: 2 }, props.touched.vehicle_type
my: 2, ? props.errors.vehicle_type
width: "100%", : null
}} }
> />
<Field </Box>
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="plate_number" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_plate_number")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_plate_number" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="plate_number"
props.touched.plate_number && props.errors.plate_number variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_plate_number")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_plate_number"
helperText={ )}
props.touched.plate_number type={"text"}
? props.errors.plate_number error={
: null props.touched.plate_number && props.errors.plate_number
} ? true
/> : false
</Box> }
<Box fullWidth
sx={{ helperText={
mx: { xs: 0, sm: 2 }, props.touched.plate_number
my: 2, ? props.errors.plate_number
width: "100%", : null
}} }
> />
<Field </Box>
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="province" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_province")} }}
placeholder={t("LoanRequest.text_field_enter_your_province")} >
type={"text"} <Field
error={ as={TextField}
props.touched.province && props.errors.province sx={{width: "100%"}}
? true name="province"
: false variant="outlined"
} size="small"
fullWidth label={t("LoanRequest.text_field_province")}
helperText={ placeholder={t("LoanRequest.text_field_enter_your_province")}
props.touched.province ? props.errors.province : null type={"text"}
} error={
/> props.touched.province && props.errors.province
</Box> ? true
</Box> : false
<Box }
sx={{ fullWidth
display: "flex", helperText={
flexDirection: { xs: "column", sm: "row" }, props.touched.province ? props.errors.province : null
alignItems: "start", }
justifyContent: "center", />
width: "100%", </Box>
}} </Box>
> <Box
<Box sx={{
sx={{ display: "flex",
mx: { xs: 0, sm: 2 }, flexDirection: {xs: "column", sm: "row"},
my: 2, alignItems: "start",
width: "100%", justifyContent: "center",
}} width: "100%",
> }}
<Field >
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="national_code" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_national_code")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_national_code" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="national_code"
props.touched.national_code && props.errors.national_code variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_national_code")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_national_code"
helperText={ )}
props.touched.national_code type={"text"}
? props.errors.national_code error={
: null props.touched.national_code && props.errors.national_code
} ? true
/> : false
</Box> }
<Box fullWidth
sx={{ helperText={
mx: { xs: 0, sm: 2 }, props.touched.national_code
my: 2, ? props.errors.national_code
width: "100%", : null
}} }
> />
<Field </Box>
as={TextField} <Box
sx={{ width: "100%" }} sx={{
name="shenasname_id" mx: {xs: 0, sm: 2},
variant="outlined" my: 2,
size="small" width: "100%",
label={t("LoanRequest.text_field_shenasname_id")} }}
placeholder={t( >
"LoanRequest.text_field_enter_your_shenasname_id" <Field
)} as={TextField}
type={"text"} sx={{width: "100%"}}
error={ name="shenasname_id"
props.touched.shenasname_id && props.errors.shenasname_id variant="outlined"
? true size="small"
: false label={t("LoanRequest.text_field_shenasname_id")}
} placeholder={t(
fullWidth "LoanRequest.text_field_enter_your_shenasname_id"
helperText={ )}
props.touched.shenasname_id type={"text"}
? props.errors.shenasname_id error={
: null props.touched.shenasname_id && props.errors.shenasname_id
} ? true
/> : false
</Box> }
</Box> fullWidth
<Box helperText={
sx={{ props.touched.shenasname_id
display: "flex", ? props.errors.shenasname_id
flexDirection: { xs: "column", sm: "row" }, : null
alignItems: "center", }
justifyContent: "space-around", />
width: "100%", </Box>
}} </Box>
> <Box
<UploadSystem sx={{
selectedImage={selectedImageShenasname} display: "flex",
handleUploadChange={(e) => flexDirection: {xs: "column", sm: "row"},
handleUploadChangeShenasname(e, props.setFieldValue) alignItems: "center",
} justifyContent: "space-around",
setselectedImage={setSelectedImageShenasname} width: "100%",
setFieldValue={props.setFieldValue} }}
fieldname="shenasname_img" >
fileType={fileTypeShenasname} <UploadSystem
fileName={fileNameShenasname} selectedImage={selectedImageShenasname}
imageAlt={t("app_name")} handleUploadChange={(e) =>
imageSize={[300 /*width*/, 150 /*height*/]} handleUploadChangeShenasname(e, props.setFieldValue)
label={t("LoanRequest.file_field_shenasname_image")} }
/> setselectedImage={setSelectedImageShenasname}
<UploadSystem setFieldValue={props.setFieldValue}
selectedImage={selectedImageNationalCard} fieldname="shenasname_img"
handleUploadChange={(e) => fileType={fileTypeShenasname}
handleUploadChangeNationalCard(e, props.setFieldValue) fileName={fileNameShenasname}
} imageAlt={t("app_name")}
setselectedImage={setSelectedImageNationalCard} imageSize={[300 /*width*/, 150 /*height*/]}
setFieldValue={props.setFieldValue} label={t("LoanRequest.file_field_shenasname_image")}
fieldname="national_card_img" />
fileType={fileTypeNationalCard} <UploadSystem
fileName={fileNameNationalCard} selectedImage={selectedImageNationalCard}
imageAlt={t("app_name")} handleUploadChange={(e) =>
imageSize={[300 /*width*/, 150 /*height*/]} handleUploadChangeNationalCard(e, props.setFieldValue)
label={t("LoanRequest.file_field_national_card_image")} }
/> setselectedImage={setSelectedImageNationalCard}
</Box> setFieldValue={props.setFieldValue}
<Box fieldname="national_card_img"
sx={{ fileType={fileTypeNationalCard}
display: "flex", fileName={fileNameNationalCard}
flexDirection: { xs: "column", sm: "row" }, imageAlt={t("app_name")}
alignItems: "center", imageSize={[300 /*width*/, 150 /*height*/]}
mx: "auto", label={t("LoanRequest.file_field_national_card_image")}
my: 2, />
width: { xs: "100%", sm: "30%", md: "25%" }, </Box>
}} <Box
> sx={{
<Button display: "flex",
fullWidth flexDirection: {xs: "column", sm: "row"},
type="submit" alignItems: "center",
variant="contained" mx: "auto",
size="large" my: 2,
endIcon={<DataSaverOnIcon />} width: {xs: "100%", sm: "30%", md: "25%"},
disabled={props.isSubmitting ? true : false} }}
> >
{t("LoanRequest.button_submit")} <Button
</Button> fullWidth
</Box> type="submit"
</StyledForm> variant="contained"
</Stack> size="large"
)} endIcon={<DataSaverOnIcon/>}
</Formik> disabled={props.isSubmitting ? true : false}
); >
{t("LoanRequest.button_submit")}
</Button>
</Box>
</StyledForm>
</Stack>
)}
</Formik>
);
}; };
export default WelfareServicesForm; export default WelfareServicesForm;

View File

@@ -3,29 +3,29 @@ import DashboardLayouts from "@/layouts/dashboardLayouts";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import NavyForm from "./NavyForm"; import NavyForm from "./NavyForm";
import WelfareServicesForm from "./WelfareServicesForm"; import WelfareServicesForm from "./WelfareServicesForm";
import { Divider, Chip, Box } from "@mui/material"; import {Box, Chip, Divider} from "@mui/material";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
const DashboardLoanRequestComponent = () => { const DashboardLoanRequestComponent = () => {
const t = useTranslations(); const t = useTranslations();
const { user } = useUser(); const {user} = useUser();
return ( return (
<DashboardLayouts> <DashboardLayouts>
<CenterLayout> <CenterLayout>
<Box sx={{ width: "80%", my: 2 }}> <Box sx={{width: "80%", my: 2}}>
<Divider> <Divider>
<Chip <Chip
label={`${t("LoanRequest.loan_request_page")} | ${ label={`${t("LoanRequest.loan_request_page")} | ${
user.type_name user.type_name
}`} }`}
/> />
</Divider> </Divider>
</Box> </Box>
{user.type_id == 1 ? <NavyForm /> : <WelfareServicesForm />} {user.type_id == 1 ? <NavyForm/> : <WelfareServicesForm/>}
</CenterLayout> </CenterLayout>
</DashboardLayouts> </DashboardLayouts>
); );
}; };
export default DashboardLoanRequestComponent; export default DashboardLoanRequestComponent;

View File

@@ -1,55 +1,55 @@
import dahsboardImage from "&/images/dashboard.svg"; import dahsboardImage from "&/images/dashboard.svg";
import { NextLinkComposed } from "@/core/components/LinkRouting"; import {NextLinkComposed} from "@/core/components/LinkRouting";
import StyledImage from "@/core/components/StyledImage"; import StyledImage from "@/core/components/StyledImage";
import CenterLayout from "@/layouts/CenterLayout"; import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout"; import FullPageLayout from "@/layouts/FullPageLayout";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import { Button, Typography } from "@mui/material"; import {Button, Typography} from "@mui/material";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
const FirstComponent = () => { const FirstComponent = () => {
const t = useTranslations(); const t = useTranslations();
const { isAuth } = useUser(); const {isAuth} = useUser();
return ( return (
<FullPageLayout sx={{ p: 1 }}> <FullPageLayout sx={{p: 1}}>
<CenterLayout spacing={3}> <CenterLayout spacing={3}>
<StyledImage <StyledImage
src={dahsboardImage} src={dahsboardImage}
alt={t("app_name")} alt={t("app_name")}
width={300} width={300}
height={200} height={200}
priority priority
/> />
<Typography variant="h5" sx={{ textAlign: "center" }}> <Typography variant="h5" sx={{textAlign: "center"}}>
{t("app_name")} {t("app_name")}
</Typography> </Typography>
{isAuth ? ( {isAuth ? (
<Button <Button
variant="contained" variant="contained"
component={NextLinkComposed} component={NextLinkComposed}
to={{ to={{
pathname: "/dashboard", pathname: "/dashboard",
}} }}
> >
{t("dashboard")} {t("dashboard")}
</Button> </Button>
) : ( ) : (
<Button <Button
sx={{ whiteSpace: "nowrap" }} sx={{whiteSpace: "nowrap"}}
variant="contained" variant="contained"
size="large" size="large"
component={NextLinkComposed} component={NextLinkComposed}
to={{ to={{
pathname: "/login", pathname: "/login",
}} }}
> >
{t("login_user_panel")} {t("login_user_panel")}
</Button> </Button>
)} )}
</CenterLayout> </CenterLayout>
</FullPageLayout> </FullPageLayout>
); );
}; };
export default FirstComponent; export default FirstComponent;

View File

@@ -1,167 +1,158 @@
import Notifications from "@/core/components/notifications"; import Notifications from "@/core/components/notifications";
import ResendToken from "@/core/components/ResendToken"; import ResendToken from "@/core/components/ResendToken";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
import { LOGIN } from "@/core/data/apiRoutes"; import {LOGIN} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout"; import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout"; import FullPageLayout from "@/layouts/FullPageLayout";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import ChangeCircleIcon from "@mui/icons-material/ChangeCircle"; import ChangeCircleIcon from "@mui/icons-material/ChangeCircle";
import LoginIcon from "@mui/icons-material/Login"; import LoginIcon from "@mui/icons-material/Login";
import { import {Box, Button, Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material";
Box,
Button,
Container,
Grid,
Paper,
Stack,
TextField,
Typography,
} from "@mui/material";
import axios from "axios"; import axios from "axios";
import { Field, Formik } from "formik"; import {Field, Formik} from "formik";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import Image from "next/image"; import Image from "next/image";
import * as Yup from "yup"; import * as Yup from "yup";
const SendToken = ({ const SendToken = ({
PhoneNumber, PhoneNumber,
setOtpToken, setOtpToken,
timer, timer,
setTimer, setTimer,
initialTimerValue, initialTimerValue,
}) => { }) => {
const t = useTranslations(); const t = useTranslations();
const { directionApp } = useDirection(); const {directionApp} = useDirection();
const { setToken } = useUser(); const {setToken} = useUser();
const initialValues = { const initialValues = {
phone_number: PhoneNumber, phone_number: PhoneNumber,
verification_code: "", verification_code: "",
}; };
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
verification_code: Yup.string().required( verification_code: Yup.string().required(
t("LoginPage.error_message_required") t("LoginPage.error_message_required")
), ),
}); });
const handleSubmit = async (values, props) => { const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined); Notifications(directionApp, t, undefined);
await axios await axios
.post(LOGIN, { .post(LOGIN, {
phone_number: values.phone_number, phone_number: values.phone_number,
verification_code: values.verification_code, verification_code: values.verification_code,
}) })
.then(function (response) { .then(function (response) {
Notifications(directionApp, t, response); Notifications(directionApp, t, response);
setToken(response.data.token); setToken(response.data.token);
}) })
.catch(function (error) { .catch(function (error) {
Notifications(directionApp, t, error.response); Notifications(directionApp, t, error.response);
props.setSubmitting(false); props.setSubmitting(false);
}); });
}; };
return ( return (
<FullPageLayout sx={{ p: 1 }}> <FullPageLayout sx={{p: 1}}>
<CenterLayout> <CenterLayout>
<Container maxWidth="sm"> <Container maxWidth="sm">
<Paper elevation={0}> <Paper elevation={0}>
<Formik <Formik
initialValues={initialValues} initialValues={initialValues}
onSubmit={handleSubmit} onSubmit={handleSubmit}
validationSchema={validationSchema} validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{ p: 2 }}>
<Box
sx={{ position: "relative", width: "100%", height: 200 }}
>
<Image
fill
src="/images/login.svg"
priority
alt={t("app_name")}
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("login")}
</Typography>
<StyledForm sx={{ width: "100%" }}>
<Stack spacing={3} sx={{ p: 2 }}>
<Box
sx={{
display: { xs: "column", sm: "flex" },
alignItems: "center",
textAlign: { xs: "center", sm: "unset" },
justifyContent: "space-between",
}}
>
<Typography variant="button" sx={{ display: "block" }}>
{t("LoginPage.sent_token_to")}: {PhoneNumber}
</Typography>
<Button
size="small"
startIcon={<ChangeCircleIcon />}
variant="outlined"
onClick={() => setOtpToken(false)}
sx={{ whiteSpace: "nowrap", my: { xs: 1, sm: 0 } }}
> >
{t("LoginPage.change_phone_number")} {(props) => (
</Button> <Stack spacing={2} sx={{p: 2}}>
</Box> <Box
<Field sx={{position: "relative", width: "100%", height: 200}}
as={TextField} >
name="verification_code" <Image
variant="outlined" fill
label={t("LoginPage.text_field_verification_code")} src="/images/login.svg"
placeholder={t( priority
"LoginPage.text_field_enter_your_verification_code" alt={t("app_name")}
)} />
type={"text"} </Box>
error={ <Typography margin={2} variant="h4" textAlign="center">
props.touched.verification_code && {t("login")}
props.errors.verification_code </Typography>
? true <StyledForm sx={{width: "100%"}}>
: false <Stack spacing={3} sx={{p: 2}}>
} <Box
fullWidth sx={{
helperText={ display: {xs: "column", sm: "flex"},
props.touched.verification_code alignItems: "center",
? props.errors.verification_code textAlign: {xs: "center", sm: "unset"},
: null justifyContent: "space-between",
} }}
/> >
<Grid container> <Typography variant="button" sx={{display: "block"}}>
<Grid item xs={12}> {t("LoginPage.sent_token_to")}: {PhoneNumber}
<Button </Typography>
fullWidth <Button
type="submit" size="small"
variant="contained" startIcon={<ChangeCircleIcon/>}
size="large" variant="outlined"
endIcon={<LoginIcon />} onClick={() => setOtpToken(false)}
disabled={props.isSubmitting ? true : false} sx={{whiteSpace: "nowrap", my: {xs: 1, sm: 0}}}
> >
{t("LoginPage.button_submit")} {t("LoginPage.change_phone_number")}
</Button> </Button>
</Grid> </Box>
</Grid> <Field
<ResendToken as={TextField}
initialTimerValue={initialTimerValue} name="verification_code"
timer={timer} variant="outlined"
setTimer={setTimer} label={t("LoginPage.text_field_verification_code")}
PhoneNumber={PhoneNumber} placeholder={t(
/> "LoginPage.text_field_enter_your_verification_code"
</Stack> )}
</StyledForm> type={"text"}
</Stack> error={
)} props.touched.verification_code &&
</Formik> props.errors.verification_code
</Paper> ? true
</Container> : false
</CenterLayout> }
</FullPageLayout> fullWidth
); helperText={
props.touched.verification_code
? props.errors.verification_code
: null
}
/>
<Grid container>
<Grid item xs={12}>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<LoginIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("LoginPage.button_submit")}
</Button>
</Grid>
</Grid>
<ResendToken
initialTimerValue={initialTimerValue}
timer={timer}
setTimer={setTimer}
PhoneNumber={PhoneNumber}
/>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
</FullPageLayout>
);
}; };
export default SendToken; export default SendToken;

View File

@@ -1,173 +1,164 @@
import LinkRouting from "@/core/components/LinkRouting"; import LinkRouting from "@/core/components/LinkRouting";
import Notifications from "@/core/components/notifications"; import Notifications from "@/core/components/notifications";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
import { SEND_OTP_TOKEN } from "@/core/data/apiRoutes"; import {SEND_OTP_TOKEN} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout"; import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout"; import FullPageLayout from "@/layouts/FullPageLayout";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
import FingerprintIcon from "@mui/icons-material/Fingerprint"; import FingerprintIcon from "@mui/icons-material/Fingerprint";
import PersonAddIcon from "@mui/icons-material/PersonAdd"; import PersonAddIcon from "@mui/icons-material/PersonAdd";
import { import {Box, Button, Container, Grid, Paper, Stack, TextField, Typography,} from "@mui/material";
Box,
Button,
Container,
Grid,
Paper,
Stack,
TextField,
Typography,
} from "@mui/material";
import axios from "axios"; import axios from "axios";
import { Field, Formik } from "formik"; import {Field, Formik} from "formik";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import Image from "next/image"; import Image from "next/image";
import { useSearchParams } from "next/navigation"; import {useSearchParams} from "next/navigation";
import * as Yup from "yup"; import * as Yup from "yup";
const SendUserData = ({ const SendUserData = ({
setOtpToken, setOtpToken,
setPhoneNumber, setPhoneNumber,
PhoneNumber, PhoneNumber,
setTimer, setTimer,
initialTimerValue, initialTimerValue,
}) => { }) => {
const t = useTranslations(); const t = useTranslations();
const { directionApp } = useDirection(); const {directionApp} = useDirection();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url"); const backUrlDecodedPath = searchParams.get("back_url");
const initialValues = { const initialValues = {
phone_number: PhoneNumber, phone_number: PhoneNumber,
}; };
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
phone_number: Yup.string().required(t("LoginPage.error_message_required")), phone_number: Yup.string().required(t("LoginPage.error_message_required")),
}); });
const handleSubmit = async (values, props) => { const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined); Notifications(directionApp, t, undefined);
await axios await axios
.post(SEND_OTP_TOKEN, { .post(SEND_OTP_TOKEN, {
phone_number: values.phone_number, phone_number: values.phone_number,
}) })
.then(function (response) { .then(function (response) {
Notifications(directionApp, t, response); Notifications(directionApp, t, response);
setPhoneNumber(values.phone_number); setPhoneNumber(values.phone_number);
setOtpToken(true); setOtpToken(true);
setTimer(initialTimerValue); setTimer(initialTimerValue);
}) })
.catch(function (error) { .catch(function (error) {
Notifications(directionApp, t, error.response); Notifications(directionApp, t, error.response);
props.setSubmitting(false); props.setSubmitting(false);
}); });
}; };
return ( return (
<FullPageLayout sx={{ p: 1 }}> <FullPageLayout sx={{p: 1}}>
<CenterLayout> <CenterLayout>
<Container maxWidth="sm"> <Container maxWidth="sm">
<Paper elevation={0}> <Paper elevation={0}>
<Formik <Formik
initialValues={initialValues} initialValues={initialValues}
onSubmit={handleSubmit} onSubmit={handleSubmit}
validationSchema={validationSchema} validationSchema={validationSchema}
> >
{(props) => ( {(props) => (
<Stack spacing={2} sx={{ p: 2 }}> <Stack spacing={2} sx={{p: 2}}>
<Box <Box
sx={{ position: "relative", width: "100%", height: 200 }} sx={{position: "relative", width: "100%", height: 200}}
> >
<Image <Image
fill fill
src="/images/login.svg" src="/images/login.svg"
priority priority
alt={t("app_name")} alt={t("app_name")}
/> />
</Box> </Box>
<Typography margin={2} variant="h4" textAlign="center"> <Typography margin={2} variant="h4" textAlign="center">
{t("Titles.title_login_page")} {t("Titles.title_login_page")}
</Typography> </Typography>
<StyledForm sx={{ width: "100%" }}> <StyledForm sx={{width: "100%"}}>
<Stack spacing={3} sx={{ p: 2 }}> <Stack spacing={3} sx={{p: 2}}>
<Field <Field
as={TextField} as={TextField}
name="phone_number" name="phone_number"
variant="outlined" variant="outlined"
label={t("LoginPage.text_field_phone_number")} label={t("LoginPage.text_field_phone_number")}
placeholder={t( placeholder={t(
"LoginPage.text_field_enter_your_phone_number" "LoginPage.text_field_enter_your_phone_number"
)} )}
type={"text"} type={"text"}
error={ error={
props.touched.phone_number && props.touched.phone_number &&
props.errors.phone_number props.errors.phone_number
? true ? true
: false : false
} }
fullWidth fullWidth
helperText={ helperText={
props.touched.phone_number props.touched.phone_number
? props.errors.phone_number ? props.errors.phone_number
: null : null
} }
/> />
<Grid <Grid
container container
rowSpacing={{ xs: 1, sm: 0 }} rowSpacing={{xs: 1, sm: 0}}
sx={{ sx={{
flexDirection: { xs: "column-reverse", sm: "row" }, flexDirection: {xs: "column-reverse", sm: "row"},
}} }}
> >
<Grid item xs={12} sm={6} sx={{ pr: { xs: 0, sm: 1 } }}> <Grid item xs={12} sm={6} sx={{pr: {xs: 0, sm: 1}}}>
<LinkRouting href={"/register"}> <LinkRouting href={"/register"}>
<Button <Button
fullWidth fullWidth
type="submit" type="submit"
variant="outlined" variant="outlined"
size="large" size="large"
endIcon={<PersonAddIcon />} endIcon={<PersonAddIcon/>}
disabled={props.isSubmitting ? true : false} disabled={props.isSubmitting ? true : false}
> >
{t("LoginPage.button_make_account")} {t("LoginPage.button_make_account")}
</Button> </Button>
</LinkRouting> </LinkRouting>
</Grid> </Grid>
<Grid item xs={12} sm={6} sx={{ pl: { xs: 0, sm: 1 } }}> <Grid item xs={12} sm={6} sx={{pl: {xs: 0, sm: 1}}}>
<Button <Button
fullWidth fullWidth
type="submit" type="submit"
variant="contained" variant="contained"
size="large" size="large"
endIcon={<FingerprintIcon />} endIcon={<FingerprintIcon/>}
disabled={props.isSubmitting ? true : false} disabled={props.isSubmitting ? true : false}
> >
{t("LoginPage.button_request_verification")} {t("LoginPage.button_request_verification")}
</Button> </Button>
</Grid> </Grid>
</Grid> </Grid>
</Stack> </Stack>
</StyledForm> </StyledForm>
</Stack> </Stack>
)} )}
</Formik> </Formik>
</Paper> </Paper>
</Container> </Container>
</CenterLayout> </CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center"> <Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting <LinkRouting
sx={{ margin: 2 }} sx={{margin: 2}}
href={ href={
backUrlDecodedPath ? decodeURIComponent(backUrlDecodedPath) : "/" backUrlDecodedPath ? decodeURIComponent(backUrlDecodedPath) : "/"
} }
> >
{t("LoginPage.link_routing_back_to")}{" "} {t("LoginPage.link_routing_back_to")}{" "}
{backUrlDecodedPath {backUrlDecodedPath
? t("LoginPage.link_routing_previuos_page") ? t("LoginPage.link_routing_previuos_page")
: t("LoginPage.link_routing_main_page")} : t("LoginPage.link_routing_main_page")}
</LinkRouting> </LinkRouting>
</Stack> </Stack>
</FullPageLayout> </FullPageLayout>
); );
}; };
export default SendUserData; export default SendUserData;

View File

@@ -1,37 +1,37 @@
import { useState } from "react"; import {useState} from "react";
import SendToken from "./SendToken"; import SendToken from "./SendToken";
import SendUserData from "./SendUserData"; import SendUserData from "./SendUserData";
const LoginComponent = () => { const LoginComponent = () => {
const [otpToken, setOtpToken] = useState(false); const [otpToken, setOtpToken] = useState(false);
const [PhoneNumber, setPhoneNumber] = useState(""); const [PhoneNumber, setPhoneNumber] = useState("");
// For Resend Token (read ResendToken Component Doc) // For Resend Token (read ResendToken Component Doc)
const initialTimerValue = 30; const initialTimerValue = 30;
const [timer, setTimer] = useState(initialTimerValue); const [timer, setTimer] = useState(initialTimerValue);
// End For Resend Token // End For Resend Token
if (!otpToken) { if (!otpToken) {
return ( return (
<SendUserData <SendUserData
setOtpToken={setOtpToken} setOtpToken={setOtpToken}
setPhoneNumber={setPhoneNumber} setPhoneNumber={setPhoneNumber}
PhoneNumber={PhoneNumber} PhoneNumber={PhoneNumber}
initialTimerValue={initialTimerValue} initialTimerValue={initialTimerValue}
setTimer={setTimer} setTimer={setTimer}
/> />
); );
} else { } else {
return ( return (
<SendToken <SendToken
PhoneNumber={PhoneNumber} PhoneNumber={PhoneNumber}
setOtpToken={setOtpToken} setOtpToken={setOtpToken}
timer={timer} timer={timer}
initialTimerValue={initialTimerValue} initialTimerValue={initialTimerValue}
setTimer={setTimer} setTimer={setTimer}
/> />
); );
} }
}; };
export default LoginComponent; export default LoginComponent;

View File

@@ -1,38 +1,38 @@
import CenterLayout from "@/layouts/CenterLayout"; import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout"; import FullPageLayout from "@/layouts/FullPageLayout";
import { Box, Button, Typography } from "@mui/material"; import {Box, Button, Typography} from "@mui/material";
import { NextLinkComposed } from "@/core/components/LinkRouting"; import {NextLinkComposed} from "@/core/components/LinkRouting";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import Image from "next/image"; import Image from "next/image";
const NotFoundComponent = () => { const NotFoundComponent = () => {
const t = useTranslations(); const t = useTranslations();
return ( return (
<FullPageLayout sx={{ p: 1 }}> <FullPageLayout sx={{p: 1}}>
<CenterLayout> <CenterLayout>
<Box sx={{ position: "relative", width: "100%", height: 250 }}> <Box sx={{position: "relative", width: "100%", height: 250}}>
<Image <Image
fill fill
src="/images/not-found.svg" src="/images/not-found.svg"
alt="not found image" alt="not found image"
priority priority
/> />
</Box> </Box>
<Typography margin={2} variant="h6" textAlign="center"> <Typography margin={2} variant="h6" textAlign="center">
صفحه ای با این عنوان یافت نشد صفحه ای با این عنوان یافت نشد
</Typography> </Typography>
<Button <Button
variant="contained" variant="contained"
component={NextLinkComposed} component={NextLinkComposed}
to={{ to={{
pathname: "/dashboard", pathname: "/dashboard",
}} }}
> >
رفتن به داشبورد رفتن به داشبورد
</Button> </Button>
</CenterLayout> </CenterLayout>
</FullPageLayout> </FullPageLayout>
); );
}; };
export default NotFoundComponent; export default NotFoundComponent;

View File

@@ -1,151 +1,143 @@
import LinkRouting from "@/core/components/LinkRouting"; import LinkRouting from "@/core/components/LinkRouting";
import Notifications from "@/core/components/notifications"; import Notifications from "@/core/components/notifications";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
import { SEND_OTP_TOKEN } from "@/core/data/apiRoutes"; import {SEND_OTP_TOKEN} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout"; import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout"; import FullPageLayout from "@/layouts/FullPageLayout";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
import FingerprintIcon from "@mui/icons-material/Fingerprint"; import FingerprintIcon from "@mui/icons-material/Fingerprint";
import { import {Box, Button, Container, Paper, Stack, TextField, Typography,} from "@mui/material";
Box,
Button,
Container,
Paper,
Stack,
TextField,
Typography,
} from "@mui/material";
import axios from "axios"; import axios from "axios";
import { Field, Formik } from "formik"; import {Field, Formik} from "formik";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import Image from "next/image"; import Image from "next/image";
import { useSearchParams } from "next/navigation"; import {useSearchParams} from "next/navigation";
import * as Yup from "yup"; import * as Yup from "yup";
const RequestOtp = ({ const RequestOtp = ({
setOtpToken, setOtpToken,
setPhoneNumber, setPhoneNumber,
PhoneNumber, PhoneNumber,
setTimer, setTimer,
initialTimerValue, initialTimerValue,
}) => { }) => {
const t = useTranslations(); const t = useTranslations();
const { directionApp } = useDirection(); const {directionApp} = useDirection();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url"); const backUrlDecodedPath = searchParams.get("back_url");
const initialValues = { const initialValues = {
phone_number: PhoneNumber, phone_number: PhoneNumber,
}; };
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
phone_number: Yup.string().required( phone_number: Yup.string().required(
t("RegisterPage.error_message_required") t("RegisterPage.error_message_required")
), ),
}); });
const handleSubmit = async (values, props) => { const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined); Notifications(directionApp, t, undefined);
await axios await axios
.post(SEND_OTP_TOKEN, { .post(SEND_OTP_TOKEN, {
phone_number: values.phone_number, phone_number: values.phone_number,
}) })
.then(function (response) { .then(function (response) {
Notifications(directionApp, t, response); Notifications(directionApp, t, response);
setPhoneNumber(values.phone_number); setPhoneNumber(values.phone_number);
setOtpToken(true); setOtpToken(true);
setTimer(initialTimerValue); setTimer(initialTimerValue);
}) })
.catch(function (error) { .catch(function (error) {
Notifications(directionApp, t, error.response); Notifications(directionApp, t, error.response);
props.setSubmitting(false); props.setSubmitting(false);
}); });
}; };
return ( return (
<FullPageLayout sx={{ p: 1 }}> <FullPageLayout sx={{p: 1}}>
<CenterLayout> <CenterLayout>
<Container maxWidth="sm"> <Container maxWidth="sm">
<Paper elevation={0}> <Paper elevation={0}>
<Formik <Formik
initialValues={initialValues} initialValues={initialValues}
onSubmit={handleSubmit} onSubmit={handleSubmit}
validationSchema={validationSchema} validationSchema={validationSchema}
> >
{(props) => ( {(props) => (
<Stack spacing={2} sx={{ p: 2 }}> <Stack spacing={2} sx={{p: 2}}>
<Box <Box
sx={{ position: "relative", width: "100%", height: 200 }} sx={{position: "relative", width: "100%", height: 200}}
> >
<Image <Image
fill fill
src="/images/login.svg" src="/images/login.svg"
priority priority
alt={t("app_name")} alt={t("app_name")}
/> />
</Box> </Box>
<Typography margin={2} variant="h4" textAlign="center"> <Typography margin={2} variant="h4" textAlign="center">
{t("Titles.title_register_page")} {t("Titles.title_register_page")}
</Typography> </Typography>
<StyledForm sx={{ width: "100%" }}> <StyledForm sx={{width: "100%"}}>
<Stack spacing={3} sx={{ p: 2 }}> <Stack spacing={3} sx={{p: 2}}>
<Field <Field
as={TextField} as={TextField}
name="phone_number" name="phone_number"
variant="outlined" variant="outlined"
label={t("RegisterPage.text_field_phone_number")} label={t("RegisterPage.text_field_phone_number")}
placeholder={t( placeholder={t(
"RegisterPage.text_field_enter_your_phone_number" "RegisterPage.text_field_enter_your_phone_number"
)} )}
type={"text"} type={"text"}
error={ error={
props.touched.phone_number && props.touched.phone_number &&
props.errors.phone_number props.errors.phone_number
? true ? true
: false : false
} }
fullWidth fullWidth
helperText={ helperText={
props.touched.phone_number props.touched.phone_number
? props.errors.phone_number ? props.errors.phone_number
: null : null
} }
/> />
<Button <Button
fullWidth fullWidth
type="submit" type="submit"
variant="contained" variant="contained"
size="large" size="large"
endIcon={<FingerprintIcon />} endIcon={<FingerprintIcon/>}
disabled={props.isSubmitting ? true : false} disabled={props.isSubmitting ? true : false}
> >
{t("RegisterPage.button_request_verification")} {t("RegisterPage.button_request_verification")}
</Button> </Button>
</Stack> </Stack>
</StyledForm> </StyledForm>
</Stack> </Stack>
)} )}
</Formik> </Formik>
</Paper> </Paper>
</Container> </Container>
</CenterLayout> </CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center"> <Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting <LinkRouting
sx={{ margin: 2 }} sx={{margin: 2}}
href={ href={
backUrlDecodedPath backUrlDecodedPath
? decodeURIComponent(backUrlDecodedPath) ? decodeURIComponent(backUrlDecodedPath)
: "/register" : "/register"
} }
> >
{t("RegisterPage.link_routing_back_to")}{" "} {t("RegisterPage.link_routing_back_to")}{" "}
{backUrlDecodedPath {backUrlDecodedPath
? t("RegisterPage.link_routing_previuos_page") ? t("RegisterPage.link_routing_previuos_page")
: t("RegisterPage.link_routing_register")} : t("RegisterPage.link_routing_register")}
</LinkRouting> </LinkRouting>
</Stack> </Stack>
</FullPageLayout> </FullPageLayout>
); );
}; };
export default RequestOtp; export default RequestOtp;

View File

@@ -1,98 +1,97 @@
import dahsboardImage from "&/images/dashboard.svg"; import dahsboardImage from "&/images/dashboard.svg";
import LinkRouting from "@/core/components/LinkRouting"; import LinkRouting, {NextLinkComposed} from "@/core/components/LinkRouting";
import { NextLinkComposed } from "@/core/components/LinkRouting";
import StyledImage from "@/core/components/StyledImage"; import StyledImage from "@/core/components/StyledImage";
import CenterLayout from "@/layouts/CenterLayout"; import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout"; import FullPageLayout from "@/layouts/FullPageLayout";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import { Box, Button, Grid, Stack } from "@mui/material"; import {Box, Button, Grid, Stack} from "@mui/material";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import { useSearchParams } from "next/navigation"; import {useSearchParams} from "next/navigation";
const RegisterComponent = () => { const RegisterComponent = () => {
const t = useTranslations(); const t = useTranslations();
const { isAuth } = useUser(); const {isAuth} = useUser();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url"); const backUrlDecodedPath = searchParams.get("back_url");
return ( return (
<FullPageLayout sx={{ p: 1 }}> <FullPageLayout sx={{p: 1}}>
<CenterLayout spacing={3}> <CenterLayout spacing={3}>
<StyledImage <StyledImage
src={dahsboardImage} src={dahsboardImage}
alt={t("app_name")} alt={t("app_name")}
width={300} width={300}
height={200} height={200}
priority priority
/> />
{isAuth ? ( {isAuth ? (
<Button <Button
variant="contained" variant="contained"
component={NextLinkComposed} component={NextLinkComposed}
to={{ to={{
pathname: "/dashboard", pathname: "/dashboard",
}} }}
> >
{t("dashboard")} {t("dashboard")}
</Button> </Button>
) : ( ) : (
<Box> <Box>
<Grid <Grid
container container
rowSpacing={{ xs: 1, sm: 0 }} rowSpacing={{xs: 1, sm: 0}}
sx={{ sx={{
flexDirection: { xs: "column", sm: "row" }, flexDirection: {xs: "column", sm: "row"},
alignItems: "center", alignItems: "center",
}} }}
> >
<Grid item xs={12} sm={6} sx={{ px: { xs: 0, sm: 1 } }}> <Grid item xs={12} sm={6} sx={{px: {xs: 0, sm: 1}}}>
<Button <Button
sx={{ whiteSpace: "nowrap" }} sx={{whiteSpace: "nowrap"}}
variant="contained" variant="contained"
size="large" size="large"
component={NextLinkComposed} component={NextLinkComposed}
to={{ to={{
pathname: "register/navy", pathname: "register/navy",
}} }}
>
{t("register_navy")}
</Button>
</Grid>
<Grid item xs={12} sm={6} sx={{px: {xs: 0, sm: 1}}}>
<Button
sx={{whiteSpace: "nowrap"}}
variant="contained"
size="large"
component={NextLinkComposed}
to={{
pathname: "register/welfare-services",
}}
>
{t("register_welfare_services")}
</Button>
</Grid>
</Grid>
</Box>
)}
</CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting
sx={{margin: 2}}
href={
backUrlDecodedPath
? decodeURIComponent(backUrlDecodedPath)
: "/login"
}
> >
{t("register_navy")} {t("RegisterPage.link_routing_back_to")}{" "}
</Button> {backUrlDecodedPath
</Grid> ? t("RegisterPage.link_routing_previuos_page")
<Grid item xs={12} sm={6} sx={{ px: { xs: 0, sm: 1 } }}> : t("RegisterPage.link_routing_login")}
<Button </LinkRouting>
sx={{ whiteSpace: "nowrap" }} </Stack>
variant="contained" </FullPageLayout>
size="large" );
component={NextLinkComposed}
to={{
pathname: "register/welfare-services",
}}
>
{t("register_welfare_services")}
</Button>
</Grid>
</Grid>
</Box>
)}
</CenterLayout>
<Stack direction="row" alignItems="center" justifyContent="center">
<LinkRouting
sx={{ margin: 2 }}
href={
backUrlDecodedPath
? decodeURIComponent(backUrlDecodedPath)
: "/login"
}
>
{t("RegisterPage.link_routing_back_to")}{" "}
{backUrlDecodedPath
? t("RegisterPage.link_routing_previuos_page")
: t("RegisterPage.link_routing_login")}
</LinkRouting>
</Stack>
</FullPageLayout>
);
}; };
export default RegisterComponent; export default RegisterComponent;

View File

@@ -1,222 +1,212 @@
import Notifications from "@/core/components/notifications"; import Notifications from "@/core/components/notifications";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
import { REGISTER } from "@/core/data/apiRoutes"; import {REGISTER} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout"; import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout"; import FullPageLayout from "@/layouts/FullPageLayout";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
import LoginIcon from "@mui/icons-material/Login"; import LoginIcon from "@mui/icons-material/Login";
import ChangeCircleIcon from "@mui/icons-material/ChangeCircle"; import ChangeCircleIcon from "@mui/icons-material/ChangeCircle";
import { import {Box, Button, Chip, Container, Divider, Paper, Stack, TextField, Typography,} from "@mui/material";
Box,
Button,
Chip,
Container,
Divider,
Paper,
Stack,
TextField,
Typography,
} from "@mui/material";
import axios from "axios"; import axios from "axios";
import { Field, Formik } from "formik"; import {Field, Formik} from "formik";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import Image from "next/image"; import Image from "next/image";
import * as Yup from "yup"; import * as Yup from "yup";
import ResendToken from "@/core/components/ResendToken"; import ResendToken from "@/core/components/ResendToken";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
const UserRegister = ({ const UserRegister = ({
PhoneNumber, PhoneNumber,
setOtpToken, setOtpToken,
initialTimerValue, initialTimerValue,
timer, timer,
setTimer, setTimer,
}) => { }) => {
const t = useTranslations(); const t = useTranslations();
const { directionApp } = useDirection(); const {directionApp} = useDirection();
const { setToken } = useUser(); const {setToken} = useUser();
const initialValues = { const initialValues = {
type_id: "1", type_id: "1",
verification_code: "", verification_code: "",
phone_number: PhoneNumber, phone_number: PhoneNumber,
national_id: "", national_id: "",
navgan_id: "", navgan_id: "",
}; };
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
verification_code: Yup.string().required( verification_code: Yup.string().required(
t("RegisterPage.error_message_required") t("RegisterPage.error_message_required")
), ),
national_id: Yup.string().required( national_id: Yup.string().required(
t("RegisterPage.error_message_required") t("RegisterPage.error_message_required")
), ),
navgan_id: Yup.string().required(t("RegisterPage.error_message_required")), navgan_id: Yup.string().required(t("RegisterPage.error_message_required")),
}); });
const handleSubmit = async (values, props) => { const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined); Notifications(directionApp, t, undefined);
console.log(initialValues); console.log(initialValues);
await axios await axios
.post(REGISTER, { .post(REGISTER, {
type_id: values.type_id, type_id: values.type_id,
national_id: values.national_id, national_id: values.national_id,
navgan_id: values.navgan_id, navgan_id: values.navgan_id,
phone_number: values.phone_number, phone_number: values.phone_number,
verification_code: values.verification_code, verification_code: values.verification_code,
}) })
.then(function (response) { .then(function (response) {
Notifications(directionApp, t, response); Notifications(directionApp, t, response);
setOtpToken(true); setOtpToken(true);
setToken(response.data.token); setToken(response.data.token);
}) })
.catch(function (error) { .catch(function (error) {
Notifications(directionApp, t, error.response); Notifications(directionApp, t, error.response);
props.setSubmitting(false); props.setSubmitting(false);
}); });
}; };
return ( return (
<FullPageLayout sx={{ p: 1 }}> <FullPageLayout sx={{p: 1}}>
<CenterLayout> <CenterLayout>
<Container maxWidth="sm"> <Container maxWidth="sm">
<Paper elevation={0}> <Paper elevation={0}>
<Formik <Formik
initialValues={initialValues} initialValues={initialValues}
onSubmit={handleSubmit} onSubmit={handleSubmit}
validationSchema={validationSchema} validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{ p: 2 }}>
<Box
sx={{ position: "relative", width: "100%", height: 200 }}
>
<Image
fill
src="/images/register.svg"
alt={t("app_name")}
priority
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("register_navy")}
</Typography>
<StyledForm sx={{ width: "100%" }}>
<Stack spacing={3} sx={{ p: 2 }}>
<Box
sx={{
display: { xs: "column", sm: "flex" },
alignItems: "center",
textAlign: { xs: "center", sm: "unset" },
justifyContent: "space-between",
}}
>
<Typography variant="button" sx={{ display: "block" }}>
{t("LoginPage.sent_token_to")}: {PhoneNumber}
</Typography>
<Button
size="small"
startIcon={<ChangeCircleIcon />}
variant="outlined"
sx={{ whiteSpace: "nowrap", my: { xs: 1, sm: 0 } }}
onClick={() => setOtpToken(false)}
> >
{t("LoginPage.change_phone_number")} {(props) => (
</Button> <Stack spacing={2} sx={{p: 2}}>
</Box> <Box
<Field sx={{position: "relative", width: "100%", height: 200}}
as={TextField} >
name="verification_code" <Image
variant="outlined" fill
label={t("LoginPage.text_field_verification_code")} src="/images/register.svg"
placeholder={t( alt={t("app_name")}
"LoginPage.text_field_enter_your_verification_code" priority
)} />
type={"text"} </Box>
error={ <Typography margin={2} variant="h4" textAlign="center">
props.touched.verification_code && {t("register_navy")}
props.errors.verification_code </Typography>
? true <StyledForm sx={{width: "100%"}}>
: false <Stack spacing={3} sx={{p: 2}}>
} <Box
fullWidth sx={{
helperText={ display: {xs: "column", sm: "flex"},
props.touched.verification_code alignItems: "center",
? props.errors.verification_code textAlign: {xs: "center", sm: "unset"},
: null justifyContent: "space-between",
} }}
/> >
<ResendToken <Typography variant="button" sx={{display: "block"}}>
initialTimerValue={initialTimerValue} {t("LoginPage.sent_token_to")}: {PhoneNumber}
timer={timer} </Typography>
setTimer={setTimer} <Button
PhoneNumber={PhoneNumber} size="small"
/> startIcon={<ChangeCircleIcon/>}
<Divider> variant="outlined"
<Chip label={t("RegisterPage.complete_information")} /> sx={{whiteSpace: "nowrap", my: {xs: 1, sm: 0}}}
</Divider> onClick={() => setOtpToken(false)}
<Field >
as={TextField} {t("LoginPage.change_phone_number")}
name="national_id" </Button>
variant="outlined" </Box>
label={t("RegisterPage.text_field_national_id")} <Field
placeholder={t( as={TextField}
"RegisterPage.text_field_enter_your_national_id" name="verification_code"
)} variant="outlined"
type={"text"} label={t("LoginPage.text_field_verification_code")}
error={ placeholder={t(
props.touched.national_id && props.errors.national_id "LoginPage.text_field_enter_your_verification_code"
? true )}
: false type={"text"}
} error={
fullWidth props.touched.verification_code &&
helperText={ props.errors.verification_code
props.touched.national_id ? true
? props.errors.national_id : false
: null }
} fullWidth
/> helperText={
<Field props.touched.verification_code
as={TextField} ? props.errors.verification_code
name="navgan_id" : null
variant="outlined" }
label={t("RegisterPage.text_field_navgan_id")} />
placeholder={t( <ResendToken
"RegisterPage.text_field_enter_your_navgan_id" initialTimerValue={initialTimerValue}
)} timer={timer}
type={"text"} setTimer={setTimer}
error={ PhoneNumber={PhoneNumber}
props.touched.navgan_id && props.errors.navgan_id />
? true <Divider>
: false <Chip label={t("RegisterPage.complete_information")}/>
} </Divider>
fullWidth <Field
helperText={ as={TextField}
props.touched.navgan_id name="national_id"
? props.errors.navgan_id variant="outlined"
: null label={t("RegisterPage.text_field_national_id")}
} placeholder={t(
/> "RegisterPage.text_field_enter_your_national_id"
<Button )}
fullWidth type={"text"}
type="submit" error={
variant="contained" props.touched.national_id && props.errors.national_id
size="large" ? true
endIcon={<LoginIcon />} : false
disabled={props.isSubmitting ? true : false} }
> fullWidth
{t("RegisterPage.button_submit")} helperText={
</Button> props.touched.national_id
</Stack> ? props.errors.national_id
</StyledForm> : null
</Stack> }
)} />
</Formik> <Field
</Paper> as={TextField}
</Container> name="navgan_id"
</CenterLayout> variant="outlined"
</FullPageLayout> label={t("RegisterPage.text_field_navgan_id")}
); placeholder={t(
"RegisterPage.text_field_enter_your_navgan_id"
)}
type={"text"}
error={
props.touched.navgan_id && props.errors.navgan_id
? true
: false
}
fullWidth
helperText={
props.touched.navgan_id
? props.errors.navgan_id
: null
}
/>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<LoginIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("RegisterPage.button_submit")}
</Button>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
</FullPageLayout>
);
}; };
export default UserRegister; export default UserRegister;

View File

@@ -1,37 +1,37 @@
import { useState } from "react"; import {useState} from "react";
import RequestOtp from "../RequestOtp"; import RequestOtp from "../RequestOtp";
import UserRegister from "./UserRegister"; import UserRegister from "./UserRegister";
const NavyComponent = () => { const NavyComponent = () => {
const [otpToken, setOtpToken] = useState(false); const [otpToken, setOtpToken] = useState(false);
const [PhoneNumber, setPhoneNumber] = useState(""); const [PhoneNumber, setPhoneNumber] = useState("");
// For Resend Token (read ResendToken Component Doc) // For Resend Token (read ResendToken Component Doc)
const initialTimerValue = 30; const initialTimerValue = 30;
const [timer, setTimer] = useState(initialTimerValue); const [timer, setTimer] = useState(initialTimerValue);
// End For Resend Token // End For Resend Token
if (!otpToken) { if (!otpToken) {
return ( return (
<RequestOtp <RequestOtp
setOtpToken={setOtpToken} setOtpToken={setOtpToken}
PhoneNumber={PhoneNumber} PhoneNumber={PhoneNumber}
setPhoneNumber={setPhoneNumber} setPhoneNumber={setPhoneNumber}
setTimer={setTimer} setTimer={setTimer}
initialTimerValue={initialTimerValue} initialTimerValue={initialTimerValue}
/> />
); );
} else { } else {
return ( return (
<UserRegister <UserRegister
PhoneNumber={PhoneNumber} PhoneNumber={PhoneNumber}
setOtpToken={setOtpToken} setOtpToken={setOtpToken}
timer={timer} timer={timer}
setTimer={setTimer} setTimer={setTimer}
initialTimerValue={initialTimerValue} initialTimerValue={initialTimerValue}
/> />
); );
} }
}; };
export default NavyComponent; export default NavyComponent;

View File

@@ -1,198 +1,188 @@
import Notifications from "@/core/components/notifications"; import Notifications from "@/core/components/notifications";
import StyledForm from "@/core/components/StyledForm"; import StyledForm from "@/core/components/StyledForm";
import { REGISTER } from "@/core/data/apiRoutes"; import {REGISTER} from "@/core/data/apiRoutes";
import CenterLayout from "@/layouts/CenterLayout"; import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout"; import FullPageLayout from "@/layouts/FullPageLayout";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
import LoginIcon from "@mui/icons-material/Login"; import LoginIcon from "@mui/icons-material/Login";
import ChangeCircleIcon from "@mui/icons-material/ChangeCircle"; import ChangeCircleIcon from "@mui/icons-material/ChangeCircle";
import { import {Box, Button, Chip, Container, Divider, Paper, Stack, TextField, Typography,} from "@mui/material";
Box,
Button,
Chip,
Container,
Divider,
Paper,
Stack,
TextField,
Typography,
} from "@mui/material";
import axios from "axios"; import axios from "axios";
import { Field, Formik } from "formik"; import {Field, Formik} from "formik";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import Image from "next/image"; import Image from "next/image";
import * as Yup from "yup"; import * as Yup from "yup";
import ResendToken from "@/core/components/ResendToken"; import ResendToken from "@/core/components/ResendToken";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
const UserRegister = ({ const UserRegister = ({
PhoneNumber, PhoneNumber,
setOtpToken, setOtpToken,
initialTimerValue, initialTimerValue,
timer, timer,
setTimer, setTimer,
}) => { }) => {
const t = useTranslations(); const t = useTranslations();
const { directionApp } = useDirection(); const {directionApp} = useDirection();
const { setToken } = useUser(); const {setToken} = useUser();
const initialValues = { const initialValues = {
type_id: "2", type_id: "2",
verification_code: "", verification_code: "",
phone_number: PhoneNumber, phone_number: PhoneNumber,
national_id: "", national_id: "",
}; };
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
verification_code: Yup.string().required( verification_code: Yup.string().required(
t("RegisterPage.error_message_required") t("RegisterPage.error_message_required")
), ),
national_id: Yup.string().required( national_id: Yup.string().required(
t("RegisterPage.error_message_required") t("RegisterPage.error_message_required")
), ),
}); });
const handleSubmit = async (values, props) => { const handleSubmit = async (values, props) => {
Notifications(directionApp, t, undefined); Notifications(directionApp, t, undefined);
console.log(initialValues); console.log(initialValues);
await axios await axios
.post(REGISTER, { .post(REGISTER, {
type_id: values.type_id, type_id: values.type_id,
national_id: values.national_id, national_id: values.national_id,
phone_number: values.phone_number, phone_number: values.phone_number,
verification_code: values.verification_code, verification_code: values.verification_code,
}) })
.then(function (response) { .then(function (response) {
Notifications(directionApp, t, response); Notifications(directionApp, t, response);
setOtpToken(true); setOtpToken(true);
setToken(response.data.token); setToken(response.data.token);
}) })
.catch(function (error) { .catch(function (error) {
Notifications(directionApp, t, error.response); Notifications(directionApp, t, error.response);
props.setSubmitting(false); props.setSubmitting(false);
}); });
}; };
return ( return (
<FullPageLayout sx={{ p: 1 }}> <FullPageLayout sx={{p: 1}}>
<CenterLayout> <CenterLayout>
<Container maxWidth="sm"> <Container maxWidth="sm">
<Paper elevation={0}> <Paper elevation={0}>
<Formik <Formik
initialValues={initialValues} initialValues={initialValues}
onSubmit={handleSubmit} onSubmit={handleSubmit}
validationSchema={validationSchema} validationSchema={validationSchema}
>
{(props) => (
<Stack spacing={2} sx={{ p: 2 }}>
<Box
sx={{ position: "relative", width: "100%", height: 200 }}
>
<Image
fill
src="/images/register.svg"
alt={t("app_name")}
priority
/>
</Box>
<Typography margin={2} variant="h4" textAlign="center">
{t("register_welfare_services")}
</Typography>
<StyledForm sx={{ width: "100%" }}>
<Stack spacing={3} sx={{ p: 2 }}>
<Box
sx={{
display: { xs: "column", sm: "flex" },
alignItems: "center",
textAlign: { xs: "center", sm: "unset" },
justifyContent: "space-between",
}}
>
<Typography variant="button" sx={{ display: "block" }}>
{t("LoginPage.sent_token_to")}: {PhoneNumber}
</Typography>
<Button
size="small"
startIcon={<ChangeCircleIcon />}
variant="outlined"
onClick={() => setOtpToken(false)}
sx={{ whiteSpace: "nowrap", my: { xs: 1, sm: 0 } }}
> >
{t("LoginPage.change_phone_number")} {(props) => (
</Button> <Stack spacing={2} sx={{p: 2}}>
</Box> <Box
<Field sx={{position: "relative", width: "100%", height: 200}}
as={TextField} >
name="verification_code" <Image
variant="outlined" fill
label={t("LoginPage.text_field_verification_code")} src="/images/register.svg"
placeholder={t( alt={t("app_name")}
"LoginPage.text_field_enter_your_verification_code" priority
)} />
type={"text"} </Box>
error={ <Typography margin={2} variant="h4" textAlign="center">
props.touched.verification_code && {t("register_welfare_services")}
props.errors.verification_code </Typography>
? true <StyledForm sx={{width: "100%"}}>
: false <Stack spacing={3} sx={{p: 2}}>
} <Box
fullWidth sx={{
helperText={ display: {xs: "column", sm: "flex"},
props.touched.verification_code alignItems: "center",
? props.errors.verification_code textAlign: {xs: "center", sm: "unset"},
: null justifyContent: "space-between",
} }}
/> >
<ResendToken <Typography variant="button" sx={{display: "block"}}>
initialTimerValue={initialTimerValue} {t("LoginPage.sent_token_to")}: {PhoneNumber}
timer={timer} </Typography>
setTimer={setTimer} <Button
PhoneNumber={PhoneNumber} size="small"
/> startIcon={<ChangeCircleIcon/>}
<Divider> variant="outlined"
<Chip label={t("RegisterPage.complete_information")} /> onClick={() => setOtpToken(false)}
</Divider> sx={{whiteSpace: "nowrap", my: {xs: 1, sm: 0}}}
<Field >
as={TextField} {t("LoginPage.change_phone_number")}
name="national_id" </Button>
variant="outlined" </Box>
label={t("RegisterPage.text_field_national_id")} <Field
placeholder={t( as={TextField}
"RegisterPage.text_field_enter_your_national_id" name="verification_code"
)} variant="outlined"
type={"text"} label={t("LoginPage.text_field_verification_code")}
error={ placeholder={t(
props.touched.national_id && props.errors.national_id "LoginPage.text_field_enter_your_verification_code"
? true )}
: false type={"text"}
} error={
fullWidth props.touched.verification_code &&
helperText={ props.errors.verification_code
props.touched.national_id ? true
? props.errors.national_id : false
: null }
} fullWidth
/> helperText={
<Button props.touched.verification_code
fullWidth ? props.errors.verification_code
type="submit" : null
variant="contained" }
size="large" />
endIcon={<LoginIcon />} <ResendToken
disabled={props.isSubmitting ? true : false} initialTimerValue={initialTimerValue}
> timer={timer}
{t("RegisterPage.button_submit")} setTimer={setTimer}
</Button> PhoneNumber={PhoneNumber}
</Stack> />
</StyledForm> <Divider>
</Stack> <Chip label={t("RegisterPage.complete_information")}/>
)} </Divider>
</Formik> <Field
</Paper> as={TextField}
</Container> name="national_id"
</CenterLayout> variant="outlined"
</FullPageLayout> label={t("RegisterPage.text_field_national_id")}
); placeholder={t(
"RegisterPage.text_field_enter_your_national_id"
)}
type={"text"}
error={
props.touched.national_id && props.errors.national_id
? true
: false
}
fullWidth
helperText={
props.touched.national_id
? props.errors.national_id
: null
}
/>
<Button
fullWidth
type="submit"
variant="contained"
size="large"
endIcon={<LoginIcon/>}
disabled={props.isSubmitting ? true : false}
>
{t("RegisterPage.button_submit")}
</Button>
</Stack>
</StyledForm>
</Stack>
)}
</Formik>
</Paper>
</Container>
</CenterLayout>
</FullPageLayout>
);
}; };
export default UserRegister; export default UserRegister;

View File

@@ -1,37 +1,37 @@
import { useState } from "react"; import {useState} from "react";
import RequestOtp from "../RequestOtp"; import RequestOtp from "../RequestOtp";
import UserRegister from "./UserRegister"; import UserRegister from "./UserRegister";
const NavyComponent = () => { const NavyComponent = () => {
const [otpToken, setOtpToken] = useState(false); const [otpToken, setOtpToken] = useState(false);
const [PhoneNumber, setPhoneNumber] = useState(""); const [PhoneNumber, setPhoneNumber] = useState("");
// For Resend Token (read ResendToken Component Doc) // For Resend Token (read ResendToken Component Doc)
const initialTimerValue = 30; const initialTimerValue = 30;
const [timer, setTimer] = useState(initialTimerValue); const [timer, setTimer] = useState(initialTimerValue);
// End For Resend Token // End For Resend Token
if (!otpToken) { if (!otpToken) {
return ( return (
<RequestOtp <RequestOtp
setOtpToken={setOtpToken} setOtpToken={setOtpToken}
PhoneNumber={PhoneNumber} PhoneNumber={PhoneNumber}
setPhoneNumber={setPhoneNumber} setPhoneNumber={setPhoneNumber}
setTimer={setTimer} setTimer={setTimer}
initialTimerValue={initialTimerValue} initialTimerValue={initialTimerValue}
/> />
); );
} else { } else {
return ( return (
<UserRegister <UserRegister
PhoneNumber={PhoneNumber} PhoneNumber={PhoneNumber}
setOtpToken={setOtpToken} setOtpToken={setOtpToken}
timer={timer} timer={timer}
setTimer={setTimer} setTimer={setTimer}
initialTimerValue={initialTimerValue} initialTimerValue={initialTimerValue}
/> />
); );
} }
}; };
export default NavyComponent; export default NavyComponent;

View File

@@ -1,116 +1,116 @@
import MuiLink from "@mui/material/Link"; import MuiLink from "@mui/material/Link";
import { styled } from "@mui/material/styles"; import {styled} from "@mui/material/styles";
import clsx from "clsx"; import clsx from "clsx";
import NextLink from "next/link"; import NextLink from "next/link";
import { useRouter } from "next/router"; import {useRouter} from "next/router";
import * as React from "react"; import * as React from "react";
// Add support for the sx prop for consistency with the other branches. // Add support for the sx prop for consistency with the other branches.
const Anchor = styled("a")({}); const Anchor = styled("a")({});
export const NextLinkComposed = React.forwardRef(function NextLinkComposed( export const NextLinkComposed = React.forwardRef(function NextLinkComposed(
props, props,
ref ref
) { ) {
const { const {
to, to,
linkAs, linkAs,
replace, replace,
scroll, scroll,
shallow, shallow,
prefetch, prefetch,
legacyBehavior = true, legacyBehavior = true,
locale, locale,
...other ...other
} = props; } = props;
return ( return (
<NextLink <NextLink
href={to} href={to}
prefetch={prefetch} prefetch={prefetch}
as={linkAs} as={linkAs}
replace={replace} replace={replace}
scroll={scroll} scroll={scroll}
shallow={shallow} shallow={shallow}
passHref passHref
locale={locale} locale={locale}
legacyBehavior={legacyBehavior} legacyBehavior={legacyBehavior}
> >
<Anchor ref={ref} {...other} /> <Anchor ref={ref} {...other} />
</NextLink> </NextLink>
); );
}); });
// A styled version of the Next.js Link component: // A styled version of the Next.js Link component:
// https://nextjs.org/docs/api-reference/next/link // https://nextjs.org/docs/api-reference/next/link
const LinkRouting = React.forwardRef(function Link(props, ref) { const LinkRouting = React.forwardRef(function Link(props, ref) {
const { const {
activeClassName = "active", activeClassName = "active",
as, as,
className: classNameProps, className: classNameProps,
href, href,
legacyBehavior, legacyBehavior,
linkAs: linkAsProp, linkAs: linkAsProp,
locale, locale,
noLinkStyle, noLinkStyle,
prefetch, prefetch,
replace, replace,
role, // Link don't have roles. role, // Link don't have roles.
scroll, scroll,
shallow, shallow,
...other ...other
} = props; } = props;
const router = useRouter(); const router = useRouter();
const pathname = typeof href === "string" ? href : href.pathname; const pathname = typeof href === "string" ? href : href.pathname;
const className = clsx(classNameProps, { const className = clsx(classNameProps, {
[activeClassName]: router.pathname === pathname && activeClassName, [activeClassName]: router.pathname === pathname && activeClassName,
}); });
const isExternal = const isExternal =
typeof href === "string" && typeof href === "string" &&
(href.indexOf("http") === 0 || href.indexOf("mailto:") === 0); (href.indexOf("http") === 0 || href.indexOf("mailto:") === 0);
if (isExternal) { if (isExternal) {
if (noLinkStyle) { if (noLinkStyle) {
return <Anchor className={className} href={href} ref={ref} {...other} />; return <Anchor className={className} href={href} ref={ref} {...other} />;
}
return <MuiLink className={className} href={href} ref={ref} {...other} />;
} }
return <MuiLink className={className} href={href} ref={ref} {...other} />; const linkAs = linkAsProp || as;
} const nextjsProps = {
to: href,
linkAs,
replace,
scroll,
shallow,
prefetch,
legacyBehavior,
locale,
};
const linkAs = linkAsProp || as; if (noLinkStyle) {
const nextjsProps = { return (
to: href, <NextLinkComposed
linkAs, className={className}
replace, ref={ref}
scroll, {...nextjsProps}
shallow, {...other}
prefetch, />
legacyBehavior, );
locale, }
};
if (noLinkStyle) {
return ( return (
<NextLinkComposed <MuiLink
className={className} component={NextLinkComposed}
ref={ref} className={className}
{...nextjsProps} ref={ref}
{...other} {...nextjsProps}
/> {...other}
/>
); );
}
return (
<MuiLink
component={NextLinkComposed}
className={className}
ref={ref}
{...nextjsProps}
{...other}
/>
);
}); });
export default LinkRouting; export default LinkRouting;

View File

@@ -1,44 +1,44 @@
import { Backdrop, Fade, styled } from "@mui/material"; import {Backdrop, Fade, styled} from "@mui/material";
import StyledImage from "./StyledImage"; import StyledImage from "./StyledImage";
const LoadingImage = styled(StyledImage)({ const LoadingImage = styled(StyledImage)({
"@keyframes load": { "@keyframes load": {
"0%": { "0%": {
// opacity: 0, // opacity: 0,
transform: "scale(1)", transform: "scale(1)",
},
"50%": {
// opacity: 1,
transform: "scale(2)",
},
"100%": {
// opacity: 0,
transform: "scale(1)",
},
}, },
"50%": { animation: "load 2s infinite",
// opacity: 1,
transform: "scale(2)",
},
"100%": {
// opacity: 0,
transform: "scale(1)",
},
},
animation: "load 2s infinite",
}); });
const LoadingHardPage = ({ children, loading }) => { const LoadingHardPage = ({children, loading}) => {
return ( return (
<> <>
<Backdrop <Backdrop
sx={{ bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1 }} sx={{bgcolor: "#fff", zIndex: (theme) => theme.zIndex.drawer + 1}}
open={loading} open={loading}
> >
<Fade in={true}> <Fade in={true}>
<LoadingImage <LoadingImage
src={"/images/loading.svg"} src={"/images/loading.svg"}
alt="loading marhaba" alt="loading marhaba"
priority priority
width={100} width={100}
height={100} height={100}
/> />
</Fade> </Fade>
</Backdrop> </Backdrop>
{children} {children}
</> </>
); );
}; };
export default LoadingHardPage; export default LoadingHardPage;

View File

@@ -2,22 +2,22 @@ import CenterLayout from "@/layouts/CenterLayout";
import FullPageLayout from "@/layouts/FullPageLayout"; import FullPageLayout from "@/layouts/FullPageLayout";
import StyledImage from "./StyledImage"; import StyledImage from "./StyledImage";
const Message = ({ text, actions }) => { const Message = ({text, actions}) => {
return ( return (
<FullPageLayout sx={{ p: 1 }}> <FullPageLayout sx={{p: 1}}>
<CenterLayout spacing={3}> <CenterLayout spacing={3}>
<StyledImage <StyledImage
src={"/images/loading.svg"} src={"/images/loading.svg"}
alt="loading loan facilities" alt="loading loan facilities"
width={100} width={100}
height={100} height={100}
priority priority
/> />
{text} {text}
{actions} {actions}
</CenterLayout> </CenterLayout>
</FullPageLayout> </FullPageLayout>
); );
}; };
export default Message; export default Message;

View File

@@ -1,33 +1,33 @@
import { useState } from "react"; import {useState} from "react";
import { IconButton, InputAdornment, TextField } from "@mui/material"; import {IconButton, InputAdornment, TextField} from "@mui/material";
import { Visibility, VisibilityOff } from "@mui/icons-material"; import {Visibility, VisibilityOff} from "@mui/icons-material";
import { Field } from "formik"; import {Field} from "formik";
const PasswordField = (props) => { const PasswordField = (props) => {
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState(false);
const handleClickShowPassword = () => { const handleClickShowPassword = () => {
setShowPassword(!showPassword); setShowPassword(!showPassword);
}; };
return ( return (
<Field <Field
variant="outlined" variant="outlined"
fullWidth fullWidth
as={TextField} as={TextField}
{...props} {...props}
type={showPassword ? "text" : "password"} type={showPassword ? "text" : "password"}
InputProps={{ InputProps={{
endAdornment: ( endAdornment: (
<InputAdornment position="end"> <InputAdornment position="end">
<IconButton onClick={handleClickShowPassword}> <IconButton onClick={handleClickShowPassword}>
{showPassword ? <Visibility /> : <VisibilityOff />} {showPassword ? <Visibility/> : <VisibilityOff/>}
</IconButton> </IconButton>
</InputAdornment> </InputAdornment>
), ),
}} }}
/> />
); );
}; };
export default PasswordField; export default PasswordField;

View File

@@ -1,72 +1,72 @@
import Notifications from "@/core/components/notifications"; import Notifications from "@/core/components/notifications";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
import { Button, Typography } from "@mui/material"; import {Button} from "@mui/material";
import axios from "axios"; import axios from "axios";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import { useEffect } from "react"; import {useEffect} from "react";
import { SEND_OTP_TOKEN } from "../data/apiRoutes"; import {SEND_OTP_TOKEN} from "../data/apiRoutes";
const ResendToken = ({ initialTimerValue, timer, setTimer, PhoneNumber }) => { const ResendToken = ({initialTimerValue, timer, setTimer, PhoneNumber}) => {
const t = useTranslations(); const t = useTranslations();
const { directionApp } = useDirection(); const {directionApp} = useDirection();
// Countdown Timer // Countdown Timer
useEffect(() => { useEffect(() => {
let interval; let interval;
if (timer > 0) { if (timer > 0) {
interval = setInterval(() => { interval = setInterval(() => {
setTimer((prevTimer) => prevTimer - 1); setTimer((prevTimer) => prevTimer - 1);
}, 1000); }, 1000);
} else { } else {
clearInterval(interval); clearInterval(interval);
} }
return () => clearInterval(interval); return () => clearInterval(interval);
}, [timer]); }, [timer]);
// End Countdown Timer // End Countdown Timer
// Handle Resend Token // Handle Resend Token
const handleResendClick = async () => { const handleResendClick = async () => {
// work on it // work on it
if (timer != 0) return; if (timer != 0) return;
Notifications(directionApp, t, undefined); Notifications(directionApp, t, undefined);
await axios await axios
.post(SEND_OTP_TOKEN, { .post(SEND_OTP_TOKEN, {
phone_number: PhoneNumber, phone_number: PhoneNumber,
}) })
.then(function (response) { .then(function (response) {
Notifications(directionApp, t, response); Notifications(directionApp, t, response);
setTimer(initialTimerValue); setTimer(initialTimerValue);
}) })
.catch(function (error) { .catch(function (error) {
Notifications(directionApp, t, error.response); Notifications(directionApp, t, error.response);
}); });
}; };
// End Handle Resend Token // End Handle Resend Token
return ( return (
<> <>
{timer > 0 ? ( {timer > 0 ? (
<Button <Button
color="success" color="success"
disabled disabled
sx={{ width: "auto", alignSelf: "center", mt: 0 }} sx={{width: "auto", alignSelf: "center", mt: 0}}
onClick={handleResendClick} onClick={handleResendClick}
> >
{t("Resend_code_in")} {timer} {" "} {t("Resend_code_in")} {timer} {" "}
{t("seconds_later")} {t("seconds_later")}
</Button> </Button>
) : ( ) : (
<Button <Button
color="success" color="success"
sx={{ width: "120px", alignSelf: "center", mt: 0 }} sx={{width: "120px", alignSelf: "center", mt: 0}}
onClick={handleResendClick} onClick={handleResendClick}
> >
{t("resend_code")} {t("resend_code")}
</Button> </Button>
)} )}
</> </>
); );
}; };
export default ResendToken; export default ResendToken;

View File

@@ -1,55 +1,49 @@
import { import {FormControl, FormHelperText, InputLabel, MenuItem, Select,} from "@mui/material";
FormControl,
FormHelperText,
InputLabel,
MenuItem,
Select,
} from "@mui/material";
function SelectBox({ function SelectBox({
select, select,
selectType, selectType,
selectors, selectors,
label, label,
setFieldValue, setFieldValue,
setFieldTouched, setFieldTouched,
error, error,
helperText, helperText,
}) { }) {
const handleChange = (event) => { const handleChange = (event) => {
setFieldValue(selectType, event.target.value); setFieldValue(selectType, event.target.value);
}; };
const handleBlur = () => { const handleBlur = () => {
setFieldTouched(select, true); setFieldTouched(select, true);
}; };
return ( return (
<FormControl <FormControl
variant="outlined" variant="outlined"
margin="normal" margin="normal"
fullWidth fullWidth
size="small" size="small"
error={error} error={error}
> >
<InputLabel id="language-label">{label}</InputLabel> <InputLabel id="language-label">{label}</InputLabel>
<Select <Select
labelId="language-label" labelId="language-label"
id={select} id={select}
name={select} name={select}
size="small" size="small"
value={select} value={select}
onChange={handleChange} onChange={handleChange}
label="Language" label="Language"
onBlur={handleBlur} onBlur={handleBlur}
> >
{selectors.map((selector) => ( {selectors.map((selector) => (
<MenuItem key={selector.id} value={selector.value}> <MenuItem key={selector.id} value={selector.value}>
{selector.name} {selector.name}
</MenuItem> </MenuItem>
))} ))}
</Select> </Select>
<FormHelperText>{helperText}</FormHelperText> <FormHelperText>{helperText}</FormHelperText>
</FormControl> </FormControl>
); );
} }
export default SelectBox; export default SelectBox;

View File

@@ -1,5 +1,5 @@
import { styled } from "@mui/material"; import {styled} from "@mui/material";
import { Form } from "formik"; import {Form} from "formik";
const StyledForm = styled(Form)``; const StyledForm = styled(Form)``;

View File

@@ -1,4 +1,4 @@
import { styled } from "@mui/material"; import {styled} from "@mui/material";
import Image from "next/image"; import Image from "next/image";
const StyledImage = styled(Image)``; const StyledImage = styled(Image)``;

View File

@@ -1,15 +1,15 @@
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import Head from "next/head"; import Head from "next/head";
const TitlePage = ({ text }) => { const TitlePage = ({text}) => {
const t = useTranslations(); const t = useTranslations();
return ( return (
<Head> <Head>
<title> <title>
{text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")} {text ? `${t("app_short_name")} | ${t(text)}` : t("app_short_name")}
</title> </title>
</Head> </Head>
); );
}; };
export default TitlePage; export default TitlePage;

View File

@@ -1,148 +1,147 @@
import { Box, Button, TextField, Typography } from "@mui/material"; import {Box, Button, TextField, Typography} from "@mui/material";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import Image from "next/image"; import Image from "next/image";
import DeleteForeverIcon from "@mui/icons-material/DeleteForever"; import DeleteForeverIcon from "@mui/icons-material/DeleteForever";
import { useRef } from "react"; import {useRef} from "react";
const UploadSystem = ({ const UploadSystem = ({
selectedImage, selectedImage,
setselectedImage, setselectedImage,
handleUploadChange, handleUploadChange,
fieldname, fieldname,
setFieldValue, setFieldValue,
imageAlt, imageAlt,
imageSize, imageSize,
fileType, fileType,
fileName, fileName,
label, label,
}) => { }) => {
const t = useTranslations(); const t = useTranslations();
const fileInputRef = useRef(null); const fileInputRef = useRef(null);
const handleClick = () => { const handleClick = () => {
fileInputRef.current.click(); fileInputRef.current.click();
}; };
const handleDeleteImage = () => { const handleDeleteImage = () => {
setselectedImage("/images/upload-image.svg"); setselectedImage("/images/upload-image.svg");
setFieldValue(fieldname, null); setFieldValue(fieldname, null);
}; };
const isDocumentFormat = (fileType) => { const isDocumentFormat = (fileType) => {
const documentFormats = [ const documentFormats = [
"application/pdf", "application/pdf",
"application/msword", "application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document", "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-excel", "application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
]; ];
return documentFormats.includes(fileType); return documentFormats.includes(fileType);
}; };
return ( return (
<Box sx={{ width: imageSize[0], my: 2 }}> <Box sx={{width: imageSize[0], my: 2}}>
<Typography
margin={2}
sx={{
fontWeight: 500,
fontSize: "1rem",
color: "#a19d9d",
}}
textAlign="center"
>
{label}
</Typography>
{selectedImage === "/images/upload-image.svg" ? (
<Image
width={imageSize[0]}
height={imageSize[1]}
src={selectedImage}
priority
alt={imageAlt}
onClick={handleClick}
style={{
cursor: "pointer",
objectFit: "contain",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
padding: "5px",
}}
/>
) : fileType && fileType.startsWith("image/") ? (
<Image
width={imageSize[0]}
height={imageSize[1]}
src={selectedImage}
priority
alt={imageAlt}
onClick={handleClick}
style={{
cursor: "pointer",
objectFit: "contain",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
padding: "5px",
}}
/>
) : (
fileType &&
isDocumentFormat(fileType) && (
<Box
sx={{
width: imageSize[0],
height: imageSize[1],
display: "flex",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
alignItems: "center",
justifyContent: "center",
}}
onClick={handleClick}
>
<Typography <Typography
margin={2} margin={2}
sx={{ sx={{
fontWeight: 600, fontWeight: 500,
fontSize: "1rem", fontSize: "1rem",
color: "#a19d9d", color: "#a19d9d",
}} }}
textAlign="center" textAlign="center"
> >
{fileName} {label}
</Typography> </Typography>
</Box> {selectedImage === "/images/upload-image.svg" ? (
) <Image
)} width={imageSize[0]}
height={imageSize[1]}
src={selectedImage}
priority
alt={imageAlt}
onClick={handleClick}
style={{
cursor: "pointer",
objectFit: "contain",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
padding: "5px",
}}
/>
) : fileType && fileType.startsWith("image/") ? (
<Image
width={imageSize[0]}
height={imageSize[1]}
src={selectedImage}
priority
alt={imageAlt}
onClick={handleClick}
style={{
cursor: "pointer",
objectFit: "contain",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
padding: "5px",
}}
/>
) : (
fileType &&
isDocumentFormat(fileType) && (
<Box
sx={{
width: imageSize[0],
height: imageSize[1],
display: "flex",
border: "1px dashed #e1e1e1",
borderBottom: "unset",
alignItems: "center",
justifyContent: "center",
}}
onClick={handleClick}
>
<Typography
margin={2}
sx={{
fontWeight: 600,
fontSize: "1rem",
color: "#a19d9d",
}}
textAlign="center"
>
{fileName}
</Typography>
</Box>
)
)}
<TextField <TextField
id="avatar-upload" id="avatar-upload"
type="file" type="file"
accept="image/*" accept="image/*"
style={{ display: "none" }} style={{display: "none"}}
onChange={handleUploadChange} onChange={handleUploadChange}
inputRef={fileInputRef} inputRef={fileInputRef}
/> />
<Button <Button
sx={{ sx={{
width: "100%", width: "100%",
borderTopLeftRadius: "unset", borderTopLeftRadius: "unset",
borderTopRightRadius: "unset", borderTopRightRadius: "unset",
}} }}
color="error" color="error"
disabled={selectedImage === "/images/upload-image.svg"} disabled={selectedImage === "/images/upload-image.svg"}
endIcon={<DeleteForeverIcon />} endIcon={<DeleteForeverIcon/>}
variant="contained" variant="contained"
onClick={handleDeleteImage} onClick={handleDeleteImage}
> >
{t("delete")} {t("delete")}
</Button> </Button>
</Box> </Box>
); );
}; };
export default UploadSystem; export default UploadSystem;
//////****** usage document ******///////// //////****** usage document ******/////////
// 1.) use <UploadSystem /> component inside your page // 1.) use <UploadSystem /> component inside your page
// 2.) list of props that you need to send is down below // 2.) list of props that you need to send is down below

View File

@@ -1,8 +1,8 @@
import { NoSsr } from "@mui/material"; import {NoSsr} from "@mui/material";
const NoSsrHandler = ({ isBot, children }) => { const NoSsrHandler = ({isBot, children}) => {
if (isBot) return children; if (isBot) return children;
return <NoSsr>{children}</NoSsr>; return <NoSsr>{children}</NoSsr>;
}; };
export default NoSsrHandler; export default NoSsrHandler;

View File

@@ -1,40 +1,40 @@
import DangerousIcon from "@mui/icons-material/Dangerous"; import DangerousIcon from "@mui/icons-material/Dangerous";
import { Box, Typography } from "@mui/material"; import {Box, Typography} from "@mui/material";
import { toast } from "react-toastify"; import {toast} from "react-toastify";
const ErrorNotification = (directionApp, t, status, message) => { const ErrorNotification = (directionApp, t, status, message) => {
toast( toast(
({ closeToast }) => ( ({closeToast}) => (
<> <>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
alignItems: "start", alignItems: "start",
justifyContent: "start", justifyContent: "start",
}} }}
> >
<Box sx={{ display: "flex", alignItems: "center" }}> <Box sx={{display: "flex", alignItems: "center"}}>
<DangerousIcon color="error" sx={{ mr: 1.6 }} /> <DangerousIcon color="error" sx={{mr: 1.6}}/>
<Box sx={{ display: "flex", flexDirection: "column" }}> <Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="error" variant="button"> <Typography color="error" variant="button">
{t("notifications.error")} ({t("notifications.code")}: {status}) {t("notifications.error")} ({t("notifications.code")}: {status})
</Typography> </Typography>
<Typography variant="caption"> <Typography variant="caption">
{message || t("notifications.error_static_text")} {message || t("notifications.error_static_text")}
</Typography> </Typography>
</Box> </Box>
</Box> </Box>
</Box> </Box>
</> </>
), ),
{ {
position: directionApp === "ltr" ? "top-left" : "top-right", position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false, autoClose: false,
closeOnClick: false, closeOnClick: false,
draggable: false, draggable: false,
} }
); );
}; };
export default ErrorNotification; export default ErrorNotification;

View File

@@ -1,43 +1,43 @@
import BeenhereIcon from "@mui/icons-material/Beenhere"; import BeenhereIcon from "@mui/icons-material/Beenhere";
import { Box, Typography } from "@mui/material"; import {Box, Typography} from "@mui/material";
import { toast } from "react-toastify"; import {toast} from "react-toastify";
const SuccessNotification = (directionApp, t, status) => { const SuccessNotification = (directionApp, t, status) => {
toast( toast(
() => ( () => (
<> <>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
alignItems: "start", alignItems: "start",
justifyContent: "start", justifyContent: "start",
}} }}
> >
<Box sx={{ display: "flex", alignItems: "center" }}> <Box sx={{display: "flex", alignItems: "center"}}>
<BeenhereIcon color="success" sx={{ mr: 1.6 }} /> <BeenhereIcon color="success" sx={{mr: 1.6}}/>
<Box sx={{ display: "flex", flexDirection: "column" }}> <Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="success.main" variant="button"> <Typography color="success.main" variant="button">
{t("notifications.success")} ({t("notifications.code")}:{" "} {t("notifications.success")} ({t("notifications.code")}:{" "}
{status}) {status})
</Typography> </Typography>
<Typography variant="caption"> <Typography variant="caption">
{t("notifications.success_static_text")} {t("notifications.success_static_text")}
</Typography> </Typography>
</Box> </Box>
</Box> </Box>
</Box> </Box>
</> </>
), ),
{ {
position: directionApp === "ltr" ? "top-left" : "top-right", position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: 3000, autoClose: 3000,
hideProgressBar: true, hideProgressBar: true,
pauseOnHover: true, pauseOnHover: true,
closeOnClick: false, closeOnClick: false,
draggable: true, draggable: true,
} }
); );
}; };
export default SuccessNotification; export default SuccessNotification;

View File

@@ -1,41 +1,41 @@
import ReportIcon from "@mui/icons-material/Report"; import ReportIcon from "@mui/icons-material/Report";
import { Box, Divider, Typography } from "@mui/material"; import {Box, Divider, Typography} from "@mui/material";
import { toast } from "react-toastify"; import {toast} from "react-toastify";
const WarningNotification = (directionApp, t, status) => { const WarningNotification = (directionApp, t, status) => {
toast( toast(
({ closeToast }) => ( ({closeToast}) => (
<> <>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
alignItems: "start", alignItems: "start",
justifyContent: "start", justifyContent: "start",
}} }}
> >
<Box sx={{ display: "flex", alignItems: "center" }}> <Box sx={{display: "flex", alignItems: "center"}}>
<ReportIcon color="warning" sx={{ mr: 1.6 }} /> <ReportIcon color="warning" sx={{mr: 1.6}}/>
<Box sx={{ display: "flex", flexDirection: "column" }}> <Box sx={{display: "flex", flexDirection: "column"}}>
<Typography color="warning.main" variant="button"> <Typography color="warning.main" variant="button">
{t("warning")} ({t("code")}: {status}) {t("warning")} ({t("code")}: {status})
</Typography> </Typography>
<Typography variant="caption"> <Typography variant="caption">
{t("warning_static_text")} {t("warning_static_text")}
</Typography> </Typography>
</Box> </Box>
</Box> </Box>
</Box> </Box>
<Divider sx={{ my: 1 }} /> <Divider sx={{my: 1}}/>
</> </>
), ),
{ {
position: directionApp === "ltr" ? "top-left" : "top-right", position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false, autoClose: false,
closeOnClick: false, closeOnClick: false,
draggable: false, draggable: false,
} }
); );
}; };
export default WarningNotification; export default WarningNotification;

View File

@@ -1,45 +1,45 @@
import { toast } from "react-toastify"; import {toast} from "react-toastify";
import ErrorNotification from "./ErrorNotification"; import ErrorNotification from "./ErrorNotification";
import SuccessNotification from "./SuccessNotification"; import SuccessNotification from "./SuccessNotification";
import WarningNotification from "./WarningNotification"; import WarningNotification from "./WarningNotification";
const Notifications = async (directionApp, t, response) => { const Notifications = async (directionApp, t, response) => {
const { status, data } = response != undefined ? response : "" const {status, data} = response != undefined ? response : ""
toast.dismiss(); toast.dismiss();
switch (status) { switch (status) {
case 200: case 200:
SuccessNotification(directionApp, t, status); SuccessNotification(directionApp, t, status);
break; break;
case 400: case 400:
ErrorNotification(directionApp, t,status); ErrorNotification(directionApp, t, status);
break; break;
case 401: case 401:
ErrorNotification(directionApp, t, status); ErrorNotification(directionApp, t, status);
break; break;
case 403: case 403:
ErrorNotification(directionApp, t, status); ErrorNotification(directionApp, t, status);
break; break;
case 422: case 422:
ErrorNotification(directionApp, t, status, data.message); ErrorNotification(directionApp, t, status, data.message);
break; break;
case 500: case 500:
WarningNotification(directionApp, t, status); WarningNotification(directionApp, t, status);
break; break;
case 503: case 503:
WarningNotification(directionApp, t, status); WarningNotification(directionApp, t, status);
break; break;
case 504: case 504:
WarningNotification(directionApp, t, status); WarningNotification(directionApp, t, status);
break; break;
default: default:
toast(t("pending"), { toast(t("pending"), {
position: directionApp === "ltr" ? "top-left" : "top-right", position: directionApp === "ltr" ? "top-left" : "top-right",
autoClose: false, autoClose: false,
closeOnClick: false, closeOnClick: false,
draggable: false, draggable: false,
}); });
break; break;
} }
}; };
export default Notifications; export default Notifications;

View File

@@ -1,7 +1,3 @@
import BorderColorIcon from "@mui/icons-material/BorderColor"; const headerProfileItems = [];
import PasswordIcon from "@mui/icons-material/Password";
const headerProfileItems = [
];
export default headerProfileItems; export default headerProfileItems;

View File

@@ -3,29 +3,29 @@ import BookmarkAddedIcon from "@mui/icons-material/BookmarkAdded";
import DataSaverOnIcon from "@mui/icons-material/DataSaverOn"; import DataSaverOnIcon from "@mui/icons-material/DataSaverOn";
const sidebarMenu = [ const sidebarMenu = [
[ [
{ {
key: "sidebar.dashboard", key: "sidebar.dashboard",
type: "page", type: "page",
route: "/dashboard", route: "/dashboard",
icon: <SpaceDashboardIcon />, icon: <SpaceDashboardIcon/>,
selected: false, selected: false,
}, },
{ {
key: "sidebar.loan-request", key: "sidebar.loan-request",
type: "page", type: "page",
route: "/dashboard/loan-request", route: "/dashboard/loan-request",
icon: <DataSaverOnIcon />, icon: <DataSaverOnIcon/>,
selected: false, selected: false,
}, },
{ {
key: "sidebar.loan-follow-up", key: "sidebar.loan-follow-up",
type: "page", type: "page",
route: "/dashboard/loan-follow-up", route: "/dashboard/loan-follow-up",
icon: <BookmarkAddedIcon />, icon: <BookmarkAddedIcon/>,
selected: false, selected: false,
}, },
], ],
]; ];
export default sidebarMenu; export default sidebarMenu;

View File

@@ -1,38 +1,38 @@
import createCache from "@emotion/cache"; import createCache from "@emotion/cache";
import { prefixer } from "stylis"; import {prefixer} from "stylis";
import stylisRTLPlugin from "stylis-plugin-rtl"; import stylisRTLPlugin from "stylis-plugin-rtl";
const isBrowser = typeof document !== "undefined"; const isBrowser = typeof document !== "undefined";
export const createEmotionCacheLtr = () => { export const createEmotionCacheLtr = () => {
let insertionPoint; let insertionPoint;
if (isBrowser) { if (isBrowser) {
const emotionInsertionPoint = document.querySelector( const emotionInsertionPoint = document.querySelector(
'meta[name="emotion-insertion-point"]' 'meta[name="emotion-insertion-point"]'
); );
insertionPoint = emotionInsertionPoint ?? undefined; insertionPoint = emotionInsertionPoint ?? undefined;
} }
return createCache({ return createCache({
key: "mui-style", key: "mui-style",
insertionPoint, insertionPoint,
}); });
}; };
export const createEmotionCacheRtl = () => { export const createEmotionCacheRtl = () => {
let insertionPoint; let insertionPoint;
if (isBrowser) { if (isBrowser) {
const emotionInsertionPoint = document.querySelector( const emotionInsertionPoint = document.querySelector(
'meta[name="emotion-insertion-point"]' 'meta[name="emotion-insertion-point"]'
); );
insertionPoint = emotionInsertionPoint ?? undefined; insertionPoint = emotionInsertionPoint ?? undefined;
} }
return createCache({ return createCache({
key: "muirtl", key: "muirtl",
stylisPlugins: [prefixer, stylisRTLPlugin], stylisPlugins: [prefixer, stylisRTLPlugin],
insertionPoint, insertionPoint,
}); });
}; };

View File

@@ -1,12 +1,12 @@
import { createTheme } from "@mui/material/styles"; import {createTheme} from "@mui/material/styles";
import theme from "./theme"; import theme from "./theme";
const themeRtl = createTheme({ const themeRtl = createTheme({
direction: "rtl", direction: "rtl",
typography: { typography: {
fontFamily: `IRANSans, sans-serif`, fontFamily: `IRANSans, sans-serif`,
}, },
...theme, ...theme,
}); });
export default themeRtl; export default themeRtl;

View File

@@ -1,18 +1,18 @@
const theme = { const theme = {
palette: { palette: {
primary: { primary: {
main: "#084070", main: "#084070",
contrastText: "#fff", contrastText: "#fff",
light: "#2c6291", light: "#2c6291",
dark: "#11293e", dark: "#11293e",
},
secondary: {
main: "#FF4E00",
contrastText: "#fff",
light: "#ed743e",
dark: "#ad3a07",
},
}, },
secondary: {
main: "#FF4E00",
contrastText: "#fff",
light: "#ed743e",
dark: "#ad3a07",
},
},
}; };
export default theme; export default theme;

View File

@@ -4,96 +4,96 @@ import useLoading from "@/lib/app/hooks/useLoading";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import Head from "next/head"; import Head from "next/head";
import NextNProgress from "nextjs-progressbar"; import NextNProgress from "nextjs-progressbar";
import { useEffect } from "react"; import {useEffect} from "react";
function AppLayout({ children, isBot }) { function AppLayout({children, isBot}) {
const { languageIsReady } = useLanguage(); const {languageIsReady} = useLanguage();
const { setLoadingPage } = useLoading(); const {setLoadingPage} = useLoading();
const { userChangedLanguage, token, isAuth } = useUser(); const {userChangedLanguage, token, isAuth} = useUser();
useEffect(() => { useEffect(() => {
if (languageIsReady) { if (languageIsReady) {
if (token) { if (token) {
if (isAuth) { if (isAuth) {
if (userChangedLanguage) { if (userChangedLanguage) {
setLoadingPage(true); setLoadingPage(true);
return;
}
setLoadingPage(false);
return;
}
setLoadingPage(true);
return;
}
setLoadingPage(false);
return; return;
}
setLoadingPage(false);
return;
} }
setLoadingPage(true); setLoadingPage(true);
return; }, [languageIsReady, token, isAuth, userChangedLanguage]);
}
setLoadingPage(false); if (!isBot) {
return; if (userChangedLanguage) return;
if (!languageIsReady) return;
} }
setLoadingPage(true);
}, [languageIsReady, token, isAuth, userChangedLanguage]);
if (!isBot) { return (
if (userChangedLanguage) return; <>
if (!languageIsReady) return; <Head>
} <meta
name="application-name"
return ( content={process.env.NEXT_PUBLIC_API_NAME}
<> />
<Head> <meta name="apple-mobile-web-app-capable" content="yes"/>
<meta <meta
name="application-name" name="apple-mobile-web-app-status-bar-style"
content={process.env.NEXT_PUBLIC_API_NAME} content="black-translucent"
/> />
<meta name="apple-mobile-web-app-capable" content="yes" /> <meta
<meta name="apple-mobile-web-app-title"
name="apple-mobile-web-app-status-bar-style" content={process.env.NEXT_PUBLIC_API_NAME}
content="black-translucent" />
/> <meta name="description" content="Marhaba does it for you"/>
<meta <meta name="format-detection" content="telephone=no"/>
name="apple-mobile-web-app-title" <meta name="format-detection" content="date=no"/>
content={process.env.NEXT_PUBLIC_API_NAME} <meta name="format-detection" content="address=no"/>
/> <meta name="format-detection" content="email=no"/>
<meta name="description" content="Marhaba does it for you" /> <meta name="mobile-web-app-capable" content="yes"/>
<meta name="format-detection" content="telephone=no" /> <link rel="apple-touch-icon" href="/icons/maskable_icon_x512.png"/>
<meta name="format-detection" content="date=no" /> <link
<meta name="format-detection" content="address=no" /> rel="apple-touch-icon"
<meta name="format-detection" content="email=no" /> sizes="120x120"
<meta name="mobile-web-app-capable" content="yes" /> href="/icons/maskable_icon_x128.png"
<link rel="apple-touch-icon" href="/icons/maskable_icon_x512.png" /> />
<link <link
rel="apple-touch-icon" rel="apple-touch-icon"
sizes="120x120" sizes="180x180"
href="/icons/maskable_icon_x128.png" href="/icons/maskable_icon_x192.png"
/> />
<link <meta name="google" content="notranslate"/>
rel="apple-touch-icon" <meta name="robots" content="noindex"/>
sizes="180x180" <meta
href="/icons/maskable_icon_x192.png" name="viewport"
/> content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
<meta name="google" content="notranslate" /> />
<meta name="robots" content="noindex" /> <link
<meta rel="icon"
name="viewport" type="image/svg"
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover" sizes="32x32"
/> href="/images/logo.png"
<link />
rel="icon" <link
type="image/svg" rel="icon"
sizes="32x32" type="image/svg"
href="/images/logo.png" sizes="16x16"
/> href="/images/logo.png"
<link />
rel="icon" </Head>
type="image/svg" <NextNProgress
sizes="16x16" color={theme.palette.secondary.dark}
href="/images/logo.png" options={{showSpinner: false}}
/> />
</Head> {children}
<NextNProgress </>
color={theme.palette.secondary.dark} );
options={{ showSpinner: false }}
/>
{children}
</>
);
} }
export default AppLayout; export default AppLayout;

View File

@@ -1,18 +1,18 @@
import { Fade, Stack } from "@mui/material"; import {Fade, Stack} from "@mui/material";
const CenterLayout = (props) => { const CenterLayout = (props) => {
return ( return (
<Fade in={true}> <Fade in={true}>
<Stack <Stack
alignItems="center" alignItems="center"
justifyContent="center" justifyContent="center"
spacing={props?.spacing} spacing={props?.spacing}
sx={{ flex: 1, ...props?.sx, py: 3 }} sx={{flex: 1, ...props?.sx, py: 3}}
> >
{props.children} {props.children}
</Stack> </Stack>
</Fade> </Fade>
); );
}; };
export default CenterLayout; export default CenterLayout;

View File

@@ -1,21 +1,21 @@
import { Stack } from "@mui/material"; import {Stack} from "@mui/material";
const FullPageLayout = (props) => { const FullPageLayout = (props) => {
return ( return (
<Stack <Stack
spacing={props?.spacing} spacing={props?.spacing}
direction={props?.direction} direction={props?.direction}
sx={{ sx={{
width: "100%", width: "100%",
height: "100%", height: "100%",
overflowY: "scroll", overflowY: "scroll",
overflowX: "scroll", overflowX: "scroll",
...props?.sx, ...props?.sx,
}} }}
> >
{props.children} {props.children}
</Stack> </Stack>
); );
}; };
export default FullPageLayout; export default FullPageLayout;

View File

@@ -1,76 +1,74 @@
import NoSsrHandler from "@/core/components/isBotHandler"; import NoSsrHandler from "@/core/components/isBotHandler";
import { import {createEmotionCacheRtl} from "@/core/utils/createEmotionCache";
createEmotionCacheRtl
} from "@/core/utils/createEmotionCache";
import themeRtl from "@/core/utils/theme-rtl"; import themeRtl from "@/core/utils/theme-rtl";
import { CacheProvider } from "@emotion/react"; import {CacheProvider} from "@emotion/react";
import { GlobalStyles } from "@mui/material"; import {GlobalStyles} from "@mui/material";
import CssBaseline from "@mui/material/CssBaseline"; import CssBaseline from "@mui/material/CssBaseline";
import { ThemeProvider } from "@mui/material/styles"; import {ThemeProvider} from "@mui/material/styles";
import Head from "next/head"; import Head from "next/head";
const clientSideEmotionCacheRtl = createEmotionCacheRtl(); const clientSideEmotionCacheRtl = createEmotionCacheRtl();
const MuiLayout = ({ children, isBot }) => { const MuiLayout = ({children, isBot}) => {
const emotionCache = clientSideEmotionCacheRtl; const emotionCache = clientSideEmotionCacheRtl;
const theme = themeRtl; const theme = themeRtl;
return ( return (
<NoSsrHandler isBot={isBot}> <NoSsrHandler isBot={isBot}>
<CacheProvider value={emotionCache}> <CacheProvider value={emotionCache}>
<Head> <Head>
<meta name="viewport" content="initial-scale=1, width=device-width" /> <meta name="viewport" content="initial-scale=1, width=device-width"/>
</Head> </Head>
<ThemeProvider theme={theme}> <ThemeProvider theme={theme}>
<GlobalStyles <GlobalStyles
styles={{ styles={{
"*:not(.MuiTableContainer-root)::-webkit-scrollbar": { "*:not(.MuiTableContainer-root)::-webkit-scrollbar": {
display: "none", display: "none",
}, },
"*::-webkit-scrollbar": { "*::-webkit-scrollbar": {
height: "8px", height: "8px",
}, },
"*::-webkit-scrollbar-thumb": { "*::-webkit-scrollbar-thumb": {
background: "#e1e1e1", background: "#e1e1e1",
borderRadius: "3px", borderRadius: "3px",
}, },
"*:not(.MuiTableContainer-root)": { "*:not(.MuiTableContainer-root)": {
scrollbarWidth: "thin", scrollbarWidth: "thin",
scrollbarColor: "transparent transparent", scrollbarColor: "transparent transparent",
}, },
"*": { "*": {
scrollbarWidth: "thin", scrollbarWidth: "thin",
scrollbarColor: "#e1e1e1 transparent", scrollbarColor: "#e1e1e1 transparent",
}, },
"*::-moz-scrollbar-thumb": { "*::-moz-scrollbar-thumb": {
backgroundColor: "#e1e1e1", backgroundColor: "#e1e1e1",
}, },
[`@media (max-width: ${theme.breakpoints.values.sm}px)`]: { [`@media (max-width: ${theme.breakpoints.values.sm}px)`]: {
"*::-webkit-scrollbar": { "*::-webkit-scrollbar": {
height: "4px", height: "4px",
}, },
}, },
body: { body: {
width: "100vw", width: "100vw",
height: "100vh", height: "100vh",
}, },
"#__next": { "#__next": {
width: "100%", width: "100%",
height: "100%", height: "100%",
}, },
}} }}
/> />
<CssBaseline /> <CssBaseline/>
{children} {children}
</ThemeProvider> </ThemeProvider>
</CacheProvider> </CacheProvider>
</NoSsrHandler> </NoSsrHandler>
); );
}; };
export default MuiLayout; export default MuiLayout;

View File

@@ -1,25 +1,25 @@
import { Box, Fade } from "@mui/material"; import {Box, Fade} from "@mui/material";
const ScrollableLayout = (props) => { const ScrollableLayout = (props) => {
const overflowY = props?.y || "hidden"; const overflowY = props?.y || "hidden";
const overflowX = props?.x || "hidden"; const overflowX = props?.x || "hidden";
return ( return (
<Fade in={true}> <Fade in={true}>
<Box <Box
spacing={props?.spacing} spacing={props?.spacing}
sx={{ sx={{
width: "auto", width: "auto",
height: "auto", height: "auto",
overflowY: overflowY, overflowY: overflowY,
overflowX: overflowX, overflowX: overflowX,
...props?.sx, ...props?.sx,
}} }}
> >
{props.children} {props.children}
</Box> </Box>
</Fade> </Fade>
); );
}; };
export default ScrollableLayout; export default ScrollableLayout;

View File

@@ -1,19 +1,19 @@
import LinkRouting from "@/core/components/LinkRouting"; import LinkRouting from "@/core/components/LinkRouting";
import { Typography } from "@mui/material"; import {Typography} from "@mui/material";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
export default function BreadcrumbItem(props) { export default function BreadcrumbItem(props) {
const t = useTranslations(); const t = useTranslations();
const isLast = props.index === props.RouterArray.length - 1; const isLast = props.index === props.RouterArray.length - 1;
const url = `/${props.RouterArray.slice(0, props.index + 1).join("/")}`; const url = `/${props.RouterArray.slice(0, props.index + 1).join("/")}`;
return isLast ? ( return isLast ? (
<Typography variant="body2" color="primary"> <Typography variant="body2" color="primary">
{t("sidebar." + props.label)} {t("sidebar." + props.label)}
</Typography> </Typography>
) : ( ) : (
<LinkRouting underline="hover" color="inherit" passHref href={url}> <LinkRouting underline="hover" color="inherit" passHref href={url}>
<Typography variant="body2">{t("sidebar." + props.label)}</Typography> <Typography variant="body2">{t("sidebar." + props.label)}</Typography>
</LinkRouting> </LinkRouting>
); );
} }

View File

@@ -1,49 +1,49 @@
import { useRouter } from "next/router"; import {useRouter} from "next/router";
import { Box, Breadcrumbs } from "@mui/material"; import {Box, Breadcrumbs} from "@mui/material";
import { useTheme } from "@mui/material/styles"; import {useTheme} from "@mui/material/styles";
import { NavigateBefore, NavigateNext } from "@mui/icons-material"; import {NavigateBefore, NavigateNext} from "@mui/icons-material";
import BreadcrumbItem from "./BreadcrumbItem"; import BreadcrumbItem from "./BreadcrumbItem";
const BreadCrumbs = (props) => { const BreadCrumbs = (props) => {
const { isVisible } = props; const {isVisible} = props;
const theme = useTheme(); const theme = useTheme();
const router = useRouter(); const router = useRouter();
if (!isVisible) { if (!isVisible) {
return null; return null;
} }
const { pathname } = router; const {pathname} = router;
const RouterArray = pathname.split("/").filter((segment) => segment !== ""); const RouterArray = pathname.split("/").filter((segment) => segment !== "");
if (RouterArray.length === 1) { if (RouterArray.length === 1) {
return null; return null;
} }
return ( return (
<Box p={3} component="span"> <Box p={3} component="span">
<Breadcrumbs <Breadcrumbs
maxItems={2} maxItems={2}
separator={ separator={
theme.direction === "ltr" ? ( theme.direction === "ltr" ? (
<NavigateNext fontSize="small" /> <NavigateNext fontSize="small"/>
) : ( ) : (
<NavigateBefore fontSize="small" /> <NavigateBefore fontSize="small"/>
) )
} }
aria-label="breadcrumb" aria-label="breadcrumb"
> >
{RouterArray.map((segment, index) => ( {RouterArray.map((segment, index) => (
<BreadcrumbItem <BreadcrumbItem
RouterArray={RouterArray} RouterArray={RouterArray}
label={segment} label={segment}
key={segment} key={segment}
index={index} index={index}
/> />
))} ))}
</Breadcrumbs> </Breadcrumbs>
</Box> </Box>
); );
}; };
export default BreadCrumbs; export default BreadCrumbs;

View File

@@ -1,15 +1,15 @@
import { Avatar, Stack, Typography } from "@mui/material"; import {Avatar, Stack} from "@mui/material";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
export default function ProfileData() { export default function ProfileData() {
const { user } = useUser(); const {user} = useUser();
return ( return (
<Stack alignItems="center" spacing={2} sx={{ p: 3 }}> <Stack alignItems="center" spacing={2} sx={{p: 3}}>
<Avatar <Avatar
sx={{ width: "80px", height: "80px" }} sx={{width: "80px", height: "80px"}}
alt="User Image" alt="User Image"
src={user.user_avatar} src={user.user_avatar}
/> />
</Stack> </Stack>
); );
} }

View File

@@ -1,61 +1,62 @@
import { Avatar, Menu, IconButton, Tooltip } from "@mui/material"; import {Avatar, IconButton, Menu, Tooltip} from "@mui/material";
import { useState } from "react"; import {useState} from "react";
import ProfileData from "./ProfileData"; import ProfileData from "./ProfileData";
import ProfileOptions from "./ProfileOptions"; import ProfileOptions from "./ProfileOptions";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
function ProfileMenu() { function ProfileMenu() {
const t = useTranslations(); const t = useTranslations();
const [anchorElUser, setAnchorElUser] = useState(null); const [anchorElUser, setAnchorElUser] = useState(null);
const { user } = useUser(); const {user} = useUser();
const handleOpenUserMenu = (event) => { const handleOpenUserMenu = (event) => {
setAnchorElUser(event.currentTarget); setAnchorElUser(event.currentTarget);
}; };
const handleCloseUserMenu = () => { const handleCloseUserMenu = () => {
setAnchorElUser(null); setAnchorElUser(null);
}; };
return ( return (
<> <>
<Tooltip title={t("header.open_profile")} arrow> <Tooltip title={t("header.open_profile")} arrow>
<IconButton onClick={handleOpenUserMenu} sx={{ p: 0 }}> <IconButton onClick={handleOpenUserMenu} sx={{p: 0}}>
<Avatar <Avatar
sx={{ sx={{
width: 24, width: 24,
height: 24, height: 24,
backgroundColor: "#fff", backgroundColor: "#fff",
color: "primary.main", color: "primary.main",
}} }}
alt="User Image" alt="User Image"
src={user.user_avatar} src={user.user_avatar}
/> />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Menu <Menu
MenuListProps={{ sx: { py: 0 } }} MenuListProps={{sx: {py: 0}}}
sx={{ sx={{
mt: 6, mt: 6,
}} }}
id="menu-appbar" id="menu-appbar"
anchorEl={anchorElUser} anchorEl={anchorElUser}
anchorOrigin={{ anchorOrigin={{
vertical: "top", vertical: "top",
horizontal: "right", horizontal: "right",
}} }}
keepMounted keepMounted
transformOrigin={{ transformOrigin={{
vertical: "top", vertical: "top",
horizontal: "right", horizontal: "right",
}} }}
open={Boolean(anchorElUser)} open={Boolean(anchorElUser)}
onClose={handleCloseUserMenu} onClose={handleCloseUserMenu}
> >
<ProfileData /> <ProfileData/>
<ProfileOptions handleCloseUserMenu={handleCloseUserMenu} /> <ProfileOptions handleCloseUserMenu={handleCloseUserMenu}/>
</Menu> </Menu>
</> </>
); );
} }
export default ProfileMenu; export default ProfileMenu;

View File

@@ -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 MeetingRoomIcon from "@mui/icons-material/MeetingRoom";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
export default function ProfileOptionLogOut({ handleCloseUserMenu }) { export default function ProfileOptionLogOut({handleCloseUserMenu}) {
const t = useTranslations(); const t = useTranslations();
const { clearToken } = useUser(); const {clearToken} = useUser();
const handleClickLogOut = () => { const handleClickLogOut = () => {
handleCloseUserMenu(); handleCloseUserMenu();
clearToken(); clearToken();
}; };
return ( return (
<> <>
<MenuItem <MenuItem
component={Button} component={Button}
to={{ to={{
pathname: "/dashboard/logout", pathname: "/dashboard/logout",
}} }}
sx={{ sx={{
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "center",
borderTop: 1, borderTop: 1,
px: 3, px: 3,
py: 1.5, py: 1.5,
borderColor: "#e1e1e1", borderColor: "#e1e1e1",
textTransform: "unset", textTransform: "unset",
}} }}
onClick={handleClickLogOut} onClick={handleClickLogOut}
> >
<Box sx={{ display: "flex", alignItems: "center", flex: 1 }}> <Box sx={{display: "flex", alignItems: "center", flex: 1}}>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
color: "primary.main", color: "primary.main",
pr: 2, pr: 2,
}} }}
> >
<MeetingRoomIcon /> <MeetingRoomIcon/>
</Box> </Box>
<Typography sx={{ flex: 1 }} textAlign="start"> <Typography sx={{flex: 1}} textAlign="start">
{t("header.logout")} {t("header.logout")}
</Typography> </Typography>
</Box> </Box>
</MenuItem> </MenuItem>
</> </>
); );
} }

View File

@@ -1,49 +1,49 @@
import { Box, MenuItem, Typography } from "@mui/material"; import {Box, MenuItem, Typography} from "@mui/material";
import { NextLinkComposed } from "@/core/components/LinkRouting"; import {NextLinkComposed} from "@/core/components/LinkRouting";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import headerProfileItems from "@/core/data/headerProfileItems"; import headerProfileItems from "@/core/data/headerProfileItems";
import ProfileOptionLogOut from "./ProfileOptionLogOut"; import ProfileOptionLogOut from "./ProfileOptionLogOut";
export default function ProfileOptions({ handleCloseUserMenu }) { export default function ProfileOptions({handleCloseUserMenu}) {
const t = useTranslations(); const t = useTranslations();
return ( return (
<> <>
{headerProfileItems.map((profile_item) => ( {headerProfileItems.map((profile_item) => (
<MenuItem <MenuItem
component={NextLinkComposed} component={NextLinkComposed}
to={{ to={{
pathname: profile_item.route, pathname: profile_item.route,
}} }}
sx={{ sx={{
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "center",
borderTop: 1, borderTop: 1,
px: 3, px: 3,
py: 1.5, py: 1.5,
borderColor: "#e1e1e1", borderColor: "#e1e1e1",
}} }}
key={profile_item.key} key={profile_item.key}
onClick={handleCloseUserMenu} onClick={handleCloseUserMenu}
> >
<Box sx={{ display: "flex", alignItems: "center", flex: 1 }}> <Box sx={{display: "flex", alignItems: "center", flex: 1}}>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
color: "primary.main", color: "primary.main",
pr: 2, pr: 2,
}} }}
> >
{profile_item.icon} {profile_item.icon}
</Box> </Box>
<Typography sx={{ flex: 1 }} textAlign="start"> <Typography sx={{flex: 1}} textAlign="start">
{t(profile_item.name)} {t(profile_item.name)}
</Typography> </Typography>
</Box> </Box>
</MenuItem> </MenuItem>
))} ))}
<ProfileOptionLogOut handleCloseUserMenu={handleCloseUserMenu} /> <ProfileOptionLogOut handleCloseUserMenu={handleCloseUserMenu}/>
</> </>
); );
} }

View File

@@ -1,80 +1,72 @@
import MenuIcon from "@mui/icons-material/Menu"; import MenuIcon from "@mui/icons-material/Menu";
import { import {AppBar, Box, Container, CssBaseline, IconButton, Stack, Toolbar, useTheme} from "@mui/material";
AppBar,
Box,
Container,
CssBaseline,
IconButton,
Stack,
Toolbar,
useTheme
} from "@mui/material";
import ProfileMenu from "./ProfileMenu"; import ProfileMenu from "./ProfileMenu";
function Header({ drawerWidth, handleDrawerToggle }) { function Header({drawerWidth, handleDrawerToggle}) {
const theme = useTheme(); const theme = useTheme();
return ( return (
<> <>
<CssBaseline /> <CssBaseline/>
<AppBar <AppBar
position="fixed" position="fixed"
sx={{
width: { md: `calc(100% - ${drawerWidth}px)` },
ml: { md: `${drawerWidth}px` },
}}
>
<Container maxWidth="xxl">
<Toolbar
disableGutters
sx={{
display: "flex",
}}
>
<Stack direction="row" justifyContent="flex-start" sx={{ flex: 1 }}>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={handleDrawerToggle}
edge="start"
sx={{ display: { md: "none" }, m: 0 }}
>
<MenuIcon />
</IconButton>
</Stack>
<Stack
direction="row"
justifyContent="center"
sx={{
flex: 1,
position: "relative",
...theme.mixins.toolbar,
}}
>
<Box
sx={{ sx={{
position: "relative", width: {md: `calc(100% - ${drawerWidth}px)`},
my: 1, ml: {md: `${drawerWidth}px`},
width: 56,
height: 56,
"@media (min-width:600px)": { maxWidth: 64, maxHeight: 64 },
"@media (min-width:0px)": {
"@media (orientation: landscape)": {
width: 48,
height: 48,
},
},
}} }}
> >
</Box> <Container maxWidth="xxl">
</Stack> <Toolbar
<Stack direction="row" justifyContent="flex-end" sx={{ flex: 1 }}> disableGutters
<ProfileMenu /> sx={{
</Stack> display: "flex",
</Toolbar> }}
</Container> >
</AppBar> <Stack direction="row" justifyContent="flex-start" sx={{flex: 1}}>
</> <IconButton
); color="inherit"
aria-label="open drawer"
onClick={handleDrawerToggle}
edge="start"
sx={{display: {md: "none"}, m: 0}}
>
<MenuIcon/>
</IconButton>
</Stack>
<Stack
direction="row"
justifyContent="center"
sx={{
flex: 1,
position: "relative",
...theme.mixins.toolbar,
}}
>
<Box
sx={{
position: "relative",
my: 1,
width: 56,
height: 56,
"@media (min-width:600px)": {maxWidth: 64, maxHeight: 64},
"@media (min-width:0px)": {
"@media (orientation: landscape)": {
width: 48,
height: 48,
},
},
}}
>
</Box>
</Stack>
<Stack direction="row" justifyContent="flex-end" sx={{flex: 1}}>
<ProfileMenu/>
</Stack>
</Toolbar>
</Container>
</AppBar>
</>
);
} }
export default Header; export default Header;

View File

@@ -1,50 +1,50 @@
import { useState } from "react"; import {useState} from "react";
import FullPageLayout from "../FullPageLayout"; import FullPageLayout from "../FullPageLayout";
import Header from "./header"; import Header from "./header";
import Sidebar from "./sidebar"; import Sidebar from "./sidebar";
import { Toolbar } from "@mui/material"; import {Toolbar} from "@mui/material";
import BreadCrumbs from "./breadcrumbs"; import BreadCrumbs from "./breadcrumbs";
import { ToastContainer } from "react-toastify"; import {ToastContainer} from "react-toastify";
import "react-toastify/dist/ReactToastify.css"; import "react-toastify/dist/ReactToastify.css";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
const drawerWidth = 240; const drawerWidth = 240;
const DashboardLayouts = (props) => { const DashboardLayouts = (props) => {
const { directionApp } = useDirection(); const {directionApp} = useDirection();
const { window } = props; const {window} = props;
const [mobileOpen, setMobileOpen] = useState(false); const [mobileOpen, setMobileOpen] = useState(false);
const container = const container =
window !== undefined ? () => window().document.body : undefined; window !== undefined ? () => window().document.body : undefined;
const handleDrawerToggle = () => { const handleDrawerToggle = () => {
setMobileOpen(!mobileOpen); setMobileOpen(!mobileOpen);
}; };
return ( return (
<FullPageLayout direction="row"> <FullPageLayout direction="row">
<Header <Header
handleDrawerToggle={handleDrawerToggle} handleDrawerToggle={handleDrawerToggle}
drawerWidth={drawerWidth} drawerWidth={drawerWidth}
/> />
<Sidebar <Sidebar
container={container} container={container}
mobileOpen={mobileOpen} mobileOpen={mobileOpen}
handleDrawerToggle={handleDrawerToggle} handleDrawerToggle={handleDrawerToggle}
drawerWidth={drawerWidth} drawerWidth={drawerWidth}
/> />
<FullPageLayout <FullPageLayout
component="main" component="main"
sx={{ flexGrow: 1, width: { sm: `calc(100% - ${drawerWidth}px)` } }} sx={{flexGrow: 1, width: {sm: `calc(100% - ${drawerWidth}px)`}}}
> >
<Toolbar /> <Toolbar/>
<FullPageLayout sx={{ mt: 3 }}> <FullPageLayout sx={{mt: 3}}>
<BreadCrumbs isVisible={true} /> <BreadCrumbs isVisible={true}/>
{props.children} {props.children}
</FullPageLayout>
</FullPageLayout>
{directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</FullPageLayout> </FullPageLayout>
</FullPageLayout> );
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />}
</FullPageLayout>
);
}; };
export default DashboardLayouts; export default DashboardLayouts;

View File

@@ -1,26 +1,26 @@
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import { Divider, Stack, Toolbar, Typography } from "@mui/material"; import {Divider, Stack, Toolbar, Typography} from "@mui/material";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import SidebarList from "./SidebarList"; import SidebarList from "./SidebarList";
const SidebarDrawer = ({ handleDrawerToggle }) => { const SidebarDrawer = ({handleDrawerToggle}) => {
const { user } = useUser(); const {user} = useUser();
const t = useTranslations(); const t = useTranslations();
return ( return (
<> <>
<Toolbar> <Toolbar>
<Stack> <Stack>
<Typography variant="h6" sx={{ color: "primary.main" }}> <Typography variant="h6" sx={{color: "primary.main"}}>
{t("app_short_name")} {t("app_short_name")}
</Typography> </Typography>
<Typography variant="caption">{user.type_name}</Typography> <Typography variant="caption">{user.type_name}</Typography>
</Stack> </Stack>
</Toolbar> </Toolbar>
<Divider /> <Divider/>
<SidebarList handleDrawerToggle={handleDrawerToggle} /> <SidebarList handleDrawerToggle={handleDrawerToggle}/>
</> </>
); );
}; };
export default SidebarDrawer; export default SidebarDrawer;

View File

@@ -1,56 +1,56 @@
import { Divider, List } from "@mui/material"; import {Divider, List} from "@mui/material";
import { Fragment, useEffect, useReducer } from "react"; import {Fragment, useEffect, useReducer} from "react";
import SidebarListItem from "./SidebarListItem"; import SidebarListItem from "./SidebarListItem";
import sidebarMenu from "@/core/data/sidebarMenu"; import sidebarMenu from "@/core/data/sidebarMenu";
import { useRouter } from "next/router"; import {useRouter} from "next/router";
function reducer(state, action) { function reducer(state, action) {
switch (action.type) { switch (action.type) {
case "COLLAPSE_MENU": case "COLLAPSE_MENU":
return state.map((itemsArr) => return state.map((itemsArr) =>
itemsArr.map((item) => itemsArr.map((item) =>
action.key == item.key action.key == item.key
? { ...item, showSubItem: !item.showSubItem } ? {...item, showSubItem: !item.showSubItem}
: item : item
) )
); );
case "SELECTED": case "SELECTED":
return state.map((itemsArr) => return state.map((itemsArr) =>
itemsArr.map((item) => itemsArr.map((item) =>
action.route == item.route action.route == item.route
? { ...item, selected: true } ? {...item, selected: true}
: { ...item, selected: false } : {...item, selected: false}
) )
); );
default: default:
throw new Error(); throw new Error();
} }
} }
export default function SidebarList({ handleDrawerToggle }) { export default function SidebarList({handleDrawerToggle}) {
const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu); const [itemMenu, dispatch] = useReducer(reducer, sidebarMenu);
// activate current page in menu // activate current page in menu
const router = useRouter(); const router = useRouter();
useEffect(() => { useEffect(() => {
dispatch({ type: "SELECTED", route: router.pathname }); dispatch({type: "SELECTED", route: router.pathname});
}, [router.pathname]); }, [router.pathname]);
return ( return (
<List> <List>
{itemMenu.map((itemArr, index) => ( {itemMenu.map((itemArr, index) => (
<Fragment key={index}> <Fragment key={index}>
{itemArr.map((item) => ( {itemArr.map((item) => (
<SidebarListItem <SidebarListItem
item={item} item={item}
dispatch={dispatch} dispatch={dispatch}
key={item.key} key={item.key}
handleDrawerToggle={handleDrawerToggle} handleDrawerToggle={handleDrawerToggle}
/> />
))} ))}
<Divider /> <Divider/>
</Fragment> </Fragment>
))} ))}
</List> </List>
); );
} }

View File

@@ -1,64 +1,59 @@
import { NextLinkComposed } from "@/core/components/LinkRouting"; import {NextLinkComposed} from "@/core/components/LinkRouting";
import ExpandLess from "@mui/icons-material/ExpandLess"; import ExpandLess from "@mui/icons-material/ExpandLess";
import ExpandMore from "@mui/icons-material/ExpandMore"; import ExpandMore from "@mui/icons-material/ExpandMore";
import { import {ListItem, ListItemButton, ListItemIcon, ListItemText,} from "@mui/material";
ListItem, import {useTranslations} from "next-intl";
ListItemButton, import {Fragment} from "react";
ListItemIcon,
ListItemText,
} from "@mui/material";
import { useTranslations } from "next-intl";
import { Fragment } from "react";
import SidebarListSubItem from "./SidebarListSubItem"; import SidebarListSubItem from "./SidebarListSubItem";
const SidebarListItem = ({ item, dispatch, handleDrawerToggle }) => { const SidebarListItem = ({item, dispatch, handleDrawerToggle}) => {
const t = useTranslations(); const t = useTranslations();
return ( return (
<Fragment key={item.key}> <Fragment key={item.key}>
<ListItem disablePadding sx={{ display: "block" }}> <ListItem disablePadding sx={{display: "block"}}>
<ListItemButton <ListItemButton
selected={item.selected} selected={item.selected}
{...(item.type == "page" && { {...(item.type == "page" && {
component: NextLinkComposed, component: NextLinkComposed,
to: { to: {
pathname: item.route, pathname: item.route,
}, },
})} })}
onClick={() => { onClick={() => {
if (item.type == "menu") { if (item.type == "menu") {
dispatch({ type: "COLLAPSE_MENU", key: item.key }); dispatch({type: "COLLAPSE_MENU", key: item.key});
} }
handleDrawerToggle(); handleDrawerToggle();
}} }}
sx={{ sx={{
minHeight: 48, minHeight: 48,
}} }}
> >
<ListItemIcon <ListItemIcon
sx={{ sx={{
minWidth: 0, minWidth: 0,
justifyContent: "center", justifyContent: "center",
color: "primary.main", color: "primary.main",
pr: 2, pr: 2,
}} }}
> >
{item.icon} {item.icon}
</ListItemIcon> </ListItemIcon>
<ListItemText primary={t(item.key)} /> <ListItemText primary={t(item.key)}/>
{item.type == "menu" && {item.type == "menu" &&
(item.showSubItem ? <ExpandLess /> : <ExpandMore />)} (item.showSubItem ? <ExpandLess/> : <ExpandMore/>)}
</ListItemButton> </ListItemButton>
</ListItem> </ListItem>
{item.subItem && ( {item.subItem && (
<SidebarListSubItem <SidebarListSubItem
item={item} item={item}
handleDrawerToggle={handleDrawerToggle} handleDrawerToggle={handleDrawerToggle}
/> />
)} )}
</Fragment> </Fragment>
); );
}; };
export default SidebarListItem; export default SidebarListItem;

View File

@@ -1,54 +1,48 @@
import { NextLinkComposed } from "@/core/components/LinkRouting"; import {NextLinkComposed} from "@/core/components/LinkRouting";
import InboxIcon from "@mui/icons-material/MoveToInbox"; import InboxIcon from "@mui/icons-material/MoveToInbox";
import { import {Collapse, List, ListItemButton, ListItemIcon, ListItemText,} from "@mui/material";
Collapse, import {useTranslations} from "next-intl";
List, import {Fragment} from "react";
ListItemButton,
ListItemIcon,
ListItemText,
} from "@mui/material";
import { useTranslations } from "next-intl";
import { Fragment } from "react";
const SidebarListSubItem = ({ item, handleDrawerToggle }) => { const SidebarListSubItem = ({item, handleDrawerToggle}) => {
const t = useTranslations(); const t = useTranslations();
return ( return (
<Collapse in={item.showSubItem} timeout="auto" unmountOnExit> <Collapse in={item.showSubItem} timeout="auto" unmountOnExit>
<List component="div" disablePadding sx={{ bgcolor: "#f6f6f6" }}> <List component="div" disablePadding sx={{bgcolor: "#f6f6f6"}}>
{item.subItem.map((subitem, index) => ( {item.subItem.map((subitem, index) => (
<Fragment key={subitem.key}> <Fragment key={subitem.key}>
<ListItemButton <ListItemButton
component={NextLinkComposed} component={NextLinkComposed}
to={{ to={{
pathname: subitem.route, pathname: subitem.route,
}} }}
sx={{ sx={{
minHeight: 48, minHeight: 48,
}} }}
onClick={(event) => { onClick={(event) => {
if (item.type == "menu") { if (item.type == "menu") {
dispatch({ type: "COLLAPSE_MENU", key: item.key }); dispatch({type: "COLLAPSE_MENU", key: item.key});
} }
handleDrawerToggle(); handleDrawerToggle();
}} }}
> >
<ListItemIcon <ListItemIcon
sx={{ sx={{
minWidth: 0, minWidth: 0,
justifyContent: "center", justifyContent: "center",
pr: 2, pr: 2,
}} }}
> >
<InboxIcon /> <InboxIcon/>
</ListItemIcon> </ListItemIcon>
<ListItemText primary={t(subitem.key)} /> <ListItemText primary={t(subitem.key)}/>
</ListItemButton> </ListItemButton>
</Fragment> </Fragment>
))} ))}
</List> </List>
</Collapse> </Collapse>
); );
}; };
export default SidebarListSubItem; export default SidebarListSubItem;

View File

@@ -1,46 +1,46 @@
import { Box, Drawer } from "@mui/material"; import {Box, Drawer} from "@mui/material";
import SidebarDrawer from "./SidebarDrawer"; import SidebarDrawer from "./SidebarDrawer";
const Sidebar = (props) => { const Sidebar = (props) => {
return ( return (
<Box <Box
component="nav" component="nav"
sx={{ width: { md: props.drawerWidth }, flexShrink: { sm: 0 } }} sx={{width: {md: props.drawerWidth}, flexShrink: {sm: 0}}}
aria-label="mailbox folders" aria-label="mailbox folders"
> >
<Drawer <Drawer
container={props.container} container={props.container}
variant="temporary" variant="temporary"
open={props.mobileOpen} open={props.mobileOpen}
onClose={props.handleDrawerToggle} onClose={props.handleDrawerToggle}
ModalProps={{ ModalProps={{
keepMounted: true, keepMounted: true,
}} }}
sx={{ sx={{
display: { xs: "block", md: "none" }, display: {xs: "block", md: "none"},
"& .MuiDrawer-paper": { "& .MuiDrawer-paper": {
boxSizing: "border-box", boxSizing: "border-box",
width: props.drawerWidth, width: props.drawerWidth,
}, },
}} }}
> >
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle} /> <SidebarDrawer handleDrawerToggle={props.handleDrawerToggle}/>
</Drawer> </Drawer>
<Drawer <Drawer
variant="permanent" variant="permanent"
sx={{ sx={{
display: { xs: "none", md: "block" }, display: {xs: "none", md: "block"},
"& .MuiDrawer-paper": { "& .MuiDrawer-paper": {
boxSizing: "border-box", boxSizing: "border-box",
width: props.drawerWidth, width: props.drawerWidth,
}, },
}} }}
open open
> >
<SidebarDrawer handleDrawerToggle={props.handleDrawerToggle} /> <SidebarDrawer handleDrawerToggle={props.handleDrawerToggle}/>
</Drawer> </Drawer>
</Box> </Box>
); );
}; };
export default Sidebar; export default Sidebar;

View File

@@ -1,99 +1,99 @@
import { FA_DATATABLE_LOCALIZATION } from "&/locales/fa/datatable"; import {FA_DATATABLE_LOCALIZATION} from "&/locales/fa/datatable";
import { useRouter } from "next/router"; import {useRouter} from "next/router";
import { createContext, useEffect, useState } from "react"; import {createContext, useEffect, useState} from "react";
import useUser from "../hooks/useUser"; import useUser from "../hooks/useUser";
export const LanguageContext = createContext(); export const LanguageContext = createContext();
export const LanguageProvider = ({ children }) => { export const LanguageProvider = ({children}) => {
const router = useRouter(); const router = useRouter();
const languageList = [ 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,
{ {
locale: languageApp, key: "fa",
dir: "rtl",
name: "فارسی",
fontFamily: `IRANSans, sans-serif`,
tableLocalization: FA_DATATABLE_LOCALIZATION,
} }
); ];
return; const {user, userChangedLanguage, changeLanguageState} = useUser();
} const [languageIsReady, setLanguageIsReady] = useState(false);
for (const lang of languageList) { const [languageApp, setLanguageApp] = useState();
if (languageApp != lang.key) continue; const [directionApp, setDirectionApp] = useState(
setDirectionApp(lang.dir); process.env.NEXT_PUBLIC_DEFAULT_DIRECTION
document.dir = lang.dir; );
}
const timer = setTimeout(() => { useEffect(() => {
changeLanguageState(false); const lang = localStorage.getItem("_language");
setLanguageIsReady(true);
}, 1000);
return () => { if (!lang && !languageApp) {
clearTimeout(timer); setLanguageApp(process.env.NEXT_PUBLIC_DEFAULT_LANGUAGE);
}; } else if (lang) {
}, [router.locale, router.isReady, userChangedLanguage, languageApp]); setLanguageApp(lang);
}
}, []);
return ( useEffect(() => {
<LanguageContext.Provider if (!languageApp) return;
value={{
languageApp, const lang = localStorage.getItem("_language");
setLanguageApp,
directionApp, if (!lang) {
languageIsReady, localStorage.setItem("_language", languageApp);
setLanguageIsReady, } else {
languageList, if (languageApp != lang) {
}} localStorage.setItem("_language", languageApp);
> }
{children} }
</LanguageContext.Provider> }, [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 (
<LanguageContext.Provider
value={{
languageApp,
setLanguageApp,
directionApp,
languageIsReady,
setLanguageIsReady,
languageList,
}}
>
{children}
</LanguageContext.Provider>
);
}; };

View File

@@ -1,14 +1,14 @@
import LoadingHardPage from "@/core/components/LoadingHardPage"; import LoadingHardPage from "@/core/components/LoadingHardPage";
import { createContext, useState } from "react"; import {createContext, useState} from "react";
export const LoadingContext = createContext(); export const LoadingContext = createContext();
export const LoadingProvider = ({ children }) => { export const LoadingProvider = ({children}) => {
const [loadingPage, setLoadingPage] = useState(false); const [loadingPage, setLoadingPage] = useState(false);
return ( return (
<LoadingContext.Provider value={{ loadingPage, setLoadingPage }}> <LoadingContext.Provider value={{loadingPage, setLoadingPage}}>
<LoadingHardPage loading={loadingPage} /> <LoadingHardPage loading={loadingPage}/>
{children} {children}
</LoadingContext.Provider> </LoadingContext.Provider>
); );
}; };

View File

@@ -1,121 +1,122 @@
import { USER_INFO } from "@/core/data/apiRoutes"; import {USER_INFO} from "@/core/data/apiRoutes";
import axios from "axios"; import axios from "axios";
import { createContext, useCallback, useEffect, useReducer } from "react"; import {createContext, useCallback, useEffect, useReducer} from "react";
const initialUser = { const initialUser = {
isAuth: false, isAuth: false,
userChangedLanguage: false, userChangedLanguage: false,
token: null, token: null,
user: {}, user: {},
}; };
const reducer = (state, action) => { const reducer = (state, action) => {
switch (action.type) { switch (action.type) {
case "CLEAR_USER": case "CLEAR_USER":
return { ...state, user: {} }; return {...state, user: {}};
case "CHANGE_USER": case "CHANGE_USER":
return { ...state, user: action.user }; return {...state, user: action.user};
case "CHANGE_USER_LANGUAGE": case "CHANGE_USER_LANGUAGE":
return { return {
...state, ...state,
user: { ...state.user, user_language: action.language }, user: {...state.user, user_language: action.language},
}; };
case "CHANGE_AUTH_STATE": case "CHANGE_AUTH_STATE":
return { ...state, isAuth: action.isAuth }; return {...state, isAuth: action.isAuth};
case "CHANGE_LANGUAGE_STATE": case "CHANGE_LANGUAGE_STATE":
return { ...state, userChangedLanguage: action.userChangedLanguage }; return {...state, userChangedLanguage: action.userChangedLanguage};
case "CLEAR_TOKEN": case "CLEAR_TOKEN":
localStorage.removeItem("_token"); localStorage.removeItem("_token");
return { ...state, token: null }; return {...state, token: null};
case "SET_TOKEN": case "SET_TOKEN":
localStorage.setItem("_token", action.token); localStorage.setItem("_token", action.token);
return { ...state, token: action.token }; return {...state, token: action.token};
default: default:
return state; return state;
} }
}; };
export const UserContext = createContext(); export const UserContext = createContext();
export const UserProvider = ({ children }) => { export const UserProvider = ({children}) => {
const [state, dispatch] = useReducer(reducer, initialUser); const [state, dispatch] = useReducer(reducer, initialUser);
const clearUser = useCallback(() => { const clearUser = useCallback(() => {
dispatch({ type: "CLEAR_USER" }); dispatch({type: "CLEAR_USER"});
}, []); }, []);
const changeUser = useCallback((user) => { const changeUser = useCallback((user) => {
dispatch({ type: "CHANGE_USER", user }); dispatch({type: "CHANGE_USER", user});
}, []); }, []);
const changeUserLanguage = useCallback(/* for multi language app */); const changeUserLanguage = useCallback(/* for multi language app */);
const changeAuthState = useCallback((isAuth) => { const changeAuthState = useCallback((isAuth) => {
dispatch({ type: "CHANGE_AUTH_STATE", isAuth }); dispatch({type: "CHANGE_AUTH_STATE", isAuth});
}, []); }, []);
const changeLanguageState = useCallback((userChangedLanguage) => { const changeLanguageState = useCallback((userChangedLanguage) => {
dispatch({ type: "CHANGE_LANGUAGE_STATE", userChangedLanguage }); dispatch({type: "CHANGE_LANGUAGE_STATE", userChangedLanguage});
}, []); }, []);
const clearToken = useCallback(() => { const clearToken = useCallback(() => {
dispatch({ type: "CLEAR_TOKEN" }); dispatch({type: "CLEAR_TOKEN"});
}, []); }, []);
const setToken = useCallback((token) => { const setToken = useCallback((token) => {
dispatch({ type: "SET_TOKEN", token }); dispatch({type: "SET_TOKEN", token});
}, []); }, []);
const getUser = useCallback( const getUser = useCallback(
(callback = () => {}) => { (callback = () => {
axios }) => {
.get(USER_INFO, { axios
headers: { authorization: `Bearer ${state.token}` }, .get(USER_INFO, {
}) headers: {authorization: `Bearer ${state.token}`},
.then(({ data }) => { })
if (typeof callback === "function") callback(data); .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]);
[state.token]
);
useEffect(() => { return (
const localToken = localStorage.getItem("_token"); <UserContext.Provider
if (localToken) dispatch({ type: "SET_TOKEN", token: localToken }); value={{
}, []); isAuth: state.isAuth,
userChangedLanguage: state.userChangedLanguage,
useEffect(() => { token: state.token,
if (!state.token) { user: state.user,
clearUser(); getUser,
changeAuthState(false); clearUser,
changeLanguageState(false); changeUser,
return; changeUserLanguage,
} changeAuthState,
getUser((data) => { changeLanguageState,
changeUser(data); clearToken,
changeAuthState(true); setToken,
changeLanguageState(true); }}
}); >
}, [state.token]); {children}
</UserContext.Provider>
return ( );
<UserContext.Provider
value={{
isAuth: state.isAuth,
userChangedLanguage: state.userChangedLanguage,
token: state.token,
user: state.user,
getUser,
clearUser,
changeUser,
changeUserLanguage,
changeAuthState,
changeLanguageState,
clearToken,
setToken,
}}
>
{children}
</UserContext.Provider>
);
}; };

View File

@@ -1,10 +1,10 @@
import { useContext } from "react"; import {useContext} from "react";
import { LanguageContext } from "../contexts/language"; import {LanguageContext} from "../contexts/language";
const useDirection = () => { const useDirection = () => {
const { directionApp } = useContext(LanguageContext); const {directionApp} = useContext(LanguageContext);
return { directionApp }; return {directionApp};
}; };
export default useDirection; export default useDirection;

View File

@@ -1,28 +1,28 @@
import { useContext } from "react"; import {useContext} from "react";
import { LanguageContext } from "../contexts/language"; import {LanguageContext} from "../contexts/language";
import useUser from "./useUser"; import useUser from "./useUser";
const useLanguage = () => { const useLanguage = () => {
const { isAuth, changeUserLanguage } = useUser(); const {isAuth, changeUserLanguage} = useUser();
const { const {
languageApp, languageApp,
setLanguageApp, setLanguageApp,
languageIsReady, languageIsReady,
setLanguageIsReady, setLanguageIsReady,
languageList, languageList,
} = useContext(LanguageContext); } = useContext(LanguageContext);
const changeLanguage = (lang) => { const changeLanguage = (lang) => {
if (lang == languageApp) return; if (lang == languageApp) return;
setLanguageIsReady(false); setLanguageIsReady(false);
setLanguageApp(lang); setLanguageApp(lang);
if (isAuth) { if (isAuth) {
changeUserLanguage(lang); changeUserLanguage(lang);
} }
}; };
return { languageApp, changeLanguage, languageIsReady, languageList }; return {languageApp, changeLanguage, languageIsReady, languageList};
}; };
export default useLanguage; export default useLanguage;

View File

@@ -1,10 +1,10 @@
import { useContext } from "react"; import {useContext} from "react";
import { LoadingContext } from "../contexts/loading"; import {LoadingContext} from "../contexts/loading";
const useLoading = () => { const useLoading = () => {
const { setLoadingPage } = useContext(LoadingContext); const {setLoadingPage} = useContext(LoadingContext);
return { setLoadingPage }; return {setLoadingPage};
}; };
export default useLoading; export default useLoading;

View File

@@ -1,36 +1,36 @@
import { useContext } from "react"; import {useContext} from "react";
import { UserContext } from "../contexts/user"; import {UserContext} from "../contexts/user";
const useUser = () => { const useUser = () => {
const { const {
isAuth, isAuth,
userChangedLanguage, userChangedLanguage,
token, token,
user, user,
getUser, getUser,
clearUser, clearUser,
changeUser, changeUser,
changeUserLanguage, changeUserLanguage,
changeAuthState, changeAuthState,
changeLanguageState, changeLanguageState,
clearToken, clearToken,
setToken, setToken,
} = useContext(UserContext); } = useContext(UserContext);
return { return {
isAuth, isAuth,
userChangedLanguage, userChangedLanguage,
token, token,
user, user,
getUser, getUser,
clearUser, clearUser,
changeUser, changeUser,
changeUserLanguage, changeUserLanguage,
changeAuthState, changeAuthState,
changeLanguageState, changeLanguageState,
clearToken, clearToken,
setToken, setToken,
}; };
}; };
export default useUser; export default useUser;

View File

@@ -1,41 +1,41 @@
import { NextLinkComposed } from "@/core/components/LinkRouting"; import {NextLinkComposed} from "@/core/components/LinkRouting";
import Message from "@/core/components/Messages"; import Message from "@/core/components/Messages";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import { Button, Typography } from "@mui/material"; import {Button, Typography} from "@mui/material";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import { useRouter } from "next/router"; import {useRouter} from "next/router";
const WithAuthMiddleware = ({ children }) => { const WithAuthMiddleware = ({children}) => {
const { isAuth } = useUser(); const {isAuth} = useUser();
const t = useTranslations(); const t = useTranslations();
const router = useRouter(); const router = useRouter();
if (!isAuth) if (!isAuth)
return ( return (
<Message <Message
text={ text={
<Typography sx={{ textAlign: "center" }}> <Typography sx={{textAlign: "center"}}>
{t( {t(
"Authorization.typography_your_access_to_this_page_has_expired_Please_login_again" "Authorization.typography_your_access_to_this_page_has_expired_Please_login_again"
)} )}
</Typography> </Typography>
} }
actions={ actions={
<> <>
<Button <Button
variant="contained" variant="contained"
component={NextLinkComposed} component={NextLinkComposed}
to={{ to={{
pathname: "/", pathname: "/",
}} }}
> >
{t("login")} {t("login")}
</Button> </Button>
</> </>
} }
/> />
); );
return <>{children}</>; return <>{children}</>;
}; };
export default WithAuthMiddleware; export default WithAuthMiddleware;

View File

@@ -1,56 +1,56 @@
import Message from "@/core/components/Messages"; import Message from "@/core/components/Messages";
import useUser from "@/lib/app/hooks/useUser"; import useUser from "@/lib/app/hooks/useUser";
import { Stack, Typography } from "@mui/material"; import {Stack, Typography} from "@mui/material";
import { useTranslations } from "next-intl"; import {useTranslations} from "next-intl";
import { useSearchParams } from "next/navigation"; import {useSearchParams} from "next/navigation";
import { useRouter } from "next/router"; import {useRouter} from "next/router";
import { useEffect } from "react"; import {useEffect} from "react";
const WithoutAuthMiddleware = ({ children }) => { const WithoutAuthMiddleware = ({children}) => {
const { isAuth } = useUser(); const {isAuth} = useUser();
const t = useTranslations(); const t = useTranslations();
const router = useRouter(); const router = useRouter();
// gettin url query // gettin url query
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const backUrlDecodedPath = searchParams.get("back_url"); const backUrlDecodedPath = searchParams.get("back_url");
useEffect(() => { useEffect(() => {
if (!isAuth) return; if (!isAuth) return;
const timer = setTimeout(() => { const timer = setTimeout(() => {
router.replace( router.replace(
backUrlDecodedPath backUrlDecodedPath
? decodeURIComponent(backUrlDecodedPath) ? decodeURIComponent(backUrlDecodedPath)
: "/dashboard" : "/dashboard"
); );
}, 2000); }, 2000);
return () => { return () => {
clearTimeout(timer); clearTimeout(timer);
}; };
}, [isAuth]); }, [isAuth]);
if (isAuth) if (isAuth)
return ( return (
<Message <Message
text={ text={
<Stack alignItems="center" spacing={2}> <Stack alignItems="center" spacing={2}>
<Typography sx={{ textAlign: "center" }}> <Typography sx={{textAlign: "center"}}>
{t( {t(
"Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again" "Authorization.typography_your_login_is_valid_and_you_do_not_need_to_login_again"
)} )}
</Typography> </Typography>
<Typography> <Typography>
{t("Authorization.typography_redirect_to")}{" "} {t("Authorization.typography_redirect_to")}{" "}
{backUrlDecodedPath {backUrlDecodedPath
? t("Authorization.typography_routing_previuos_page") ? t("Authorization.typography_routing_previuos_page")
: t("Authorization.typography_routing_dashbaord_page")} : t("Authorization.typography_routing_dashbaord_page")}
</Typography> </Typography>
</Stack> </Stack>
} }
/> />
); );
return <>{children}</>; return <>{children}</>;
}; };
export default WithoutAuthMiddleware; export default WithoutAuthMiddleware;

View File

@@ -2,12 +2,12 @@ import NotFoundComponent from "@/components/not-found";
import Head from "next/head"; import Head from "next/head";
export default function NotFound() { export default function NotFound() {
return ( return (
<> <>
<Head> <Head>
<title>یافت نشد</title> <title>یافت نشد</title>
</Head> </Head>
<NotFoundComponent /> <NotFoundComponent/>
</> </>
); );
} }

View File

@@ -1,30 +1,30 @@
import "&/fontiran.scss"; import "&/fontiran.scss";
import AppLayout from "@/layouts/AppLayout"; import AppLayout from "@/layouts/AppLayout";
import MuiLayout from "@/layouts/MuiLayout"; import MuiLayout from "@/layouts/MuiLayout";
import { LanguageProvider } from "@/lib/app/contexts/language"; import {LanguageProvider} from "@/lib/app/contexts/language";
import { LoadingProvider } from "@/lib/app/contexts/loading"; import {LoadingProvider} from "@/lib/app/contexts/loading";
import { UserProvider } from "@/lib/app/contexts/user"; import {UserProvider} from "@/lib/app/contexts/user";
import "moment/locale/fa"; import "moment/locale/fa";
import { NextIntlProvider } from "next-intl"; import {NextIntlProvider} from "next-intl";
const App = ({ Component, pageProps }) => { const App = ({Component, pageProps}) => {
return ( return (
<> <>
<UserProvider> <UserProvider>
<LanguageProvider> <LanguageProvider>
<NextIntlProvider messages={pageProps.messages}> <NextIntlProvider messages={pageProps.messages}>
<MuiLayout isBot={pageProps.isBot}> <MuiLayout isBot={pageProps.isBot}>
<LoadingProvider> <LoadingProvider>
<AppLayout isBot={pageProps.isBot}> <AppLayout isBot={pageProps.isBot}>
<Component {...pageProps} /> <Component {...pageProps} />
</AppLayout> </AppLayout>
</LoadingProvider> </LoadingProvider>
</MuiLayout> </MuiLayout>
</NextIntlProvider> </NextIntlProvider>
</LanguageProvider> </LanguageProvider>
</UserProvider> </UserProvider>
</> </>
); );
}; };
export default App; export default App;

View File

@@ -1,67 +1,65 @@
import { import {createEmotionCacheLtr} from "@/core/utils/createEmotionCache";
createEmotionCacheLtr
} from "@/core/utils/createEmotionCache";
import theme from "@/core/utils/theme"; import theme from "@/core/utils/theme";
import createEmotionServer from "@emotion/server/create-instance"; 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) { export default function MyDocument(props) {
const { emotionStyleTags } = props; const {emotionStyleTags} = props;
return ( return (
<Html> <Html>
<Head> <Head>
<meta name="theme-color" content={theme.palette.primary.main} /> <meta name="theme-color" content={theme.palette.primary.main}/>
<meta name="emotion-insertion-point" content="" /> <meta name="emotion-insertion-point" content=""/>
<link rel="shortcut icon" href="/icons/favicon.ico" /> <link rel="shortcut icon" href="/icons/favicon.ico"/>
<link rel="manifest" href="/manifest.json" /> <link rel="manifest" href="/manifest.json"/>
<link <link
rel="stylesheet" rel="stylesheet"
href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
/> />
{emotionStyleTags} {emotionStyleTags}
</Head> </Head>
<body> <body>
<Main /> <Main/>
<NextScript /> <NextScript/>
</body> </body>
</Html> </Html>
); );
} }
MyDocument.getInitialProps = async (ctx) => { MyDocument.getInitialProps = async (ctx) => {
const originalRenderPage = ctx.renderPage; const originalRenderPage = ctx.renderPage;
let cache; let cache;
switch (ctx.locale) { switch (ctx.locale) {
case "fa": case "fa":
cache = createEmotionCacheLtr(); cache = createEmotionCacheLtr();
break; break;
} }
const { extractCriticalToChunks } = createEmotionServer(cache); const {extractCriticalToChunks} = createEmotionServer(cache);
ctx.renderPage = () => ctx.renderPage = () =>
originalRenderPage({ originalRenderPage({
enhanceApp: (App) => enhanceApp: (App) =>
function EnhanceApp(props) { function EnhanceApp(props) {
return <App emotionCache={cache} {...props} />; return <App emotionCache={cache} {...props} />;
}, },
}); });
const initialProps = await Document.getInitialProps(ctx); const initialProps = await Document.getInitialProps(ctx);
const emotionStyles = extractCriticalToChunks(initialProps.html); const emotionStyles = extractCriticalToChunks(initialProps.html);
const emotionStyleTags = emotionStyles.styles.map((style) => ( const emotionStyleTags = emotionStyles.styles.map((style) => (
<style <style
data-emotion={`${style.key} ${style.ids.join(" ")}`} data-emotion={`${style.key} ${style.ids.join(" ")}`}
key={style.key} key={style.key}
// eslint-disable-next-line react/no-danger // eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: style.css }} dangerouslySetInnerHTML={{__html: style.css}}
/> />
)); ));
return { return {
...initialProps, ...initialProps,
emotionStyleTags, emotionStyleTags,
}; };
}; };

View File

@@ -1,23 +1,23 @@
import DashboardFirstComponent from "@/components/dashboard/first"; import DashboardFirstComponent from "@/components/dashboard/first";
import TitlePage from "@/core/components/TitlePage"; import TitlePage from "@/core/components/TitlePage";
import WithAuthMiddleware from "@/middlewares/WithAuth"; import WithAuthMiddleware from "@/middlewares/WithAuth";
import { parse } from "next-useragent"; import {parse} from "next-useragent";
export default function Dashboard() { export default function Dashboard() {
return ( return (
<WithAuthMiddleware> <WithAuthMiddleware>
<TitlePage text="Dashboard.dashboard_page" /> <TitlePage text="Dashboard.dashboard_page"/>
<DashboardFirstComponent /> <DashboardFirstComponent/>
</WithAuthMiddleware> </WithAuthMiddleware>
); );
} }
export async function getServerSideProps({ req, locale }) { export async function getServerSideProps({req, locale}) {
const { isBot } = parse(req.headers["user-agent"]); const {isBot} = parse(req.headers["user-agent"]);
return { return {
props: { props: {
messages: (await import(`&/locales/${locale}/app.json`)).default, messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot, isBot,
}, },
}; };
} }

View File

@@ -1,23 +1,23 @@
import DashboardLoanFollowUpComponent from "@/components/dashboard/loan-follow-up"; import DashboardLoanFollowUpComponent from "@/components/dashboard/loan-follow-up";
import TitlePage from "@/core/components/TitlePage"; import TitlePage from "@/core/components/TitlePage";
import WithAuthMiddleware from "@/middlewares/WithAuth"; import WithAuthMiddleware from "@/middlewares/WithAuth";
import { parse } from "next-useragent"; import {parse} from "next-useragent";
export default function LoanFollowUp() { export default function LoanFollowUp() {
return ( return (
<WithAuthMiddleware> <WithAuthMiddleware>
<TitlePage text="LoanFollowUp.loan_follow_up_page" /> <TitlePage text="LoanFollowUp.loan_follow_up_page"/>
<DashboardLoanFollowUpComponent /> <DashboardLoanFollowUpComponent/>
</WithAuthMiddleware> </WithAuthMiddleware>
); );
} }
export async function getServerSideProps({ req, locale }) { export async function getServerSideProps({req, locale}) {
const { isBot } = parse(req.headers["user-agent"]); const {isBot} = parse(req.headers["user-agent"]);
return { return {
props: { props: {
messages: (await import(`&/locales/${locale}/app.json`)).default, messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot, isBot,
}, },
}; };
} }

View File

@@ -1,23 +1,23 @@
import DashboardLoanRequestComponent from "@/components/dashboard/loan-request"; import DashboardLoanRequestComponent from "@/components/dashboard/loan-request";
import TitlePage from "@/core/components/TitlePage"; import TitlePage from "@/core/components/TitlePage";
import WithAuthMiddleware from "@/middlewares/WithAuth"; import WithAuthMiddleware from "@/middlewares/WithAuth";
import { parse } from "next-useragent"; import {parse} from "next-useragent";
export default function LoanRequest() { export default function LoanRequest() {
return ( return (
<WithAuthMiddleware> <WithAuthMiddleware>
<TitlePage text="LoanFollowUp.loan_follow_up_page" /> <TitlePage text="LoanFollowUp.loan_follow_up_page"/>
<DashboardLoanRequestComponent /> <DashboardLoanRequestComponent/>
</WithAuthMiddleware> </WithAuthMiddleware>
); );
} }
export async function getServerSideProps({ req, locale }) { export async function getServerSideProps({req, locale}) {
const { isBot } = parse(req.headers["user-agent"]); const {isBot} = parse(req.headers["user-agent"]);
return { return {
props: { props: {
messages: (await import(`&/locales/${locale}/app.json`)).default, messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot, isBot,
}, },
}; };
} }

View File

@@ -1,22 +1,22 @@
import FirstComponent from "@/components/first"; import FirstComponent from "@/components/first";
import TitlePage from "@/core/components/TitlePage"; import TitlePage from "@/core/components/TitlePage";
import { parse } from "next-useragent"; import {parse} from "next-useragent";
export default function Home() { export default function Home() {
return ( return (
<> <>
<TitlePage text="first_page" /> <TitlePage text="first_page"/>
<FirstComponent /> <FirstComponent/>
</> </>
); );
} }
export async function getServerSideProps({ req, locale }) { export async function getServerSideProps({req, locale}) {
const { isBot } = parse(req.headers["user-agent"]); const {isBot} = parse(req.headers["user-agent"]);
return { return {
props: { props: {
messages: (await import(`&/locales/${locale}/app.json`)).default, messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot, isBot,
}, },
}; };
} }

View File

@@ -1,28 +1,28 @@
import LoginComponent from "@/components/login"; import LoginComponent from "@/components/login";
import TitlePage from "@/core/components/TitlePage"; import TitlePage from "@/core/components/TitlePage";
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth"; import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
import { parse } from "next-useragent"; import {parse} from "next-useragent";
import "react-toastify/dist/ReactToastify.css"; import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify"; import {ToastContainer} from "react-toastify";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
export default function Login() { export default function Login() {
const { directionApp } = useDirection(); const {directionApp} = useDirection();
return ( return (
<WithoutAuthMiddleware> <WithoutAuthMiddleware>
<TitlePage text="Titles.title_login_page" /> <TitlePage text="Titles.title_login_page"/>
<LoginComponent /> <LoginComponent/>
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />} {directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</WithoutAuthMiddleware> </WithoutAuthMiddleware>
); );
} }
export async function getServerSideProps({ req, locale }) { export async function getServerSideProps({req, locale}) {
const { isBot } = parse(req.headers["user-agent"]); const {isBot} = parse(req.headers["user-agent"]);
return { return {
props: { props: {
messages: (await import(`&/locales/${locale}/app.json`)).default, messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot, isBot,
}, },
}; };
} }

View File

@@ -1,28 +1,28 @@
import RegisterComponent from "@/components/register"; import RegisterComponent from "@/components/register";
import TitlePage from "@/core/components/TitlePage"; import TitlePage from "@/core/components/TitlePage";
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth"; import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
import { parse } from "next-useragent"; import {parse} from "next-useragent";
import "react-toastify/dist/ReactToastify.css"; import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify"; import {ToastContainer} from "react-toastify";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
export default function Register() { export default function Register() {
const { directionApp } = useDirection(); const {directionApp} = useDirection();
return ( return (
<WithoutAuthMiddleware> <WithoutAuthMiddleware>
<TitlePage text="Titles.title_register_page" /> <TitlePage text="Titles.title_register_page"/>
<RegisterComponent /> <RegisterComponent/>
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />} {directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</WithoutAuthMiddleware> </WithoutAuthMiddleware>
); );
} }
export async function getServerSideProps({ req, locale }) { export async function getServerSideProps({req, locale}) {
const { isBot } = parse(req.headers["user-agent"]); const {isBot} = parse(req.headers["user-agent"]);
return { return {
props: { props: {
messages: (await import(`&/locales/${locale}/app.json`)).default, messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot, isBot,
}, },
}; };
} }

View File

@@ -1,28 +1,28 @@
import NavyComponent from "@/components/register/navy"; import NavyComponent from "@/components/register/navy";
import TitlePage from "@/core/components/TitlePage"; import TitlePage from "@/core/components/TitlePage";
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth"; import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
import { parse } from "next-useragent"; import {parse} from "next-useragent";
import "react-toastify/dist/ReactToastify.css"; import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify"; import {ToastContainer} from "react-toastify";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
export default function Register() { export default function Register() {
const { directionApp } = useDirection(); const {directionApp} = useDirection();
return ( return (
<WithoutAuthMiddleware> <WithoutAuthMiddleware>
<TitlePage text="Titles.title_register_navy_page" /> <TitlePage text="Titles.title_register_navy_page"/>
<NavyComponent /> <NavyComponent/>
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />} {directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</WithoutAuthMiddleware> </WithoutAuthMiddleware>
); );
} }
export async function getServerSideProps({ req, locale }) { export async function getServerSideProps({req, locale}) {
const { isBot } = parse(req.headers["user-agent"]); const {isBot} = parse(req.headers["user-agent"]);
return { return {
props: { props: {
messages: (await import(`&/locales/${locale}/app.json`)).default, messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot, isBot,
}, },
}; };
} }

View File

@@ -1,28 +1,28 @@
import WelfareServicesComponent from "@/components/register/welfare-services"; import WelfareServicesComponent from "@/components/register/welfare-services";
import TitlePage from "@/core/components/TitlePage"; import TitlePage from "@/core/components/TitlePage";
import WithoutAuthMiddleware from "@/middlewares/WithoutAuth"; import WithoutAuthMiddleware from "@/middlewares/WithoutAuth";
import { parse } from "next-useragent"; import {parse} from "next-useragent";
import "react-toastify/dist/ReactToastify.css"; import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify"; import {ToastContainer} from "react-toastify";
import useDirection from "@/lib/app/hooks/useDirection"; import useDirection from "@/lib/app/hooks/useDirection";
export default function Register() { export default function Register() {
const { directionApp } = useDirection(); const {directionApp} = useDirection();
return ( return (
<WithoutAuthMiddleware> <WithoutAuthMiddleware>
<TitlePage text="Titles.title_register_welfare_services_page" /> <TitlePage text="Titles.title_register_welfare_services_page"/>
<WelfareServicesComponent /> <WelfareServicesComponent/>
{directionApp === "rtl" ? <ToastContainer rtl /> : <ToastContainer ltr />} {directionApp === "rtl" ? <ToastContainer rtl/> : <ToastContainer ltr/>}
</WithoutAuthMiddleware> </WithoutAuthMiddleware>
); );
} }
export async function getServerSideProps({ req, locale }) { export async function getServerSideProps({req, locale}) {
const { isBot } = parse(req.headers["user-agent"]); const {isBot} = parse(req.headers["user-agent"]);
return { return {
props: { props: {
messages: (await import(`&/locales/${locale}/app.json`)).default, messages: (await import(`&/locales/${locale}/app.json`)).default,
isBot, isBot,
}, },
}; };
} }