aio-login 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +1 -0
  2. package/index.css +187 -0
  3. package/index.js +1189 -0
  4. package/package.json +30 -0
package/README.md ADDED
@@ -0,0 +1 @@
1
+ # aio-login
package/index.css ADDED
@@ -0,0 +1,187 @@
1
+
2
+ .aio-login{
3
+ font-size:14px;
4
+ font-family:IRANSans-Light;
5
+ direction:rtl;
6
+ width:100%;
7
+ min-height:fit-content;
8
+ }
9
+ .aio-login-reload{
10
+ width:100%;
11
+ height:60px;
12
+ display: flex;
13
+ align-items: center;
14
+ justify-content: center;
15
+ margin:24px;
16
+ }
17
+ .aio-login-reload button{
18
+ font-size:14px;
19
+ background:dodgerblue;
20
+ color:#fff;
21
+ border:none;
22
+ padding:12px 36px;
23
+ border-radius:6px;
24
+ }
25
+ .aio-login .aio-form{
26
+ background: none;
27
+ }
28
+ .aio-login .aio-form-body{
29
+ padding:12px;
30
+ background: none;
31
+ }
32
+ .aio-login .aio-input-before{
33
+ background:#f6f7f9;
34
+ color:#9ba9c3;
35
+ }
36
+ .aio-login .aio-input-after{
37
+ background:#f6f7f9;
38
+ color:#9ba9c3;
39
+ }
40
+ .aio-login-or{
41
+ font-size:14px;
42
+ color:#aaa;
43
+ }
44
+ .aio-login-splitter{
45
+ height:1px;
46
+ background:#aaa;
47
+ width:100%;
48
+ }
49
+ .aio-login-title{
50
+ font-size:18px;
51
+ color:#445778;
52
+ font-weight: bold;
53
+ padding:0 12px;
54
+ margin-bottom:12px;
55
+ }
56
+ .aio-login-subtitle{
57
+ font-size:12px;
58
+ color:#445778;
59
+ padding:0 12px;
60
+ margin-bottom:6px;
61
+ text-align: right;
62
+ }
63
+ .aio-login-text{
64
+ padding:0 12px;
65
+ font-size:12px;
66
+ font-weight:bold;
67
+ color:darkblue;
68
+ }
69
+ .aio-login-other-method{
70
+ border: 0;
71
+ color: rgb(23, 123, 223);
72
+ background:#f1f6f7;
73
+ width:100%;
74
+ height:36px;
75
+ border-radius:6px;
76
+ cursor: pointer;
77
+ font-family: inherit;
78
+ text-align:right;
79
+ padding:0 8px;
80
+ user-select: none;
81
+ -webkit-user-select: none;
82
+ font-size: 12px;
83
+ font-weight: bold;
84
+ margin-bottom:12px;
85
+ }
86
+ .aio-login-Gmail{
87
+ background:#387bdc;
88
+ color:#fff;
89
+ }
90
+ .aio-login-other-method svg{
91
+ background:#fff;
92
+ border-radius:100%;
93
+ padding:3px;
94
+ }
95
+ .aio-login-form{
96
+ background:#fff;
97
+ margin:12px;
98
+ width:100%;
99
+ padding:12px;
100
+ border-radius:12px;
101
+ }
102
+ .aio-login .aio-input{
103
+ border:1px solid #ced9e0;
104
+ height:40px;
105
+ outline:none;
106
+ border-radius:6px;
107
+ font-size:inherit;
108
+ }
109
+ .aio-login .aio-input input{
110
+ font-size:inherit;
111
+ }
112
+ .aio-login .aio-input-form{
113
+ overflow:visible;
114
+ }
115
+ .aio-login .aio-input-form-body{
116
+ overflow:visible;
117
+ }
118
+
119
+ .aio-login-submit{
120
+ height:40px;
121
+ width:100%;
122
+ border-radius:6px;
123
+ border:1px solid #1265db;
124
+ background:#1265db;
125
+ color:#fff;
126
+ display:flex;
127
+ align-items: center;
128
+ justify-content: center;
129
+ cursor:pointer;
130
+ font-family:inherit;
131
+ }
132
+ .aio-login-submit-outline{
133
+ background:none;
134
+ color:#1265db;
135
+ }
136
+ .aio-login-button{
137
+ height:40px;
138
+ width:100%;
139
+ border-radius:6px;
140
+ border:1px solid #1265db;
141
+ background:#fff;
142
+ border:none;
143
+ color:#1265db;
144
+ display:flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ cursor:pointer;
148
+ }
149
+ .aio-login-submit:disabled{
150
+ cursor:not-allowed;
151
+ background:#aaa;
152
+ border:1px solid #aaa;
153
+ }
154
+ .aio-login .aio-form-row{
155
+ margin-bottom:12px;
156
+ }
157
+ .aio-login .aio-input.aio-login-otp-code input{
158
+ font-size: 200%;
159
+ letter-spacing: 24px;
160
+ text-align: center;
161
+ direction:ltr;
162
+ }
163
+ .aio-login-register-button{
164
+ color:#1265db;
165
+ background:none;
166
+ border:none;
167
+ font-family:inherit;
168
+ cursor:pointer;
169
+ }
170
+ .aio-login .aio-login-register-tabs{
171
+ margin-bottom:24px;
172
+ font-family: inherit;
173
+ border:none;
174
+ }
175
+ .aio-login-register-tabs .aio-input-tabs-option{
176
+ flex:1;
177
+ }
178
+ .aio-login-register-tabs .aio-input-tabs-option-value{
179
+ text-align:center;
180
+ align-items: center;
181
+ }
182
+ .aio-login-forget{
183
+ padding:0 12px;
184
+ font-size:80%;
185
+ margin-top:12px;
186
+ margin-bottom:24px;
187
+ }
package/index.js ADDED
@@ -0,0 +1,1189 @@
1
+ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
3
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
4
+ import React, { Component, createRef } from 'react';
5
+ import RVD from 'react-virtual-dom';
6
+ import AIOStorage from 'aio-storage';
7
+ import AIOInput from 'aio-input';
8
+ import { Icon } from '@mdi/react';
9
+ import { mdiCellphone, mdiLock, mdiLoading, mdiAccount, mdiAccountBoxOutline, mdiEmail, mdiChevronRight } from '@mdi/js';
10
+ import AIOPopup from 'aio-popup';
11
+ import './index.css';
12
+ import { jsx as _jsx } from "react/jsx-runtime";
13
+ import { jsxs as _jsxs } from "react/jsx-runtime";
14
+ export default class AIOlogin {
15
+ constructor(props) {
16
+ _defineProperty(this, "render", () => /*#__PURE__*/_jsx(AIOLOGIN, {
17
+ ...this.props,
18
+ getActions: ({
19
+ setMode
20
+ }) => this.setMode = setMode
21
+ }));
22
+ let {
23
+ id,
24
+ onAuth,
25
+ onSubmit,
26
+ modes,
27
+ timer,
28
+ checkToken,
29
+ register,
30
+ userId,
31
+ attrs,
32
+ forget,
33
+ otpLength
34
+ } = props;
35
+ AIOLoginValidator(props);
36
+ let storage = AIOStorage(`-AIOLogin-${id}`);
37
+ this.setStorage = (key, value) => {
38
+ storage.save({
39
+ name: key,
40
+ value
41
+ });
42
+ };
43
+ this.getStorage = () => {
44
+ let token = storage.load({
45
+ name: 'token',
46
+ def: false
47
+ });
48
+ let userId = storage.load({
49
+ name: 'userId',
50
+ def: ''
51
+ });
52
+ let userInfo = storage.load({
53
+ name: 'userInfo'
54
+ });
55
+ return {
56
+ token,
57
+ userId,
58
+ userInfo
59
+ };
60
+ };
61
+ this.setUserInfo = userInfo => {
62
+ this.setStorage('userInfo', userInfo);
63
+ };
64
+ this.getUserInfo = () => {
65
+ return this.getStorage().userInfo;
66
+ };
67
+ this.setToken = token => {
68
+ this.setStorage('token', token);
69
+ };
70
+ this.getToken = () => {
71
+ return this.getStorage().token;
72
+ };
73
+ this.removeToken = () => {
74
+ storage.remove({
75
+ name: 'token'
76
+ });
77
+ };
78
+ this.getUserId = () => {
79
+ return this.getStorage().userId;
80
+ };
81
+ this.logout = () => {
82
+ this.removeToken();
83
+ window.location.reload();
84
+ };
85
+ this.props = {
86
+ id,
87
+ checkToken,
88
+ onAuth,
89
+ onSubmit,
90
+ modes,
91
+ register,
92
+ userId,
93
+ attrs,
94
+ timer,
95
+ forget,
96
+ otpLength,
97
+ getStorage: this.getStorage,
98
+ setStorage: this.setStorage,
99
+ removeToken: this.removeToken,
100
+ setToken: this.setToken,
101
+ getToken: this.getToken,
102
+ getUserId: this.getUserId,
103
+ logout: this.logout
104
+ };
105
+ }
106
+ }
107
+ class AIOLOGIN extends Component {
108
+ constructor(props) {
109
+ super(props);
110
+ this.state = {
111
+ isTokenChecked: false,
112
+ showReload: false,
113
+ reportedAuthToParent: false,
114
+ mode: props.modes[0],
115
+ loading: false
116
+ };
117
+ props.getActions({
118
+ setMode: this.setMode.bind(this)
119
+ });
120
+ }
121
+ async checkToken() {
122
+ let {
123
+ getStorage,
124
+ checkToken,
125
+ removeToken
126
+ } = this.props;
127
+ let {
128
+ token,
129
+ userId,
130
+ userInfo
131
+ } = getStorage();
132
+ let result;
133
+ if (typeof token !== 'string') {
134
+ result = false;
135
+ } else {
136
+ try {
137
+ result = await checkToken(token, {
138
+ userId,
139
+ userInfo
140
+ });
141
+ } catch (err) {
142
+ new AIOPopup().addAlert({
143
+ type: 'error',
144
+ text: 'بررسی توکن با خطا روبرو شد',
145
+ subtext: this.getError(err)
146
+ });
147
+ }
148
+ }
149
+ if (result === true) {
150
+ this.setMode('auth');
151
+ } else if (result === false) {
152
+ removeToken();
153
+ } else {
154
+ if (typeof result === 'string') {
155
+ new AIOPopup().addAlert({
156
+ type: 'error',
157
+ text: 'بررسی توکن با خطا روبرو شد',
158
+ subtext: result
159
+ });
160
+ }
161
+ this.setState({
162
+ showReload: true
163
+ });
164
+ }
165
+ this.setState({
166
+ isTokenChecked: true
167
+ });
168
+ }
169
+ getError(err) {
170
+ if (typeof err === 'string') {
171
+ return err;
172
+ }
173
+ if (typeof err === 'object') {
174
+ if (typeof err.response === 'object') {
175
+ if (typeof err.response.data === 'object') {
176
+ let {
177
+ message,
178
+ Message
179
+ } = err.response.data;
180
+ return Message || message;
181
+ } else if (typeof err.response.data === 'string') {
182
+ return err.response.data;
183
+ } else {
184
+ return 'error';
185
+ }
186
+ } else {
187
+ return err.message || err.Message;
188
+ }
189
+ }
190
+ }
191
+ async componentDidMount() {
192
+ this.checkToken();
193
+ }
194
+ async onSubmit(model) {
195
+ let {
196
+ setStorage,
197
+ removeToken,
198
+ onSubmit
199
+ } = this.props;
200
+ let {
201
+ mode: currentMode
202
+ } = this.state;
203
+ let res;
204
+ this.setState({
205
+ loading: false
206
+ });
207
+ try {
208
+ res = await onSubmit(model, currentMode);
209
+ } catch {
210
+ this.setState({
211
+ loading: false
212
+ });
213
+ return;
214
+ }
215
+ this.setState({
216
+ loading: false
217
+ });
218
+ if (typeof res === 'string') {
219
+ let text = {
220
+ "OTPNumber": 'ارسال شماره همراه',
221
+ "OTPCode": 'ارسال کد یکبار مصرف',
222
+ "userName": 'ارسال نام کاربری و رمز عبور',
223
+ "phoneNumber": 'ارسال شماره همراه و رمز عبور',
224
+ "email": 'ارسال آدرس ایمیل و رمز عبور',
225
+ "register": 'عملیات ثبت نام'
226
+ }[currentMode];
227
+ let subtext = res;
228
+ new AIOPopup().addAlert({
229
+ type: 'error',
230
+ text,
231
+ subtext
232
+ });
233
+ } else {
234
+ if (['OTPNumber', 'phoneNumber', 'userName', 'email'].indexOf(currentMode) !== -1) {
235
+ setStorage('userId', model.login.userId);
236
+ }
237
+ }
238
+ }
239
+ setMode(mode) {
240
+ this.setState({
241
+ mode
242
+ });
243
+ }
244
+ render() {
245
+ let {
246
+ otpLength,
247
+ onAuth,
248
+ id,
249
+ timer,
250
+ modes,
251
+ userId,
252
+ register = {},
253
+ attrs = {},
254
+ forget,
255
+ getStorage,
256
+ logout,
257
+ splash = () => null
258
+ } = this.props;
259
+ let {
260
+ reportedAuthToParent,
261
+ isTokenChecked,
262
+ showReload,
263
+ mode,
264
+ loading
265
+ } = this.state;
266
+ if (showReload) {
267
+ return /*#__PURE__*/_jsx("div", {
268
+ className: "aio-login-reload",
269
+ children: /*#__PURE__*/_jsx("button", {
270
+ onClick: () => window.location.reload(),
271
+ children: "\u0628\u0627\u0631\u06AF\u0630\u0627\u0631\u06CC \u0645\u062C\u062F\u062F"
272
+ })
273
+ });
274
+ }
275
+ //اگر هنوز توکن چک نشده ادامه نده
276
+ if (!isTokenChecked) {
277
+ return splash();
278
+ }
279
+ //اگر توکن چک شده و توکن ولید بوده onAuth رو کال کن و ادامه نده
280
+ if (mode === 'auth') {
281
+ //برای جلوگیری از لوپ بی نهایت فقط یکبار onAuth رو کال کن
282
+ if (!reportedAuthToParent) {
283
+ let {
284
+ token,
285
+ userId,
286
+ userInfo
287
+ } = getStorage();
288
+ onAuth({
289
+ token,
290
+ userId,
291
+ userInfo,
292
+ logout
293
+ });
294
+ setTimeout(() => {
295
+ this.setState({
296
+ reportedAuthToParent: true
297
+ });
298
+ }, 0);
299
+ }
300
+ return splash();
301
+ }
302
+ // وقتی به اینجا رسیدی یعنی توکن قطعا چک شده و ولید نبوده پس لاگین رو رندر کن
303
+ let fields = register.fields;
304
+ this.fields = fields;
305
+ let registerText = register.text || 'ثبت نام';
306
+ let props = {
307
+ forget,
308
+ timer,
309
+ otpLength,
310
+ id,
311
+ modes,
312
+ attrs,
313
+ userId,
314
+ fields,
315
+ registerText
316
+ };
317
+ let html = /*#__PURE__*/_jsx(LoginForm, {
318
+ ...props,
319
+ loading: loading,
320
+ registerButton: register.type === 'button' ? registerText : undefined,
321
+ registerTab: register.type === 'tab' ? registerText : undefined,
322
+ onSubmit: this.onSubmit.bind(this),
323
+ onChangeMode: mode => this.setMode(mode),
324
+ mode: mode
325
+ });
326
+ return html;
327
+ }
328
+ }
329
+ class LoginForm extends Component {
330
+ constructor(props) {
331
+ super(props);
332
+ this.storage = AIOStorage(`-AIOLogin-${props.id}`);
333
+ let {
334
+ timer = 30,
335
+ fields = []
336
+ } = props;
337
+ this.state = {
338
+ fields,
339
+ timer,
340
+ recode: false,
341
+ tab: 'login',
342
+ model: this.getInitialModel(props.mode)
343
+ };
344
+ }
345
+ getLabels(mode) {
346
+ let {
347
+ model,
348
+ tab
349
+ } = this.state;
350
+ let {
351
+ registerText,
352
+ forget
353
+ } = this.props;
354
+ if (mode === 'OTPNumber') {
355
+ let subtitle = 'شماره همراه خود را وارد کنید . پیامکی حاوی کد برای شما ارسال خواهد شد';
356
+ return {
357
+ inputLabel: 'شماره همراه',
358
+ title: 'ورود با کد یکبار مصرف',
359
+ submitText: 'ورود',
360
+ subtitle
361
+ };
362
+ }
363
+ if (mode === 'OTPCode') {
364
+ return {
365
+ inputLabel: 'کد پیامک شده',
366
+ title: false,
367
+ submitText: 'ورود',
368
+ subtitle: `کد پیامک شده به شماره ی ${model.login.userId} را وارد کنید`
369
+ };
370
+ }
371
+ if (mode === 'register') {
372
+ return {
373
+ inputLabel: false,
374
+ title: registerText,
375
+ submitText: registerText,
376
+ subtitle: false,
377
+ backButton: tab !== 'register'
378
+ };
379
+ }
380
+ if (mode === 'forgetUserId') {
381
+ let subtitle = `${forget.mode === 'phoneNumber' ? 'شماره همراه' : 'ایمیل'} خود را وارد کنید . کد باز یابی رمز عبور برای شما ارسال خواهد شد`;
382
+ return {
383
+ inputLabel: forget.mode === 'email' ? 'ایمیل' : 'شماره همراه',
384
+ backButton: true,
385
+ title: 'بازیابی رمز عبور',
386
+ submitText: 'دریافت کد بازیابی رمز',
387
+ subtitle
388
+ };
389
+ }
390
+ if (mode === 'forgetPassword') {
391
+ let {
392
+ mode
393
+ } = forget;
394
+ let subtitle = `کد ${mode === 'phoneNumber' ? 'پیامک' : 'ایمیل'} شده به ${mode === 'phoneNumber' ? 'شماره ی' : 'آدرس'} ${model.forget.userId} را وارد کنید`;
395
+ return {
396
+ inputLabel: `کد ${mode === 'email' ? 'ایمیل' : 'پیامک'} شده`,
397
+ backButton: true,
398
+ title: 'بازیابی رمز عبور',
399
+ submitText: 'تایید',
400
+ subtitle
401
+ };
402
+ }
403
+ if (mode === 'userName') {
404
+ return {
405
+ inputLabel: 'نام کاربری',
406
+ title: 'ورود با نام کاربری',
407
+ submitText: 'ورود',
408
+ subtitle: false
409
+ };
410
+ }
411
+ if (mode === 'email') {
412
+ return {
413
+ inputLabel: 'ایمیل',
414
+ title: 'ورود با ایمیل',
415
+ submitText: 'ورود',
416
+ subtitle: false
417
+ };
418
+ }
419
+ if (mode === 'phoneNumber') {
420
+ return {
421
+ inputLabel: 'شماره همراه',
422
+ title: 'ورود با شماره همراه',
423
+ submitText: 'ورود',
424
+ subtitle: false
425
+ };
426
+ }
427
+ }
428
+ changeMode(mode) {
429
+ let {
430
+ onChangeMode
431
+ } = this.props;
432
+ onChangeMode(mode);
433
+ this.setState({
434
+ model: this.getInitialModel(mode)
435
+ });
436
+ }
437
+ getInitialModel(mode) {
438
+ if (!mode) {
439
+ mode = this.props.mode;
440
+ }
441
+ let {
442
+ userId
443
+ } = this.props;
444
+ return {
445
+ forget: {},
446
+ register: {},
447
+ login: {
448
+ userId
449
+ }
450
+ };
451
+ }
452
+ title_layout({
453
+ title,
454
+ backButton
455
+ }) {
456
+ if (!title) {
457
+ return false;
458
+ }
459
+ let {
460
+ modes
461
+ } = this.props;
462
+ return {
463
+ className: 'aio-login-title',
464
+ align: 'v',
465
+ row: [{
466
+ show: !!backButton,
467
+ html: /*#__PURE__*/_jsx(Icon, {
468
+ path: mdiChevronRight,
469
+ size: 1
470
+ }),
471
+ size: 48,
472
+ align: 'vh',
473
+ onClick: () => this.changeMode(modes[0])
474
+ }, {
475
+ html: title
476
+ }]
477
+ };
478
+ }
479
+ subtitle_layout({
480
+ subtitle
481
+ }) {
482
+ if (!subtitle) {
483
+ return false;
484
+ }
485
+ return {
486
+ html: subtitle,
487
+ className: 'aio-login-subtitle'
488
+ };
489
+ }
490
+ getInput_phoneNumber(field, getValue) {
491
+ return {
492
+ field,
493
+ label: 'شماره همراه',
494
+ input: {
495
+ type: 'text',
496
+ justNumber: true,
497
+ before: /*#__PURE__*/_jsx(Icon, {
498
+ path: mdiCellphone,
499
+ size: 0.8
500
+ }),
501
+ placeholder: '09...',
502
+ maxLength: 11,
503
+ attrs: {
504
+ style: {
505
+ direction: 'ltr'
506
+ }
507
+ }
508
+ },
509
+ validations: [['function', () => {
510
+ let value = getValue();
511
+ if (!value) {
512
+ return 'شماره همراه خود را وارد کنید';
513
+ }
514
+ if (value.indexOf('09') !== 0) {
515
+ return 'شماره همراه باید با 09 شروع شود';
516
+ }
517
+ if (value.length !== 11) {
518
+ return 'شماره همراه باید 11 رقم باشد';
519
+ }
520
+ return false;
521
+ }]]
522
+ };
523
+ }
524
+ getInput_userName(field) {
525
+ let {
526
+ userId
527
+ } = this.props;
528
+ return {
529
+ field,
530
+ label: 'نام کاربری',
531
+ validations: [['required']],
532
+ style: {
533
+ direction: 'ltr'
534
+ },
535
+ input: {
536
+ type: 'text',
537
+ disabled: !!userId,
538
+ before: /*#__PURE__*/_jsx(Icon, {
539
+ path: mdiAccount,
540
+ size: 0.8
541
+ })
542
+ }
543
+ };
544
+ }
545
+ getInput_email(field, getValue) {
546
+ let {
547
+ userId
548
+ } = this.props;
549
+ return {
550
+ field,
551
+ label: 'ایمیل',
552
+ style: {
553
+ direction: 'ltr'
554
+ },
555
+ input: {
556
+ type: 'text',
557
+ disabled: !!userId,
558
+ before: /*#__PURE__*/_jsx(Icon, {
559
+ path: mdiEmail,
560
+ size: 0.8
561
+ })
562
+ },
563
+ validations: [['function', () => {
564
+ let value = getValue();
565
+ if (!value) {
566
+ return 'ایمیل خود را وارد کنید';
567
+ }
568
+ let atSignIndex = value.indexOf('@');
569
+ if (atSignIndex < 1) {
570
+ return 'ایمیل خود را به درستی وارد کنید';
571
+ }
572
+ if (value.indexOf('.') === -1) {
573
+ return 'ایمیل خود را به درستی وارد کنید';
574
+ }
575
+ if (value.lastIndexOf('.') > value.length - 3) {
576
+ return 'ایمیل خود را به درستی وارد کنید';
577
+ }
578
+ return false;
579
+ }]]
580
+ };
581
+ }
582
+ getInput_otp(field, getValue) {
583
+ let {
584
+ otpLength
585
+ } = this.props;
586
+ return {
587
+ field,
588
+ label: 'رمز یکبار مصرف',
589
+ input: {
590
+ maxLength: otpLength,
591
+ justNumber: true,
592
+ type: 'text',
593
+ placeholder: Array(otpLength).fill('-').join(''),
594
+ className: 'aio-login-otp-code'
595
+ },
596
+ validations: [['function', () => {
597
+ let {
598
+ otpLength
599
+ } = this.props;
600
+ let value = getValue();
601
+ if (!value) {
602
+ return 'رمز یکبار مصرف را وارد کنید';
603
+ }
604
+ return value.length !== otpLength ? `رمز یکبار مصرف باید شامل ${otpLength} کاراکتر باشد` : false;
605
+ }]]
606
+ };
607
+ }
608
+ getInput_password(field, type) {
609
+ let validations;
610
+ if (type === 2) {
611
+ validations = [['function', () => {
612
+ let {
613
+ model
614
+ } = this.state;
615
+ let value = model.forget.reNewPassword;
616
+ if (!value) {
617
+ return 'تکرار رمز عبور جدید را وارد کنید';
618
+ }
619
+ if (value.length < 1) {
620
+ return 'رمز عبور را وارد کنید';
621
+ }
622
+ if (value !== model.forget.newPassword) {
623
+ return 'رمز با تکرار آن مطابقت ندارد';
624
+ }
625
+ return false;
626
+ }]];
627
+ } else {
628
+ validations = [['required']];
629
+ }
630
+ return {
631
+ field,
632
+ label: ['رمز عبور', 'رمز عبور جدید', 'تکرار رمز عبور جدید'][type],
633
+ validations,
634
+ input: {
635
+ type: 'password',
636
+ before: /*#__PURE__*/_jsx(Icon, {
637
+ path: mdiLock,
638
+ size: 0.8
639
+ }),
640
+ style: {
641
+ direction: 'ltr'
642
+ },
643
+ visible: true
644
+ }
645
+ };
646
+ }
647
+ getInputs() {
648
+ let {
649
+ fields
650
+ } = this.state;
651
+ let {
652
+ forget,
653
+ mode
654
+ } = this.props;
655
+ if (mode === 'register') {
656
+ return [...fields.map(o => AIOInput.defaults.getInput(o, 'register'))];
657
+ }
658
+ if (mode === 'forgetUserId') {
659
+ return [this['getInput_' + forget.mode](`value.forget.userId`, () => this.state.model.forget.userId)];
660
+ }
661
+ if (mode === 'forgetPassword') {
662
+ return [this.getInput_otp('value.forget.password', () => this.state.model.forget.password), this.getInput_password('value.forget.newPassword', 1), this.getInput_password('value.forget.reNewPassword', 2)];
663
+ }
664
+ if (mode === 'OTPNumber') {
665
+ return [this.getInput_phoneNumber(`value.login.userId`, () => this.state.model.login.userId)];
666
+ }
667
+ if (mode === 'OTPCode') {
668
+ return [this.getInput_otp('value.login.password', () => this.state.model.login.password)];
669
+ }
670
+ return [this['getInput_' + mode]('value.login.userId', () => this.state.model.login.userId), this.getInput_password('value.login.password', 0)];
671
+ }
672
+ form_layout(labels) {
673
+ let {
674
+ model
675
+ } = this.state,
676
+ {
677
+ mode
678
+ } = this.props;
679
+ return {
680
+ className: 'ofy-auto',
681
+ html: /*#__PURE__*/_jsx(AIOInput, {
682
+ type: "form",
683
+ lang: "fa",
684
+ value: model,
685
+ rtl: true,
686
+ onChange: model => this.setState({
687
+ model
688
+ }),
689
+ inputs: {
690
+ props: {
691
+ gap: 12
692
+ },
693
+ column: this.getInputs(labels)
694
+ },
695
+ footer: ({
696
+ disabled
697
+ }) => this.submit_layout({
698
+ submitText: labels.submitText,
699
+ disabled
700
+ })
701
+ }, mode)
702
+ };
703
+ }
704
+ submit_layout({
705
+ submitText,
706
+ disabled
707
+ }) {
708
+ let {
709
+ loading,
710
+ timer,
711
+ mode
712
+ } = this.props;
713
+ let layout = {
714
+ style: {
715
+ padding: '0 12px'
716
+ },
717
+ html: /*#__PURE__*/_jsx(SubmitButton, {
718
+ mode: mode,
719
+ timer: timer,
720
+ text: submitText,
721
+ loading: loading,
722
+ disabled: () => !!disabled,
723
+ onClick: () => this.onSubmit()
724
+ })
725
+ };
726
+ return /*#__PURE__*/_jsx(RVD, {
727
+ layout: layout
728
+ });
729
+ }
730
+ async onSubmit() {
731
+ let {
732
+ onSubmit
733
+ } = this.props;
734
+ let {
735
+ model
736
+ } = this.state;
737
+ onSubmit(model);
738
+ }
739
+ changeUserId_layout() {
740
+ let {
741
+ mode
742
+ } = this.props;
743
+ if (mode !== 'OTPCode') {
744
+ return false;
745
+ }
746
+ return {
747
+ onClick: () => this.changeMode('OTPNumber'),
748
+ className: 'aio-login-text m-b-12',
749
+ align: 'vh',
750
+ html: 'تغییر شماره همراه'
751
+ };
752
+ }
753
+ recode_layout() {
754
+ let {
755
+ model
756
+ } = this.state;
757
+ let {
758
+ mode,
759
+ onChangeMode
760
+ } = this.props;
761
+ if (mode !== 'OTPCode') {
762
+ return false;
763
+ }
764
+ return {
765
+ className: 'aio-login-text m-b-12',
766
+ html: `ارسال مجدد کد`,
767
+ align: 'vh',
768
+ onClick: () => {
769
+ onChangeMode('OTPNumber');
770
+ this.setState({
771
+ model: {
772
+ ...model,
773
+ login: {
774
+ ...model.login,
775
+ password: ''
776
+ }
777
+ }
778
+ });
779
+ }
780
+ };
781
+ }
782
+ changeMode_layout() {
783
+ let {
784
+ mode,
785
+ modes
786
+ } = this.props;
787
+ if (mode === 'register' || mode === 'forgetUserId' || mode === 'forgetPassword') {
788
+ return false;
789
+ }
790
+ let others = [];
791
+ for (let i = 0; i < modes.length; i++) {
792
+ let key = modes[i];
793
+ if (mode === key) {
794
+ continue;
795
+ }
796
+ if (mode === 'OTPCode' && key === 'OTPNumber') {
797
+ continue;
798
+ }
799
+ let title = {
800
+ OTPNumber: 'رمز یکبار مصرف',
801
+ userName: 'نام کاربری و رمز عبور',
802
+ email: 'آدرس ایمیل و رمز عبور',
803
+ phoneNumber: 'شماره همراه و رمز عبور'
804
+ }[key];
805
+ let icon = {
806
+ OTPNumber: mdiAccount,
807
+ phoneNumber: mdiCellphone,
808
+ userName: mdiAccountBoxOutline,
809
+ email: mdiEmail
810
+ }[key];
811
+ others.push({
812
+ flex: 1,
813
+ className: `of-visible aio-login-other-method aio-login-${key}`,
814
+ onClick: () => this.changeMode(key),
815
+ row: [{
816
+ html: /*#__PURE__*/_jsx(Icon, {
817
+ path: icon,
818
+ size: 0.7
819
+ }),
820
+ align: 'vh'
821
+ }, {
822
+ size: 6
823
+ }, {
824
+ align: 'v',
825
+ html: title
826
+ }]
827
+ });
828
+ }
829
+ if (!others.length) {
830
+ return false;
831
+ }
832
+ return {
833
+ className: 'p-h-12',
834
+ column: [{
835
+ gap: 6,
836
+ row: [{
837
+ flex: 1,
838
+ html: /*#__PURE__*/_jsx("div", {
839
+ className: "aio-login-splitter"
840
+ }),
841
+ align: 'v'
842
+ }, {
843
+ html: 'یا ورود با',
844
+ align: 'v',
845
+ className: 'aio-login-or bold'
846
+ }, {
847
+ flex: 1,
848
+ html: /*#__PURE__*/_jsx("div", {
849
+ className: "aio-login-splitter"
850
+ }),
851
+ align: 'v'
852
+ }]
853
+ }, {
854
+ size: 12
855
+ }, {
856
+ grid: others,
857
+ gridCols: 1,
858
+ gridRow: {
859
+ gap: 12
860
+ }
861
+ }]
862
+ };
863
+ }
864
+ registerButton_layout() {
865
+ let {
866
+ registerButton,
867
+ mode
868
+ } = this.props;
869
+ if (!registerButton || mode === 'register') {
870
+ return false;
871
+ }
872
+ return {
873
+ align: 'vh',
874
+ html: /*#__PURE__*/_jsx("button", {
875
+ onClick: () => this.changeMode('register'),
876
+ className: "aio-login-register-button",
877
+ children: registerButton
878
+ })
879
+ };
880
+ }
881
+ registerTab_layout() {
882
+ let {
883
+ registerTab,
884
+ modes,
885
+ mode
886
+ } = this.props;
887
+ if (registerTab === true) {
888
+ registerTab = 'ثبت نام';
889
+ }
890
+ if (!registerTab) {
891
+ return false;
892
+ }
893
+ if (mode === 'forgetUserId' || mode === 'forgetPassword') {
894
+ return false;
895
+ }
896
+ return {
897
+ html: /*#__PURE__*/_jsx(AIOInput, {
898
+ className: "aio-login-register-tabs",
899
+ type: "tabs",
900
+ value: mode === 'register' ? 'register' : 'login',
901
+ options: [{
902
+ text: 'ورود',
903
+ value: 'login'
904
+ }, {
905
+ text: registerTab,
906
+ value: 'register'
907
+ }],
908
+ onChange: tab => {
909
+ if (tab === 'login') {
910
+ this.changeMode(modes[0]);
911
+ } else if (tab === 'register') {
912
+ this.changeMode('register');
913
+ }
914
+ }
915
+ })
916
+ };
917
+ }
918
+ forget_layout() {
919
+ let {
920
+ forget,
921
+ mode
922
+ } = this.props;
923
+ if (!forget) {
924
+ return false;
925
+ }
926
+ if (mode === 'register' || mode === 'OTPCode' || mode === 'OTPNumber' || mode === 'forgetUserId' || mode === 'forgetPassword') {
927
+ return false;
928
+ }
929
+ let {
930
+ text = []
931
+ } = forget;
932
+ let buttonText = text[0] || 'رمز عبور خود را فراموش کرده اید؟ اینجا کلیک کنید';
933
+ return {
934
+ className: 'aio-login-forget',
935
+ html: buttonText,
936
+ onClick: () => this.changeMode('forgetUserId')
937
+ };
938
+ }
939
+ render() {
940
+ let {
941
+ attrs,
942
+ mode
943
+ } = this.props,
944
+ labels = this.getLabels(mode);
945
+ return /*#__PURE__*/_jsx(RVD, {
946
+ layout: {
947
+ className: 'aio-login' + (attrs.className ? ' ' + attrs.className : ''),
948
+ style: attrs.style,
949
+ attrs: {
950
+ ...attrs,
951
+ onKeyDown: e => {
952
+ if (e.keyCode === 13) {
953
+ this.onSubmit();
954
+ }
955
+ }
956
+ },
957
+ column: [this.registerTab_layout(), {
958
+ column: [this.title_layout(labels), this.subtitle_layout(labels)]
959
+ }, this.form_layout(labels), this.forget_layout(), {
960
+ gap: 12,
961
+ align: 'h',
962
+ row: [this.recode_layout(), this.changeUserId_layout()]
963
+ }, this.changeMode_layout(), this.registerButton_layout()]
964
+ }
965
+ });
966
+ }
967
+ }
968
+ class SubmitButton extends Component {
969
+ constructor(...args) {
970
+ super(...args);
971
+ _defineProperty(this, "state", {
972
+ time: this.getDelta()
973
+ });
974
+ }
975
+ async onClick() {
976
+ let {
977
+ onClick,
978
+ loading
979
+ } = this.props;
980
+ if (loading) {
981
+ return;
982
+ }
983
+ this.setLastTry();
984
+ await onClick();
985
+ }
986
+ setLastTry() {
987
+ let {
988
+ mode
989
+ } = this.props;
990
+ AIOStorage('aiologinlasttrypermode').save({
991
+ name: 'dic',
992
+ value: {
993
+ ...this.getLastTry(),
994
+ [mode]: new Date().getTime()
995
+ }
996
+ });
997
+ let delta = this.getDelta();
998
+ this.setState({
999
+ time: delta
1000
+ });
1001
+ }
1002
+ getLastTry() {
1003
+ return AIOStorage('aiologinlasttrypermode').load({
1004
+ name: 'dic',
1005
+ def: {}
1006
+ });
1007
+ }
1008
+ getDelta() {
1009
+ let {
1010
+ mode,
1011
+ timer
1012
+ } = this.props;
1013
+ if (!timer) {
1014
+ return 0;
1015
+ }
1016
+ let lastTry = this.getLastTry();
1017
+ let lastTime = lastTry[mode];
1018
+ if (!lastTime) {
1019
+ return 0;
1020
+ }
1021
+ let delta = new Date().getTime() - lastTime;
1022
+ delta = delta / 1000;
1023
+ delta = timer - delta;
1024
+ delta = Math.round(delta);
1025
+ if (delta < 0) {
1026
+ delta = 0;
1027
+ }
1028
+ return delta;
1029
+ }
1030
+ render() {
1031
+ let {
1032
+ disabled,
1033
+ loading,
1034
+ text,
1035
+ outline
1036
+ } = this.props;
1037
+ let isDisabled = disabled();
1038
+ let loadingText = 'در حال ارسال';
1039
+ let {
1040
+ time
1041
+ } = this.state;
1042
+ if (time > 0) {
1043
+ setTimeout(() => this.setState({
1044
+ time: this.state.time - 1
1045
+ }), 1000);
1046
+ } else if (time < 0) {
1047
+ setTimeout(() => this.setState({
1048
+ time: 0
1049
+ }), 0);
1050
+ }
1051
+ if (time) {
1052
+ isDisabled = true;
1053
+ text = `لطفا ${time} ثانیه صبر کنید`;
1054
+ }
1055
+ return /*#__PURE__*/_jsxs("button", {
1056
+ className: 'aio-login-submit' + (outline ? ' aio-login-submit-outline' : ''),
1057
+ disabled: isDisabled,
1058
+ onClick: () => this.onClick(),
1059
+ children: [!loading && text, !!loading && /*#__PURE__*/_jsx(Icon, {
1060
+ path: mdiLoading,
1061
+ size: 1,
1062
+ spin: 0.2,
1063
+ style: {
1064
+ margin: '0 6px'
1065
+ }
1066
+ }), !!loading && loadingText]
1067
+ });
1068
+ }
1069
+ }
1070
+ function AIOLoginValidator(props) {
1071
+ let {
1072
+ id,
1073
+ onAuth,
1074
+ onSubmit,
1075
+ modes,
1076
+ timer,
1077
+ checkToken,
1078
+ register,
1079
+ userId = '',
1080
+ attrs,
1081
+ forget,
1082
+ otpLength
1083
+ } = props;
1084
+ for (let prop in props) {
1085
+ if (['id', 'onAuth', 'onSubmit', 'modes', 'timer', 'checkToken', 'register', 'userId', 'attrs', 'forget', 'otpLength', 'splash'].indexOf(prop) === -1) {
1086
+ let error = `
1087
+ aio-login error => invalid props
1088
+ ${prop} is not one of AIOLogin props,
1089
+ valid props are 'id' | 'onAuth' | 'onSubmit' | 'modes' | 'timer' | 'checkToken' | 'register' | 'userId' | 'attrs' | 'forget' | 'otpLength' | 'splash'
1090
+ `;
1091
+ alert(error);
1092
+ console.log(error);
1093
+ return;
1094
+ }
1095
+ }
1096
+ if (!id) {
1097
+ alert(`aio-login error=> missing id props, id props should be an string`);
1098
+ }
1099
+ if (!onAuth) {
1100
+ let error = `
1101
+ aio-login error => missing onAuth props
1102
+ onAuth type is => ({token:string,userId:string,userInfo?:any,logout:function})=>void
1103
+ `;
1104
+ alert(error);
1105
+ console.log(error);
1106
+ return;
1107
+ }
1108
+ if (typeof userId !== 'string') {
1109
+ let error = `aio-login error=> userId props should be an string`;
1110
+ alert(error);
1111
+ console.log(error);
1112
+ return;
1113
+ }
1114
+ if (!checkToken) {
1115
+ let error = `
1116
+ aio-login error=> missing checkToken props
1117
+ checkToken type is => (token:string)=>boolean
1118
+ for prevent it set checkToken : ()=>true
1119
+ `;
1120
+ alert(error);
1121
+ console.log(error);
1122
+ return;
1123
+ }
1124
+ if (!onSubmit) {
1125
+ let error = `
1126
+ aio-login error=> missing onSubmit props,
1127
+ onSubmit type is =>
1128
+ (model:<model type>,mode:<mode type>)=>string|undefined
1129
+ <model type> is {
1130
+ login:{userId:string,password:string | number},
1131
+ forget:{userId:string,password:string | number},
1132
+ register:{[field:string]:any}
1133
+ }
1134
+ <mode type> is 'OTPNumber' | 'OTPCode' | 'userName' | 'email' | 'phoneNumber' | 'forgetUserId' | 'forgetPassword' | 'register' | 'auth'
1135
+ `;
1136
+ alert(error);
1137
+ console.log(error);
1138
+ return;
1139
+ }
1140
+ if (typeof timer !== 'number') {
1141
+ let error = `aio-login error=> timer props should be an number`;
1142
+ alert(error);
1143
+ console.log(error);
1144
+ return;
1145
+ }
1146
+ if (!Array.isArray(modes) || !modes.filter(o => ['OTPNumber', 'userName', 'email', 'phoneNumber'].indexOf(o) !== -1).length) {
1147
+ let error = `
1148
+ aio-login error=> modes props should be an array contain composite of 'OTPNumber' | 'userName' | 'email' | 'phoneNumber'
1149
+ `;
1150
+ alert(error);
1151
+ console.log(error);
1152
+ return;
1153
+ }
1154
+ if (modes.indexOf('OTPNumber') !== -1) {
1155
+ if (!otpLength) {
1156
+ let error = `aio-login error => otpLength props is not an number (for define length of otp code)`;
1157
+ alert(error);
1158
+ console.log(error);
1159
+ return;
1160
+ }
1161
+ }
1162
+ if (register) {
1163
+ if (typeof register !== 'object' || ['mode', 'tab', 'button'].indexOf(register.type) === -1 || !register.text || !Array.isArray(register.fields) || !register.fields.length) {
1164
+ let error = `
1165
+ aio-login-error => register props should be an object contain :
1166
+ type : "mode" | "tab" | "button"
1167
+ text : string | undefined
1168
+ fields:(
1169
+ "fullname","firstname","lastname","username","address","email","fathername","phone","mobile","postalcode",
1170
+ "nationalcode","idcode","cardbank","state","city","gender","married","militaryservice","location"
1171
+ )[]
1172
+ `;
1173
+ alert(error);
1174
+ console.log(error);
1175
+ return;
1176
+ }
1177
+ }
1178
+ if (forget) {
1179
+ let message = `aio-login error=> forget props should be an object contain mode:'phoneNumber | email'`;
1180
+ if (typeof forget !== 'object') {
1181
+ alert(message);
1182
+ }
1183
+ if (['phoneNumber', 'email'].indexOf(forget.mode) === -1) {
1184
+ alert(message);
1185
+ console.log(message);
1186
+ return;
1187
+ }
1188
+ }
1189
+ }
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "aio-login",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "dependencies": {
10
+ "@mdi/js": "^7.0.96",
11
+ "@mdi/react": "^1.6.1",
12
+ "react": "^18.2.0",
13
+ "react-dom": "^18.2.0",
14
+ "react-scripts": "5.0.1",
15
+ "react-virtual-dom": "^4.0.1",
16
+ "aio-popup": "^3.0.2",
17
+ "aio-storage": "^4.0.1",
18
+ "aio-input": "^2.1.1"
19
+ },
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/mohammadFeiz/aio-login.git"
23
+ },
24
+ "author": "mohammad sharif feiz feiz.ms@gmail.com",
25
+ "license": "ISC",
26
+ "bugs": {
27
+ "url": "https://github.com/mohammadFeiz/aio-login/issues"
28
+ },
29
+ "homepage": "https://github.com/mohammadFeiz/aio-login#readme"
30
+ }