This commit is contained in:
2023-05-02 11:43:24 +07:00
parent 4770ce26d2
commit 2b491b16cd
14 changed files with 7812 additions and 24103 deletions

31696
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -220,7 +220,7 @@ const OrderForm = ({customer_id}: {customer_id: string|number}) => {
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'name']} name={[name, 'name']}
fieldKey={[fieldKey, 'name']} //fieldKey={[fieldKey, 'name']}
hidden hidden
> >
<Input /> <Input />
@@ -229,7 +229,7 @@ const OrderForm = ({customer_id}: {customer_id: string|number}) => {
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'sku']} name={[name, 'sku']}
fieldKey={[fieldKey, 'sku']} //fieldKey={[fieldKey, 'sku']}
hidden hidden
> >
<Input /> <Input />
@@ -238,7 +238,7 @@ const OrderForm = ({customer_id}: {customer_id: string|number}) => {
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'id']} name={[name, 'id']}
fieldKey={[fieldKey, 'id']} //fieldKey={[fieldKey, 'id']}
hidden hidden
> >
<Input /> <Input />
@@ -247,7 +247,7 @@ const OrderForm = ({customer_id}: {customer_id: string|number}) => {
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'price']} name={[name, 'price']}
fieldKey={[fieldKey, 'price']} //fieldKey={[fieldKey, 'price']}
> >
<Input style={{width: 90}} placeholder="giá" /> <Input style={{width: 90}} placeholder="giá" />
</Form.Item> </Form.Item>
@@ -255,7 +255,7 @@ const OrderForm = ({customer_id}: {customer_id: string|number}) => {
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'quantity']} name={[name, 'quantity']}
fieldKey={[fieldKey, 'quantity']} //fieldKey={[fieldKey, 'quantity']}
rules={[ rules={[
{ required: true, message: 'Nhập số lượng' } { required: true, message: 'Nhập số lượng' }
]} ]}
@@ -302,7 +302,7 @@ const OrderForm = ({customer_id}: {customer_id: string|number}) => {
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'name']} name={[name, 'name']}
fieldKey={[fieldKey, 'name']} //fieldKey={[fieldKey, 'name']}
rules={[{ required: true, message: 'Chưa nhập tiêu đề' }]} rules={[{ required: true, message: 'Chưa nhập tiêu đề' }]}
> >
<SelectWithAddItem current_lists={['Phí ship', 'Thuế VAT', 'Đóng gói']} /> <SelectWithAddItem current_lists={['Phí ship', 'Thuế VAT', 'Đóng gói']} />
@@ -311,7 +311,7 @@ const OrderForm = ({customer_id}: {customer_id: string|number}) => {
<Form.Item <Form.Item
{...restField} {...restField}
name={[name, 'price']} name={[name, 'price']}
fieldKey={[fieldKey, 'price']} //fieldKey={[fieldKey, 'price']}
rules={[{ required: true, message: 'price' }]} rules={[{ required: true, message: 'price' }]}
> >
<Input placeholder="giá" /> <Input placeholder="giá" />

View File

@@ -1,6 +1,6 @@
import React, { createRef, useState } from 'react'; import React, { createRef, useState } from 'react';
import debounce from "lodash/debounce"; import debounce from "lodash/debounce";
import { Image, Input, Menu, Dropdown, Layout } from "antd"; import {Image, Input, Menu, Dropdown, Layout, InputRef} from "antd";
import classNames from "classnames"; import classNames from "classnames";
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
@@ -25,12 +25,12 @@ const { Sider } = Layout;
//Note: this component has been well-tested, do NOT change it!! //Note: this component has been well-tested, do NOT change it!!
const ConversationSearch = ({ setKeyword }: { setKeyword: (keyword: string) => void }) => { const ConversationSearch = ({ setKeyword }: { setKeyword: (keyword: string) => void }) => {
const search_wait_time = 300; // milli seconds const search_wait_time = 300; // milli seconds
const inputRef = createRef<Input>(); const inputRef = createRef<InputRef>();
const startSearch = () => { const startSearch = () => {
//const time = new Date().getSeconds(); //const time = new Date().getSeconds();
const keyword = (inputRef.current) ? inputRef.current.input.value : ''; const keyword = (inputRef.current) ? inputRef.current?.input?.value : '';
//console.log('Keyword = ' + keyword + ' at ' + time); //console.log('Keyword = ' + keyword + ' at ' + time);
setKeyword(keyword); if(keyword) setKeyword(keyword);
} }
return ( return (

View File

@@ -4,16 +4,18 @@ import {isFound} from "@/lib/vietnamese";
const { Option } = Select; const { Option } = Select;
const SelectWithList = (props : {options: {value: string|number, text: string}[]} & SelectProps<string> ) => { const SelectWithList = (props : {options: {value: string|number, label: string}[]} & SelectProps<string> ) => {
const {options, ...others} = props; const {options, ...others} = props;
return ( return (
<Select <Select
showSearch showSearch
optionFilterProp="children" optionFilterProp="children"
filterOption={(input, option) => filterOption={(input, option) =>
// option!.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 // option!.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
// @ts-ignore
isFound(input, option!.children) isFound(input, option!.children)
} }
/*filterSort={(optionA, optionB) => /*filterSort={(optionA, optionB) =>
@@ -23,7 +25,7 @@ const SelectWithList = (props : {options: {value: string|number, text: string}[]
{...others} {...others}
> >
{ {
options.map(op => <Option key={op.value} value={op.value}>{op.text}</Option>) options.map(op => <Option key={op.value} value={op.value}>{op.label}</Option>)
} }
</Select> </Select>
) )

View File

@@ -1,4 +1,4 @@
import {Tag, Input, Tooltip, message} from 'antd'; import {Tag, Input, Tooltip, message, InputRef} from 'antd';
import { PlusOutlined } from '@ant-design/icons'; import { PlusOutlined } from '@ant-design/icons';
import React, {createRef, Fragment, useState} from "react"; import React, {createRef, Fragment, useState} from "react";
@@ -64,7 +64,7 @@ const AddNewTag = ({onEnter} : {onEnter: (txt: string) => void}) => {
class EditableTagGroup extends React.Component<EditableTagGroupProps, EditableTagGroupState> { class EditableTagGroup extends React.Component<EditableTagGroupProps, EditableTagGroupState> {
private editInputRef: React.RefObject<Input>; private editInputRef: React.RefObject<InputRef>;
constructor(props: EditableTagGroupProps) { constructor(props: EditableTagGroupProps) {
super(props); super(props);
@@ -75,7 +75,7 @@ class EditableTagGroup extends React.Component<EditableTagGroupProps, EditableTa
loadExistingList: false loadExistingList: false
} }
this.editInputRef = createRef<Input>(); this.editInputRef = createRef<InputRef>();
} }

View File

@@ -20,3 +20,5 @@ export const getConnectNode = (node_id: string) => {
export const SOCKET_OPTIONS = { export const SOCKET_OPTIONS = {
} }
export const CREDENTIAL_SAVE_KEY = 'chatngay-u';

View File

@@ -1,7 +1,7 @@
const GENDER_LIST = [ const GENDER_LIST = [
{"value":"u","text":"Chưa biết"}, {"value":"u","label":"Chưa biết"},
{"value":"f","text":"Nữ"}, {"value":"f","label":"Nữ"},
{"value":"m","text":"Nam"} {"value":"m","label":"Nam"}
]; ];
export default GENDER_LIST; export default GENDER_LIST;

View File

@@ -1,70 +1,70 @@
const PROVINCE_LIST = [ const PROVINCE_LIST = [
// top provinces // top provinces
{"value":"ha-noi","text":"Hà Nội"}, {"value":"ha-noi","label":"Hà Nội"},
{"value":"tp-hcm","text":"TP HCM"}, {"value":"tp-hcm","label":"TP HCM"},
{"value":"da-nang","text":"Đà Nẵng"}, {"value":"da-nang","label":"Đà Nẵng"},
{"value":"hai-phong","text":"Hải Phòng"}, {"value":"hai-phong","label":"Hải Phòng"},
{"value":"can-tho","text":"Cần Thơ"}, {"value":"can-tho","label":"Cần Thơ"},
// others // others
{"value":"an-giang","text":"An Giang"}, {"value":"an-giang","label":"An Giang"},
{"value":"ba-ria-vung-tau","text":"Bà Rịa - Vũng Tàu"}, {"value":"ba-ria-vung-tau","label":"Bà Rịa - Vũng Tàu"},
{"value":"bac-giang","text":"Bắc Giang"}, {"value":"bac-giang","label":"Bắc Giang"},
{"value":"bac-kan","text":"Bắc Kạn"}, {"value":"bac-kan","label":"Bắc Kạn"},
{"value":"bac-lieu","text":"Bạc Liêu"}, {"value":"bac-lieu","label":"Bạc Liêu"},
{"value":"bac-ninh","text":"Bắc Ninh"}, {"value":"bac-ninh","label":"Bắc Ninh"},
{"value":"ben-tre","text":"Bến Tre"}, {"value":"ben-tre","label":"Bến Tre"},
{"value":"binh-dinh","text":"Bình Định"}, {"value":"binh-dinh","label":"Bình Định"},
{"value":"binh-duong","text":"Bình Dương"}, {"value":"binh-duong","label":"Bình Dương"},
{"value":"binh-phuoc","text":"Bình Phước"}, {"value":"binh-phuoc","label":"Bình Phước"},
{"value":"binh-thuan","text":"Bình Thuận"}, {"value":"binh-thuan","label":"Bình Thuận"},
{"value":"ca-mau","text":"Cà Mau"}, {"value":"ca-mau","label":"Cà Mau"},
{"value":"cao-bang","text":"Cao Bằng"}, {"value":"cao-bang","label":"Cao Bằng"},
{"value":"dak-lak","text":"Đắk Lắk"}, {"value":"dak-lak","label":"Đắk Lắk"},
{"value":"dak-nong","text":"Đắk Nông"}, {"value":"dak-nong","label":"Đắk Nông"},
{"value":"dien-bien","text":"Điện Biên"}, {"value":"dien-bien","label":"Điện Biên"},
{"value":"dong-nai","text":"Đồng Nai"}, {"value":"dong-nai","label":"Đồng Nai"},
{"value":"dong-thap","text":"Đồng Tháp"}, {"value":"dong-thap","label":"Đồng Tháp"},
{"value":"gia-lai","text":"Gia Lai"}, {"value":"gia-lai","label":"Gia Lai"},
{"value":"ha-giang","text":"Hà Giang"}, {"value":"ha-giang","label":"Hà Giang"},
{"value":"ha-nam","text":"Hà Nam"}, {"value":"ha-nam","label":"Hà Nam"},
{"value":"ha-tinh","text":"Hà Tĩnh"}, {"value":"ha-tinh","label":"Hà Tĩnh"},
{"value":"hai-duong","text":"Hải Dương"}, {"value":"hai-duong","label":"Hải Dương"},
{"value":"hau-giang","text":"Hậu Giang"}, {"value":"hau-giang","label":"Hậu Giang"},
{"value":"hoa-binh","text":"Hòa Bình"}, {"value":"hoa-binh","label":"Hòa Bình"},
{"value":"hung-yen","text":"Hưng Yên"}, {"value":"hung-yen","label":"Hưng Yên"},
{"value":"khanh-hoa","text":"Khánh Hòa"}, {"value":"khanh-hoa","label":"Khánh Hòa"},
{"value":"kien-giang","text":"Kiên Giang"}, {"value":"kien-giang","label":"Kiên Giang"},
{"value":"kon-tum","text":"Kon Tum"}, {"value":"kon-tum","label":"Kon Tum"},
{"value":"lai-chau","text":"Lai Châu"}, {"value":"lai-chau","label":"Lai Châu"},
{"value":"lam-dong","text":"Lâm Đồng"}, {"value":"lam-dong","label":"Lâm Đồng"},
{"value":"lang-son","text":"Lạng Sơn"}, {"value":"lang-son","label":"Lạng Sơn"},
{"value":"lao-cai","text":"Lào Cai"}, {"value":"lao-cai","label":"Lào Cai"},
{"value":"long-an","text":"Long An"}, {"value":"long-an","label":"Long An"},
{"value":"nam-dinh","text":"Nam Định"}, {"value":"nam-dinh","label":"Nam Định"},
{"value":"nghe-an","text":"Nghệ An"}, {"value":"nghe-an","label":"Nghệ An"},
{"value":"ninh-binh","text":"Ninh Bình"}, {"value":"ninh-binh","label":"Ninh Bình"},
{"value":"ninh-thuan","text":"Ninh Thuận"}, {"value":"ninh-thuan","label":"Ninh Thuận"},
{"value":"phu-tho","text":"Phú Thọ"}, {"value":"phu-tho","label":"Phú Thọ"},
{"value":"quang-binh","text":"Quảng Bình"}, {"value":"quang-binh","label":"Quảng Bình"},
{"value":"quang-nam","text":"Quảng Nam"}, {"value":"quang-nam","label":"Quảng Nam"},
{"value":"quang-ngai","text":"Quảng Ngãi"}, {"value":"quang-ngai","label":"Quảng Ngãi"},
{"value":"quang-ninh","text":"Quảng Ninh"}, {"value":"quang-ninh","label":"Quảng Ninh"},
{"value":"quang-tri","text":"Quảng Trị"}, {"value":"quang-tri","label":"Quảng Trị"},
{"value":"soc-trang","text":"Sóc Trăng"}, {"value":"soc-trang","label":"Sóc Trăng"},
{"value":"son-la","text":"Sơn La"}, {"value":"son-la","label":"Sơn La"},
{"value":"tay-ninh","text":"Tây Ninh"}, {"value":"tay-ninh","label":"Tây Ninh"},
{"value":"thai-binh","text":"Thái Bình"}, {"value":"thai-binh","label":"Thái Bình"},
{"value":"thai-nguyen","text":"Thái Nguyên"}, {"value":"thai-nguyen","label":"Thái Nguyên"},
{"value":"thanh-hoa","text":"Thanh Hóa"}, {"value":"thanh-hoa","label":"Thanh Hóa"},
{"value":"thua-thien-hue","text":"Thừa Thiên Huế"}, {"value":"thua-thien-hue","label":"Thừa Thiên Huế"},
{"value":"tien-giang","text":"Tiền Giang"}, {"value":"tien-giang","label":"Tiền Giang"},
{"value":"tra-vinh","text":"Trà Vinh"}, {"value":"tra-vinh","label":"Trà Vinh"},
{"value":"tuyen-quang","text":"Tuyên Quang"}, {"value":"tuyen-quang","label":"Tuyên Quang"},
{"value":"vinh-long","text":"Vĩnh Long"}, {"value":"vinh-long","label":"Vĩnh Long"},
{"value":"vinh-phuc","text":"Vĩnh Phúc"}, {"value":"vinh-phuc","label":"Vĩnh Phúc"},
{"value":"yen-bai","text":"Yên Bái"}, {"value":"yen-bai","label":"Yên Bái"},
{"value":"phu-yen","text":"Phú Yên"} {"value":"phu-yen","label":"Phú Yên"}
]; ];

View File

@@ -2,20 +2,22 @@ import axios, {AxiosResponse} from "axios";
import {SERVER_API} from "@/config"; import {SERVER_API} from "@/config";
import {ChatboxTextMessage} from "@/typings/message.d"; import {ChatboxTextMessage} from "@/typings/message.d";
import {getAdminInfo} from "@/lib/user"; import {getUserCredential} from "@/lib/user";
import {APIResponse} from "@/typings/network"; import {APIResponse} from "@/typings/network";
import {message} from "antd"; import {message} from "antd";
type APIResultType = {status: 'ok'|'error', data?: any, msg?: string}; type APIResultType = {status: 'ok'|'error', data?: any, msg?: string};
const admin_info = getAdminInfo(); //const admin_info = getAdminInfo();
const user_credentials = getUserCredential();
// reference: https://www.npmjs.com/package/axios#axios-api // reference: https://www.npmjs.com/package/axios#axios-api
const axios_instance = axios.create({ const axios_instance = axios.create({
baseURL: SERVER_API, baseURL: SERVER_API,
timeout: 10000, timeout: 10000,
headers: { headers: {
Authorization: admin_info.jwt, // admin_info.jwt contains client_id & admin_id Authorization: user_credentials, // admin_info.jwt, // admin_info.jwt contains client_id & admin_id
} }
}) })
@@ -60,7 +62,7 @@ const get = async (endpoint: string, params?: object): Promise<APIResultType> =>
}); });
return formatAxiosResponse(res); return formatAxiosResponse(res);
}catch (e) { }catch (e: any) {
return { return {
status: 'error', status: 'error',
msg: e.message, msg: e.message,
@@ -73,7 +75,7 @@ const post = async (endpoint: string, data?: object): Promise<APIResultType> =>
let res: AxiosResponse = await axios_instance.post(endpoint, data); let res: AxiosResponse = await axios_instance.post(endpoint, data);
return formatAxiosResponse(res); return formatAxiosResponse(res);
}catch (e) { }catch (e: any) {
return { return {
status: 'error', status: 'error',
msg: e.message, msg: e.message,
@@ -88,7 +90,7 @@ const put = async (endpoint: string, data: object, params?: object): Promise<API
}); });
return formatAxiosResponse(res); return formatAxiosResponse(res);
}catch (e) { }catch (e: any) {
return { return {
status: 'error', status: 'error',
msg: e.message, msg: e.message,
@@ -103,7 +105,7 @@ const patch = async (endpoint: string, data: any, params?: object): Promise<APIR
}); });
return formatAxiosResponse(res); return formatAxiosResponse(res);
}catch (e) { }catch (e: any) {
return { return {
status: 'error', status: 'error',
msg: e.message, msg: e.message,
@@ -118,7 +120,7 @@ const del = async (endpoint: string, params?: object): Promise<APIResultType> =>
}); });
return formatAxiosResponse(res); return formatAxiosResponse(res);
}catch (e) { }catch (e: any) {
return { return {
status: 'error', status: 'error',
msg: e.message, msg: e.message,

View File

@@ -4,6 +4,9 @@ import {AdminInfo} from "@/typings/user";
import {actions} from "@/store/actions"; import {actions} from "@/store/actions";
import {getConnectNode} from "@/config"; import {getConnectNode} from "@/config";
import store from "store2";
import {CREDENTIAL_SAVE_KEY} from "@/config";
let _user_last_active_time: number = 0; let _user_last_active_time: number = 0;
@@ -13,6 +16,11 @@ let _user_last_active_time: number = 0;
} }
}*/ }*/
export const getUserCredential = (): string | undefined => {
return store.has(CREDENTIAL_SAVE_KEY) ? store(CREDENTIAL_SAVE_KEY) : undefined;
}
const getAdminInfo = () : AdminInfo => { const getAdminInfo = () : AdminInfo => {
//if(MODE === 'dev') return x as AdminInfo; //if(MODE === 'dev') return x as AdminInfo;
return window.admin_info || { client_id:'', id: '', name:'', jwt: '', group_id: '', node: '' }; return window.admin_info || { client_id:'', id: '', name:'', jwt: '', group_id: '', node: '' };

View File

@@ -5,7 +5,8 @@ const createProxyMiddleware = require('http-proxy-middleware');
// proxy middleware options // proxy middleware options
// see: https://www.npmjs.com/package/http-proxy-middleware#http-proxy-options // see: https://www.npmjs.com/package/http-proxy-middleware#http-proxy-options
const options = { const options = {
target: 'https://api195.chatngay.com/admin/', // target host // target: 'https://api195.chatngay.com/admin/', // target host
target: 'http://local.chatngay.api/admin/', //https://api195.chatngay.com/admin/', // target host
changeOrigin: true, // needed for virtual hosted sites changeOrigin: true, // needed for virtual hosted sites
//ws: true, // proxy websockets //ws: true, // proxy websockets
pathRewrite: { pathRewrite: {

View File

@@ -6,7 +6,7 @@ import {Dispatch} from "redux";
import storage, {userChatHistoryStorageKey} from "@/lib/storage"; import storage, {userChatHistoryStorageKey} from "@/lib/storage";
const changeUserVisibilityState = (new_state: VisibilityState) : Action => { const changeUserVisibilityState = (new_state: DocumentVisibilityState) : Action => {
return _createAction('UPDATE_USER_VISIBILITY_STATE', new_state); return _createAction('UPDATE_USER_VISIBILITY_STATE', new_state);
} }

View File

@@ -7,7 +7,7 @@ import {ChatboxTextMessage, ServerMessage, StatusMessageType} from "@/typings/me
import {findObjectInArray} from "@/lib/utils"; import {findObjectInArray} from "@/lib/utils";
const updateUserVisibilityState = (current_state: VisibilityState = 'visible', action: Action) : VisibilityState => { const updateUserVisibilityState = (current_state: DocumentVisibilityState = 'visible', action: Action) : DocumentVisibilityState => {
if(action.type === 'UPDATE_USER_VISIBILITY_STATE') { if(action.type === 'UPDATE_USER_VISIBILITY_STATE') {
return action.payload; return action.payload;
} }

View File

@@ -6,7 +6,7 @@ export type NetworkingStatusType = 'online' | 'offline';
export type NodeConnectionStatusType = 'ok' | 'error' | 'reconnected'; export type NodeConnectionStatusType = 'ok' | 'error' | 'reconnected';
export interface AppState { export interface AppState {
userVisibilityState: VisibilityState; userVisibilityState: DocumentVisibilityState;
network_connection: NetworkingStatusType; // user's internet is working or not? network_connection: NetworkingStatusType; // user's internet is working or not?
node_connection: NodeConnectionStatusType; // connection to node node_connection: NodeConnectionStatusType; // connection to node
user_list: UserInfo[]; user_list: UserInfo[];