Mhdeusi commited on
Commit
b510677
·
verified ·
1 Parent(s): 96bbfb4

Create logic/utils.js

Browse files
Files changed (1) hide show
  1. js/logic/utils.js +187 -0
js/logic/utils.js ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class Utils {
2
+ static async loadJSON(filePath) {
3
+ try {
4
+ const response = await fetch(filePath);
5
+ if (!response.ok) {
6
+ throw new Error(`HTTP error! status: ${response.status}`);
7
+ }
8
+ const data = await response.json();
9
+ return data;
10
+ } catch (error) {
11
+ console.error(`Error loading JSON from ${filePath}:`, error);
12
+ return null;
13
+ }
14
+ }
15
+
16
+ static saveToLocalStorage(key, data) {
17
+ try {
18
+ localStorage.setItem(key, JSON.stringify(data));
19
+ return true;
20
+ } catch (error) {
21
+ console.error('Error saving to localStorage:', error);
22
+ return false;
23
+ }
24
+ }
25
+
26
+ static loadFromLocalStorage(key) {
27
+ try {
28
+ const data = localStorage.getItem(key);
29
+ return data ? JSON.parse(data) : null;
30
+ } catch (error) {
31
+ console.error('Error loading from localStorage:', error);
32
+ return null;
33
+ }
34
+ }
35
+
36
+ static generateId() {
37
+ return Date.now().toString(36) + Math.random().toString(36).substr(2);
38
+ }
39
+
40
+ static formatTime(seconds) {
41
+ const minutes = Math.floor(seconds / 60);
42
+ const remainingSeconds = seconds % 60;
43
+ return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
44
+ }
45
+
46
+ static sanitizeHTML(str) {
47
+ const div = document.createElement('div');
48
+ div.textContent = str;
49
+ return div.innerHTML;
50
+ }
51
+
52
+ static debounce(func, wait) {
53
+ let timeout;
54
+ return function executedFunction(...args) {
55
+ const later = () => {
56
+ clearTimeout(timeout);
57
+ func(...args);
58
+ };
59
+ clearTimeout(timeout);
60
+ timeout = setTimeout(later, wait);
61
+ };
62
+ }
63
+
64
+ static validateEmail(email) {
65
+ const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
66
+ return re.test(email);
67
+ }
68
+
69
+ static validatePassword(password) {
70
+ return password.length >= 6;
71
+ }
72
+
73
+ static calculatePercentage(part, total) {
74
+ if (total === 0) return 0;
75
+ return Math.round((part / total) * 100);
76
+ }
77
+
78
+ static getCurrentDate() {
79
+ return new Date().toISOString().split('T')[0];
80
+ }
81
+
82
+ static formatNumber(num) {
83
+ return new Intl.NumberFormat('fa-IR').format(num);
84
+ }
85
+
86
+ static shuffleArray(array) {
87
+ const shuffled = [...array];
88
+ for (let i = shuffled.length - 1; i > 0; i--) {
89
+ const j = Math.floor(Math.random() * (i + 1));
90
+ [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
91
+ }
92
+ return shuffled;
93
+ }
94
+
95
+ static isMobileDevice() {
96
+ return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
97
+ }
98
+
99
+ static async copyToClipboard(text) {
100
+ try {
101
+ await navigator.clipboard.writeText(text);
102
+ return true;
103
+ } catch (error) {
104
+ console.error('Failed to copy text:', error);
105
+ return false;
106
+ }
107
+ }
108
+
109
+ static showNotification(message, type = 'info') {
110
+ const notification = document.createElement('div');
111
+ notification.className = `notification notification-${type}`;
112
+ notification.innerHTML = `
113
+ <div class="notification-content">
114
+ <span class="notification-message">${this.sanitizeHTML(message)}</span>
115
+ <button class="notification-close">&times;</button>
116
+ </div>
117
+ `;
118
+
119
+ notification.style.cssText = `
120
+ position: fixed;
121
+ top: 20px;
122
+ left: 50%;
123
+ transform: translateX(-50%);
124
+ background: ${type === 'error' ? '#fed7d7' : type === 'success' ? '#c6f6d5' : '#bee3f8'};
125
+ color: ${type === 'error' ? '#742a2a' : type === 'success' ? '#22543d' : '#2a4365'};
126
+ padding: 12px 20px;
127
+ border-radius: 8px;
128
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
129
+ z-index: 1000;
130
+ animation: slideDown 0.3s ease-out;
131
+ `;
132
+
133
+ document.body.appendChild(notification);
134
+
135
+ notification.querySelector('.notification-close').addEventListener('click', () => {
136
+ notification.remove();
137
+ });
138
+
139
+ setTimeout(() => {
140
+ if (notification.parentNode) {
141
+ notification.remove();
142
+ }
143
+ }, 5000);
144
+ }
145
+ }
146
+
147
+ // اضافه کردن استایل برای نوتیفیکیشن
148
+ const notificationStyles = `
149
+ @keyframes slideDown {
150
+ from {
151
+ opacity: 0;
152
+ transform: translateX(-50%) translateY(-20px);
153
+ }
154
+ to {
155
+ opacity: 1;
156
+ transform: translateX(-50%) translateY(0);
157
+ }
158
+ }
159
+
160
+ .notification-content {
161
+ display: flex;
162
+ align-items: center;
163
+ justify-content: space-between;
164
+ gap: 15px;
165
+ }
166
+
167
+ .notification-close {
168
+ background: none;
169
+ border: none;
170
+ font-size: 18px;
171
+ cursor: pointer;
172
+ padding: 0;
173
+ width: 20px;
174
+ height: 20px;
175
+ display: flex;
176
+ align-items: center;
177
+ justify-content: center;
178
+ }
179
+ `;
180
+
181
+ // تزریق استایل‌ها به صفحه
182
+ if (!document.querySelector('#notification-styles')) {
183
+ const styleElement = document.createElement('style');
184
+ styleElement.id = 'notification-styles';
185
+ styleElement.textContent = notificationStyles;
186
+ document.head.appendChild(styleElement);
187
+ }