Dooratre commited on
Commit
3090b5a
·
verified ·
1 Parent(s): 327d956

Upload 7 files

Browse files
database/__pycache__/db.cpython-310.pyc ADDED
Binary file (7.24 kB). View file
 
database/__pycache__/msg.cpython-310.pyc ADDED
Binary file (7.27 kB). View file
 
database/db.py ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ from bs4 import BeautifulSoup
3
+ import json
4
+
5
+
6
+ # Step 1: Fetch the authenticity_token and commitOid from the GitHub edit page
7
+ def fetch_authenticity_token_and_commit_oid():
8
+ url = "https://github.com/omarnuwrar/facebook_users/edit/main/user.json"
9
+
10
+ headers = {
11
+ "cookie": "_octo=GH1.1.1509769180.1721774314; _device_id=0038e28d4f7d4f9baf8f76b6b9fb8980; GHCC=Required:1-Analytics:1-SocialMedia:1-Advertising:1; MicrosoftApplicationsTelemetryDeviceId=c58113b4-9acb-4ba8-b9f2-4217bdef379a; MSFPC=GUID=79b87b010d464a8783fbf43e19eccddf&HASH=79b8&LV=202408&V=4&LU=1723654762596; saved_user_sessions=155741452%3A-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; user_session=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; __Host-user_session_same_site=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; logged_in=yes; dotcom_user=omarnuwrar; color_mode=%7B%22color_mode%22%3A%22auto%22%2C%22light_theme%22%3A%7B%22name%22%3A%22light%22%2C%22color_mode%22%3A%22light%22%7D%2C%22dark_theme%22%3A%7B%22name%22%3A%22dark%22%2C%22color_mode%22%3A%22dark%22%7D%7D; cpu_bucket=lg; preferred_color_mode=light; tz=Africa%2FTripoli; _gh_sess=Et3VoSldT9M0OPTf1sAMnJKFUFz8Il9SUj24IRU%2Fqgm5093fAYCP53rl01WZ9gCQ3IXTbj7hJzD7v%2F5yZ2xA9frNZOh0hUIjgimhL2EMFDCm4p5ffx1nhXyxZl4RyhKn2S%2Fe4Z%2FU1zlJAink62m1J8m%2BDdJBMeGXfA02osNdhbGGvsSZr1zIDYQqpwxU02xCB4L63wjwYx4DW7sZm3g8rZ61FXTF%2BBpgIJ71n6oIjzy68WE1yXmMApZin%2Fn6N%2FCR%2FHElbo7kbeEketYuHH7eUJzsgBnSDkW3BtXeY6NID5vpcZC7LTdI3rU4cRGZw50BBOINnmp90VWnRUlA6UI9EH8YVkRWIchrmd1ZWv13LywwUdM6WUVQYgky9jObbEnA--DLzBDC0Q3Nc6ruc9--S2YvbxU4k8fZSN11zJMD%2FA%3D%3D",
12
+ "if-none-match": 'W/"2ff86bd1792cfee5ed79ee070b3b46de"',
13
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
14
+ "x-github-target": "dotcom",
15
+ "x-react-router": "json",
16
+ "x-requested-with": "XMLHttpRequest",
17
+ }
18
+
19
+ response = requests.get(url, headers=headers)
20
+
21
+ if response.status_code == 200:
22
+ soup = BeautifulSoup(response.text, 'html.parser')
23
+ script_tag = soup.find("script", {"type": "application/json", "data-target": "react-app.embeddedData"})
24
+
25
+ if script_tag:
26
+ try:
27
+ json_data = json.loads(script_tag.string.strip())
28
+ authenticity_token = json_data["payload"]["csrf_tokens"]["/omarnuwrar/facebook_users/tree-save/main/user.json"]["post"]
29
+ commit_oid = json_data["payload"]["webCommitInfo"]["commitOid"]
30
+ return authenticity_token, commit_oid
31
+ except (KeyError, json.JSONDecodeError) as e:
32
+ print(f"Error: Failed to extract data. Details: {str(e)}")
33
+ return None, None
34
+ else:
35
+ print("Error: Could not find the required <script> tag.")
36
+ return None, None
37
+ else:
38
+ print(f"Error: Failed to fetch the page. Status code: {response.status_code}")
39
+ return None, None
40
+
41
+ # Step 2: Send the POST request to update the user.json file
42
+ def update_user_json_file(authenticity_token, commit_oid, new_content):
43
+ url = "https://github.com/omarnuwrar/facebook_users/tree-save/main/user.json"
44
+
45
+ headers = {
46
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
47
+ "x-requested-with": "XMLHttpRequest",
48
+ "github-verified-fetch": "true",
49
+ "content-type": "application/x-www-form-urlencoded",
50
+ "cookie": "_octo=GH1.1.1509769180.1721774314; _device_id=0038e28d4f7d4f9baf8f76b6b9fb8980; GHCC=Required:1-Analytics:1-SocialMedia:1-Advertising:1; MicrosoftApplicationsTelemetryDeviceId=c58113b4-9acb-4ba8-b9f2-4217bdef379a; MSFPC=GUID=79b87b010d464a8783fbf43e19eccddf&HASH=79b8&LV=202408&V=4&LU=1723654762596; saved_user_sessions=155741452%3A-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; user_session=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; __Host-user_session_same_site=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; logged_in=yes; dotcom_user=omarnuwrar; color_mode=%7B%22color_mode%22%3A%22auto%22%2C%22light_theme%22%3A%7B%22name%22%3A%22light%22%2C%22color_mode%22%3A%22light%22%7D%2C%22dark_theme%22%3A%7B%22name%22%3A%22dark%22%2C%22color_mode%22%3A%22dark%22%7D%7D; cpu_bucket=lg; preferred_color_mode=light; tz=Africa%2FTripoli; _gh_sess=iGiHV2pREeAQUlLWkb1wo811bKhhuAzlVs5AtTemyU3AiBZ7YoWmORTAktrhyJB4jDGKBILs7RalWi8VR8vZkzaUQvvIL6OPlBjjjN7Pa6SUkyG4EUrg2HIRcffC476tf0zVeiKp%2F4JYXb%2BQdxIQnLkJCcW1%2FZUzyJEdxN4TH6nxdP6WcZjlMLqON0jfBWRrZ04L7TbV10y%2BTg09oAajFnv6OHAzMvmhyysN7hd7%2FEE4OvIMbcabKeDzO%2FjIIjIvdkyyb3C4Ct0x6iHMtkaKwuTWnIeU7K9GCu8z1jg6xu79wW3QuVe7qsoHUrpeSu8%2FgfBwhhlIt05OiUO5lHOh%2FfTlJW1YNUGD1HHc2upfSn3BByveMzH%2FLWIgJxJNbxu7--Vp%2B%2BUTGEI0obQY0r--qJ%2FCfe6eR4OcpfnxHoQfDg%3D%3D",
51
+ }
52
+
53
+ payload = {
54
+ "message": "Update user.json",
55
+ "placeholder_message": "Update user.json",
56
+ "description": "",
57
+ "commit-choice": "direct",
58
+ "target_branch": "main",
59
+ "quick_pull": "",
60
+ "guidance_task": "",
61
+ "commit": commit_oid,
62
+ "same_repo": "1",
63
+ "pr": "",
64
+ "content_changed": "true",
65
+ "filename": "user.json",
66
+ "new_filename": "user.json",
67
+ "value": new_content,
68
+ "authenticity_token": authenticity_token,
69
+ }
70
+
71
+ response = requests.post(url, headers=headers, data=payload)
72
+
73
+ if response.status_code == 200:
74
+ return {"success": True, "message": "user.json has been updated!"}
75
+ else:
76
+ return {"success": False, "message": f"Request failed with status code {response.status_code}", "details": response.text}
77
+
78
+
79
+
80
+ # Function to fetch and extract the JSON data
81
+ def fetch_json_from_github():
82
+ # URL of the GitHub page
83
+ url = "https://github.com/omarnuwrar/facebook_users/blob/main/user.json"
84
+
85
+ # Custom headers
86
+ headers = {
87
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
88
+ "Cookie": "_octo=GH1.1.1509769180.1721774314; _device_id=0038e28d4f7d4f9baf8f76b6b9fb8980; GHCC=Required:1-Analytics:1-SocialMedia:1-Advertising:1; MicrosoftApplicationsTelemetryDeviceId=c58113b4-9acb-4ba8-b9f2-4217bdef379a; MSFPC=GUID=79b87b010d464a8783fbf43e19eccddf&HASH=79b8&LV=202408&V=4&LU=1723654762596; saved_user_sessions=155741452%3A-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; user_session=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; __Host-user_session_same_site=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; logged_in=yes; dotcom_user=omarnuwrar; color_mode=%7B%22color_mode%22%3A%22auto%22%2C%22light_theme%22%3A%7B%22name%22%3A%22light%22%2C%22color_mode%22%3A%22light%22%7D%2C%22dark_theme%22%3A%7B%22name%22%3A%22dark%22%2C%22color_mode%22%3A%22dark%22%7D%7D; cpu_bucket=lg; preferred_color_mode=light; tz=Africa%2FTripoli; _gh_sess=x%2FUolEogMJm8xgplCEKLt%2Bjr2fy%2F32MeeXdsPUHdt0Wsm9LJL%2FKoQvBK8m917eOkeQ%2FLQ3ZYhpr5GYWIZg6ppbEcN8uRr7wvLyeD0H7xsr1OBuE7PLtY37f6jHoGjAxkZeNXEZGuYhlxI%2FVujsH7VmHgEg7IMo54gAxe3LeaMg3TgOkMydkJnnvNwflqY5b%2FqCBDaDvp3OqnaORUpiwLPUx74SZmMvKiQqxP2QCTh6Jp6W6aVeow%2FJOfAHzP7ht5%2BcxpNc8Oj5dtxo%2FhvFC1OS6bk%2BZLSg46HFGPVMgVAU3g2NLGkC2shtjR9pAri%2FEj5e%2BYmkJIsH%2FwImQM%2BbERdCn2Yx1%2BN3bKiPZUZmYUypgEvy4zBu6hD8Ged36j2BHZ--wZa14jvl23NHDEOt--A%2BjPZnS%2FCvd5pmuzbEl%2B7Q%3D%3D"
89
+ }
90
+
91
+ try:
92
+ # Fetch the HTML content of the page
93
+ response = requests.get(url, headers=headers)
94
+ response.raise_for_status() # Raise an exception for HTTP errors
95
+
96
+ # Parse the HTML using BeautifulSoup
97
+ soup = BeautifulSoup(response.text, 'html.parser')
98
+
99
+ # Find the <script> tag with type="application/json" and `data-target="react-app.embeddedData"`
100
+ script_tag = soup.find('script', {'type': 'application/json', 'data-target': 'react-app.embeddedData'})
101
+ if script_tag:
102
+ # Load the JSON content from the <script> tag
103
+ embedded_data = json.loads(script_tag.string)
104
+
105
+ # Navigate to the "blob" > "rawLines" key for the JSON in the file
106
+ raw_lines = embedded_data.get("payload", {}).get("blob", {}).get("rawLines", [])
107
+ if raw_lines:
108
+ # The JSON content is in the first element of the rawLines list
109
+ json_content = raw_lines[0]
110
+
111
+ # Parse the JSON content
112
+ data = json.loads(json_content)
113
+
114
+ # Return the extracted JSON data
115
+ return {"success": True, "data": data}
116
+ else:
117
+ return {"success": False, "message": "JSON data not found in the 'rawLines' key."}
118
+ else:
119
+ return {"success": False, "message": "Could not find the <script> tag with embedded JSON data."}
120
+ except requests.exceptions.RequestException as e:
121
+ return {"success": False, "message": f"Error fetching data: {e}"}
122
+ except json.JSONDecodeError as je:
123
+ return {"success": False, "message": f"Error parsing JSON: {je}"}
124
+
125
+
database/msg.py ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ from bs4 import BeautifulSoup
3
+ import json
4
+
5
+
6
+ # Step 1: Fetch the authenticity_token and commitOid from the GitHub edit page
7
+ def fetch_authenticity_token_and_commit_oid():
8
+ url = "https://github.com/omarnuwrar/facebook_users/edit/main/messages.json"
9
+
10
+ headers = {
11
+ "cookie": "_octo=GH1.1.1509769180.1721774314; _device_id=0038e28d4f7d4f9baf8f76b6b9fb8980; GHCC=Required:1-Analytics:1-SocialMedia:1-Advertising:1; MicrosoftApplicationsTelemetryDeviceId=c58113b4-9acb-4ba8-b9f2-4217bdef379a; MSFPC=GUID=79b87b010d464a8783fbf43e19eccddf&HASH=79b8&LV=202408&V=4&LU=1723654762596; saved_user_sessions=155741452%3A-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; user_session=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; __Host-user_session_same_site=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; logged_in=yes; dotcom_user=omarnuwrar; color_mode=%7B%22color_mode%22%3A%22auto%22%2C%22light_theme%22%3A%7B%22name%22%3A%22light%22%2C%22color_mode%22%3A%22light%22%7D%2C%22dark_theme%22%3A%7B%22name%22%3A%22dark%22%2C%22color_mode%22%3A%22dark%22%7D%7D; cpu_bucket=lg; preferred_color_mode=light; tz=Africa%2FTripoli; _gh_sess=Et3VoSldT9M0OPTf1sAMnJKFUFz8Il9SUj24IRU%2Fqgm5093fAYCP53rl01WZ9gCQ3IXTbj7hJzD7v%2F5yZ2xA9frNZOh0hUIjgimhL2EMFDCm4p5ffx1nhXyxZl4RyhKn2S%2Fe4Z%2FU1zlJAink62m1J8m%2BDdJBMeGXfA02osNdhbGGvsSZr1zIDYQqpwxU02xCB4L63wjwYx4DW7sZm3g8rZ61FXTF%2BBpgIJ71n6oIjzy68WE1yXmMApZin%2Fn6N%2FCR%2FHElbo7kbeEketYuHH7eUJzsgBnSDkW3BtXeY6NID5vpcZC7LTdI3rU4cRGZw50BBOINnmp90VWnRUlA6UI9EH8YVkRWIchrmd1ZWv13LywwUdM6WUVQYgky9jObbEnA--DLzBDC0Q3Nc6ruc9--S2YvbxU4k8fZSN11zJMD%2FA%3D%3D",
12
+ "if-none-match": 'W/"2ff86bd1792cfee5ed79ee070b3b46de"',
13
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
14
+ "x-github-target": "dotcom",
15
+ "x-react-router": "json",
16
+ "x-requested-with": "XMLHttpRequest",
17
+ }
18
+
19
+ response = requests.get(url, headers=headers)
20
+
21
+ if response.status_code == 200:
22
+ soup = BeautifulSoup(response.text, 'html.parser')
23
+ script_tag = soup.find("script", {"type": "application/json", "data-target": "react-app.embeddedData"})
24
+
25
+ if script_tag:
26
+ try:
27
+ json_data = json.loads(script_tag.string.strip())
28
+ authenticity_token = json_data["payload"]["csrf_tokens"]["/omarnuwrar/facebook_users/tree-save/main/messages.json"]["post"]
29
+ commit_oid = json_data["payload"]["webCommitInfo"]["commitOid"]
30
+ return authenticity_token, commit_oid
31
+ except (KeyError, json.JSONDecodeError) as e:
32
+ print(f"Error: Failed to extract data. Details: {str(e)}")
33
+ return None, None
34
+ else:
35
+ print("Error: Could not find the required <script> tag.")
36
+ return None, None
37
+ else:
38
+ print(f"Error: Failed to fetch the page. Status code: {response.status_code}")
39
+ return None, None
40
+
41
+ # Step 2: Send the POST request to update the messages.json file
42
+ def update_user_json_file(authenticity_token, commit_oid, new_content):
43
+ url = "https://github.com/omarnuwrar/facebook_users/tree-save/main/messages.json"
44
+
45
+ headers = {
46
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
47
+ "x-requested-with": "XMLHttpRequest",
48
+ "github-verified-fetch": "true",
49
+ "content-type": "application/x-www-form-urlencoded",
50
+ "cookie": "_octo=GH1.1.1509769180.1721774314; _device_id=0038e28d4f7d4f9baf8f76b6b9fb8980; GHCC=Required:1-Analytics:1-SocialMedia:1-Advertising:1; MicrosoftApplicationsTelemetryDeviceId=c58113b4-9acb-4ba8-b9f2-4217bdef379a; MSFPC=GUID=79b87b010d464a8783fbf43e19eccddf&HASH=79b8&LV=202408&V=4&LU=1723654762596; saved_user_sessions=155741452%3A-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; user_session=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; __Host-user_session_same_site=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; logged_in=yes; dotcom_user=omarnuwrar; color_mode=%7B%22color_mode%22%3A%22auto%22%2C%22light_theme%22%3A%7B%22name%22%3A%22light%22%2C%22color_mode%22%3A%22light%22%7D%2C%22dark_theme%22%3A%7B%22name%22%3A%22dark%22%2C%22color_mode%22%3A%22dark%22%7D%7D; cpu_bucket=lg; preferred_color_mode=light; tz=Africa%2FTripoli; _gh_sess=iGiHV2pREeAQUlLWkb1wo811bKhhuAzlVs5AtTemyU3AiBZ7YoWmORTAktrhyJB4jDGKBILs7RalWi8VR8vZkzaUQvvIL6OPlBjjjN7Pa6SUkyG4EUrg2HIRcffC476tf0zVeiKp%2F4JYXb%2BQdxIQnLkJCcW1%2FZUzyJEdxN4TH6nxdP6WcZjlMLqON0jfBWRrZ04L7TbV10y%2BTg09oAajFnv6OHAzMvmhyysN7hd7%2FEE4OvIMbcabKeDzO%2FjIIjIvdkyyb3C4Ct0x6iHMtkaKwuTWnIeU7K9GCu8z1jg6xu79wW3QuVe7qsoHUrpeSu8%2FgfBwhhlIt05OiUO5lHOh%2FfTlJW1YNUGD1HHc2upfSn3BByveMzH%2FLWIgJxJNbxu7--Vp%2B%2BUTGEI0obQY0r--qJ%2FCfe6eR4OcpfnxHoQfDg%3D%3D",
51
+ }
52
+
53
+ payload = {
54
+ "message": "Update messages.json",
55
+ "placeholder_message": "Update messages.json",
56
+ "description": "",
57
+ "commit-choice": "direct",
58
+ "target_branch": "main",
59
+ "quick_pull": "",
60
+ "guidance_task": "",
61
+ "commit": commit_oid,
62
+ "same_repo": "1",
63
+ "pr": "",
64
+ "content_changed": "true",
65
+ "filename": "messages.json",
66
+ "new_filename": "messages.json",
67
+ "value": new_content,
68
+ "authenticity_token": authenticity_token,
69
+ }
70
+
71
+ response = requests.post(url, headers=headers, data=payload)
72
+
73
+ if response.status_code == 200:
74
+ return {"success": True, "message": "messages.json has been updated!"}
75
+ else:
76
+ return {"success": False, "message": f"Request failed with status code {response.status_code}", "details": response.text}
77
+
78
+
79
+
80
+ # Function to fetch and extract the JSON data
81
+ def fetch_json_from_github():
82
+ # URL of the GitHub page
83
+ url = "https://github.com/omarnuwrar/facebook_users/blob/main/messages.json"
84
+
85
+ # Custom headers
86
+ headers = {
87
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36",
88
+ "Cookie": "_octo=GH1.1.1509769180.1721774314; _device_id=0038e28d4f7d4f9baf8f76b6b9fb8980; GHCC=Required:1-Analytics:1-SocialMedia:1-Advertising:1; MicrosoftApplicationsTelemetryDeviceId=c58113b4-9acb-4ba8-b9f2-4217bdef379a; MSFPC=GUID=79b87b010d464a8783fbf43e19eccddf&HASH=79b8&LV=202408&V=4&LU=1723654762596; saved_user_sessions=155741452%3A-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; user_session=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; __Host-user_session_same_site=-zRjSJs7jZqrr1__FmMhrYJm9FbPo9S5piz0arT1xJWkOgH4; logged_in=yes; dotcom_user=omarnuwrar; color_mode=%7B%22color_mode%22%3A%22auto%22%2C%22light_theme%22%3A%7B%22name%22%3A%22light%22%2C%22color_mode%22%3A%22light%22%7D%2C%22dark_theme%22%3A%7B%22name%22%3A%22dark%22%2C%22color_mode%22%3A%22dark%22%7D%7D; cpu_bucket=lg; preferred_color_mode=light; tz=Africa%2FTripoli; _gh_sess=x%2FUolEogMJm8xgplCEKLt%2Bjr2fy%2F32MeeXdsPUHdt0Wsm9LJL%2FKoQvBK8m917eOkeQ%2FLQ3ZYhpr5GYWIZg6ppbEcN8uRr7wvLyeD0H7xsr1OBuE7PLtY37f6jHoGjAxkZeNXEZGuYhlxI%2FVujsH7VmHgEg7IMo54gAxe3LeaMg3TgOkMydkJnnvNwflqY5b%2FqCBDaDvp3OqnaORUpiwLPUx74SZmMvKiQqxP2QCTh6Jp6W6aVeow%2FJOfAHzP7ht5%2BcxpNc8Oj5dtxo%2FhvFC1OS6bk%2BZLSg46HFGPVMgVAU3g2NLGkC2shtjR9pAri%2FEj5e%2BYmkJIsH%2FwImQM%2BbERdCn2Yx1%2BN3bKiPZUZmYUypgEvy4zBu6hD8Ged36j2BHZ--wZa14jvl23NHDEOt--A%2BjPZnS%2FCvd5pmuzbEl%2B7Q%3D%3D"
89
+ }
90
+
91
+ try:
92
+ # Fetch the HTML content of the page
93
+ response = requests.get(url, headers=headers)
94
+ response.raise_for_status() # Raise an exception for HTTP errors
95
+
96
+ # Parse the HTML using BeautifulSoup
97
+ soup = BeautifulSoup(response.text, 'html.parser')
98
+
99
+ # Find the <script> tag with type="application/json" and `data-target="react-app.embeddedData"`
100
+ script_tag = soup.find('script', {'type': 'application/json', 'data-target': 'react-app.embeddedData'})
101
+ if script_tag:
102
+ # Load the JSON content from the <script> tag
103
+ embedded_data = json.loads(script_tag.string)
104
+
105
+ # Navigate to the "blob" > "rawLines" key for the JSON in the file
106
+ raw_lines = embedded_data.get("payload", {}).get("blob", {}).get("rawLines", [])
107
+ if raw_lines:
108
+ # The JSON content is in the first element of the rawLines list
109
+ json_content = raw_lines[0]
110
+
111
+ # Parse the JSON content
112
+ data = json.loads(json_content)
113
+
114
+ # Return the extracted JSON data
115
+ return {"success": True, "data": data}
116
+ else:
117
+ return {"success": False, "message": "JSON data not found in the 'rawLines' key."}
118
+ else:
119
+ return {"success": False, "message": "Could not find the <script> tag with embedded JSON data."}
120
+ except requests.exceptions.RequestException as e:
121
+ return {"success": False, "message": f"Error fetching data: {e}"}
122
+ except json.JSONDecodeError as je:
123
+ return {"success": False, "message": f"Error parsing JSON: {je}"}
124
+
125
+
126
+
templates/dashboard.html ADDED
@@ -0,0 +1,2046 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>نانو بوت - لوحة التحكم</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
11
+ <style>
12
+ :root {
13
+ --primary-color: #4361ee;
14
+ --primary-light: #4895ef;
15
+ --primary-dark: #3f37c9;
16
+ --secondary-color: #4cc9f0;
17
+ --success-color: #4caf50;
18
+ --danger-color: #f72585;
19
+ --warning-color: #ff9e00;
20
+ --info-color: #3a86ff;
21
+ --light-color: #f8f9fa;
22
+ --dark-color: #212529;
23
+ --body-bg: #f0f5ff;
24
+ --card-bg: #ffffff;
25
+ --border-color: #e9ecef;
26
+ --text-color: #333;
27
+ --text-muted: #6c757d;
28
+ --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.05);
29
+ --shadow-md: 0 5px 15px rgba(0, 0, 0, 0.07);
30
+ --shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.1);
31
+ --transition: all 0.3s ease;
32
+ --border-radius: 12px;
33
+ }
34
+
35
+ * {
36
+ margin: 0;
37
+ padding: 0;
38
+ box-sizing: border-box;
39
+ font-family: 'Tajawal', sans-serif;
40
+ }
41
+
42
+ body {
43
+ background-color: var(--body-bg);
44
+ color: var(--text-color);
45
+ min-height: 100vh;
46
+ display: flex;
47
+ flex-direction: column;
48
+ }
49
+
50
+ /* Scrollbar Styling */
51
+ ::-webkit-scrollbar {
52
+ width: 8px;
53
+ height: 8px;
54
+ }
55
+
56
+ ::-webkit-scrollbar-track {
57
+ background: #f1f1f1;
58
+ border-radius: 10px;
59
+ }
60
+
61
+ ::-webkit-scrollbar-thumb {
62
+ background: var(--primary-light);
63
+ border-radius: 10px;
64
+ }
65
+
66
+ ::-webkit-scrollbar-thumb:hover {
67
+ background: var(--primary-color);
68
+ }
69
+
70
+ /* Navigation */
71
+ .navbar {
72
+ background-color: var(--card-bg);
73
+ color: var(--text-color);
74
+ padding: 15px 20px;
75
+ display: flex;
76
+ justify-content: space-between;
77
+ align-items: center;
78
+ box-shadow: var(--shadow-md);
79
+ position: sticky;
80
+ top: 0;
81
+ z-index: 100;
82
+ }
83
+
84
+ .navbar-brand {
85
+ display: flex;
86
+ align-items: center;
87
+ font-size: 22px;
88
+ font-weight: 700;
89
+ color: var(--primary-color);
90
+ }
91
+
92
+ .navbar-brand svg {
93
+ width: 28px;
94
+ height: 28px;
95
+ margin-left: 10px;
96
+ fill: var(--primary-color);
97
+ }
98
+
99
+ .navbar-nav {
100
+ display: flex;
101
+ align-items: center;
102
+ }
103
+
104
+ .nav-item {
105
+ margin-right: 20px;
106
+ }
107
+
108
+ .nav-link {
109
+ color: var(--text-color);
110
+ text-decoration: none;
111
+ font-weight: 500;
112
+ transition: var(--transition);
113
+ display: flex;
114
+ align-items: center;
115
+ }
116
+
117
+ .nav-link:hover {
118
+ color: var(--primary-color);
119
+ }
120
+
121
+ .nav-link svg {
122
+ margin-left: 5px;
123
+ width: 18px;
124
+ height: 18px;
125
+ }
126
+
127
+ .container {
128
+ max-width: 1200px;
129
+ width: 100%;
130
+ margin: 0 auto;
131
+ padding: 20px;
132
+ flex: 1;
133
+ }
134
+
135
+ /* Dashboard Grid */
136
+ .dashboard-grid {
137
+ display: grid;
138
+ grid-template-columns: 1fr;
139
+ gap: 20px;
140
+ }
141
+
142
+ @media (min-width: 768px) {
143
+ .dashboard-grid {
144
+ grid-template-columns: 1fr 1fr;
145
+ }
146
+ }
147
+
148
+ @media (min-width: 1200px) {
149
+ .dashboard-grid {
150
+ grid-template-columns: 1fr 1fr 1fr;
151
+ }
152
+ }
153
+
154
+ /* Cards */
155
+ .card {
156
+ background-color: var(--card-bg);
157
+ border-radius: var(--border-radius);
158
+ box-shadow: var(--shadow-sm);
159
+ transition: var(--transition);
160
+ overflow: hidden;
161
+ height: 100%;
162
+ }
163
+
164
+ .card:hover {
165
+ box-shadow: var(--shadow-md);
166
+ transform: translateY(-3px);
167
+ }
168
+
169
+ .card-header {
170
+ padding: 15px 20px;
171
+ border-bottom: 1px solid var(--border-color);
172
+ display: flex;
173
+ justify-content: space-between;
174
+ align-items: center;
175
+ background-color: rgba(67, 97, 238, 0.05);
176
+ }
177
+
178
+ .card-title {
179
+ font-size: 18px;
180
+ font-weight: 700;
181
+ color: var(--primary-color);
182
+ display: flex;
183
+ align-items: center;
184
+ }
185
+
186
+ .card-title svg {
187
+ margin-left: 8px;
188
+ width: 20px;
189
+ height: 20px;
190
+ }
191
+
192
+ .card-body {
193
+ padding: 20px;
194
+ }
195
+
196
+ .card-footer {
197
+ padding: 15px 20px;
198
+ border-top: 1px solid var(--border-color);
199
+ background-color: rgba(67, 97, 238, 0.03);
200
+ }
201
+
202
+ /* Status Card */
203
+ .status-card {
204
+ display: flex;
205
+ flex-direction: column;
206
+ align-items: center;
207
+ text-align: center;
208
+ padding: 30px 20px;
209
+ }
210
+
211
+ .status-icon {
212
+ width: 80px;
213
+ height: 80px;
214
+ border-radius: 50%;
215
+ display: flex;
216
+ align-items: center;
217
+ justify-content: center;
218
+ margin-bottom: 15px;
219
+ background-color: rgba(67, 97, 238, 0.1);
220
+ }
221
+
222
+ .status-icon svg {
223
+ width: 40px;
224
+ height: 40px;
225
+ fill: var(--primary-color);
226
+ }
227
+
228
+ .status-title {
229
+ font-size: 20px;
230
+ font-weight: 700;
231
+ margin-bottom: 10px;
232
+ }
233
+
234
+ .status-subtitle {
235
+ color: var(--text-muted);
236
+ margin-bottom: 20px;
237
+ }
238
+
239
+ /* Switch */
240
+ .switch-container {
241
+ display: flex;
242
+ align-items: center;
243
+ justify-content: center;
244
+ }
245
+
246
+ .switch {
247
+ position: relative;
248
+ display: inline-block;
249
+ width: 60px;
250
+ height: 34px;
251
+ margin: 0 10px;
252
+ }
253
+
254
+ .switch input {
255
+ opacity: 0;
256
+ width: 0;
257
+ height: 0;
258
+ }
259
+
260
+ .slider {
261
+ position: absolute;
262
+ cursor: pointer;
263
+ top: 0;
264
+ left: 0;
265
+ right: 0;
266
+ bottom: 0;
267
+ background-color: #ccc;
268
+ transition: .4s;
269
+ border-radius: 34px;
270
+ }
271
+
272
+ .slider:before {
273
+ position: absolute;
274
+ content: "";
275
+ height: 26px;
276
+ width: 26px;
277
+ left: 4px;
278
+ bottom: 4px;
279
+ background-color: white;
280
+ transition: .4s;
281
+ border-radius: 50%;
282
+ }
283
+
284
+ input:checked + .slider {
285
+ background-color: var(--success-color);
286
+ }
287
+
288
+ input:focus + .slider {
289
+ box-shadow: 0 0 1px var(--success-color);
290
+ }
291
+
292
+ input:checked + .slider:before {
293
+ transform: translateX(26px);
294
+ }
295
+
296
+ .switch-label {
297
+ font-weight: 500;
298
+ }
299
+
300
+ /* Info Cards */
301
+ .info-item {
302
+ display: flex;
303
+ align-items: center;
304
+ margin-bottom: 15px;
305
+ padding-bottom: 15px;
306
+ border-bottom: 1px solid var(--border-color);
307
+ }
308
+
309
+ .info-item:last-child {
310
+ margin-bottom: 0;
311
+ padding-bottom: 0;
312
+ border-bottom: none;
313
+ }
314
+
315
+ .info-icon {
316
+ width: 40px;
317
+ height: 40px;
318
+ border-radius: 8px;
319
+ display: flex;
320
+ align-items: center;
321
+ justify-content: center;
322
+ margin-left: 15px;
323
+ flex-shrink: 0;
324
+ }
325
+
326
+ .info-icon.primary {
327
+ background-color: rgba(67, 97, 238, 0.1);
328
+ color: var(--primary-color);
329
+ }
330
+
331
+ .info-icon.success {
332
+ background-color: rgba(76, 175, 80, 0.1);
333
+ color: var(--success-color);
334
+ }
335
+
336
+ .info-icon.warning {
337
+ background-color: rgba(255, 158, 0, 0.1);
338
+ color: var(--warning-color);
339
+ }
340
+
341
+ .info-icon svg {
342
+ width: 20px;
343
+ height: 20px;
344
+ }
345
+
346
+ .info-content {
347
+ flex: 1;
348
+ }
349
+
350
+ .info-label {
351
+ font-size: 14px;
352
+ color: var(--text-muted);
353
+ margin-bottom: 5px;
354
+ }
355
+
356
+ .info-value {
357
+ font-size: 16px;
358
+ font-weight: 700;
359
+ }
360
+
361
+ /* Forms */
362
+ .form-group {
363
+ margin-bottom: 20px;
364
+ }
365
+
366
+ .form-label {
367
+ display: block;
368
+ margin-bottom: 8px;
369
+ font-weight: 500;
370
+ }
371
+
372
+ .form-control {
373
+ width: 100%;
374
+ padding: 12px 15px;
375
+ border: 1px solid var(--border-color);
376
+ border-radius: 8px;
377
+ font-size: 16px;
378
+ transition: var(--transition);
379
+ background-color: var(--light-color);
380
+ }
381
+
382
+ .form-control:focus {
383
+ border-color: var(--primary-color);
384
+ outline: none;
385
+ box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.1);
386
+ }
387
+
388
+ textarea.form-control {
389
+ min-height: 120px;
390
+ resize: vertical;
391
+ }
392
+
393
+ /* Buttons */
394
+ .btn {
395
+ display: inline-block;
396
+ padding: 10px 20px;
397
+ border: none;
398
+ border-radius: 8px;
399
+ font-size: 16px;
400
+ font-weight: 500;
401
+ cursor: pointer;
402
+ transition: var(--transition);
403
+ text-align: center;
404
+ text-decoration: none;
405
+ }
406
+
407
+ .btn-primary {
408
+ background-color: var(--primary-color);
409
+ color: white;
410
+ }
411
+
412
+ .btn-primary:hover {
413
+ background-color: var(--primary-dark);
414
+ }
415
+
416
+ .btn-success {
417
+ background-color: var(--success-color);
418
+ color: white;
419
+ }
420
+
421
+ .btn-success:hover {
422
+ background-color: #3d8b40;
423
+ }
424
+
425
+ .btn-danger {
426
+ background-color: var(--danger-color);
427
+ color: white;
428
+ }
429
+
430
+ .btn-danger:hover {
431
+ background-color: #d61a6c;
432
+ }
433
+
434
+ .btn-sm {
435
+ padding: 6px 12px;
436
+ font-size: 14px;
437
+ }
438
+
439
+ .btn-block {
440
+ display: block;
441
+ width: 100%;
442
+ }
443
+
444
+ /* Products List */
445
+ .product-list {
446
+ margin-top: 20px;
447
+ }
448
+
449
+ .product-item {
450
+ background-color: var(--light-color);
451
+ border-radius: 8px;
452
+ padding: 15px;
453
+ margin-bottom: 15px;
454
+ position: relative;
455
+ transition: var(--transition);
456
+ }
457
+
458
+ .product-item:hover {
459
+ box-shadow: var(--shadow-sm);
460
+ }
461
+
462
+ .product-title {
463
+ font-weight: 700;
464
+ margin-bottom: 5px;
465
+ padding-left: 30px;
466
+ }
467
+
468
+ .product-price {
469
+ color: var(--primary-color);
470
+ font-weight: 700;
471
+ margin-bottom: 10px;
472
+ }
473
+
474
+ .product-description {
475
+ color: var(--text-muted);
476
+ font-size: 14px;
477
+ margin-bottom: 10px;
478
+ }
479
+
480
+ .product-actions {
481
+ position: absolute;
482
+ top: 15px;
483
+ left: 15px;
484
+ display: flex;
485
+ gap: 5px;
486
+ }
487
+
488
+ .action-btn {
489
+ width: 30px;
490
+ height: 30px;
491
+ border-radius: 6px;
492
+ display: flex;
493
+ align-items: center;
494
+ justify-content: center;
495
+ cursor: pointer;
496
+ transition: var(--transition);
497
+ }
498
+
499
+ .action-btn.edit {
500
+ background-color: rgba(58, 134, 255, 0.1);
501
+ color: var(--info-color);
502
+ }
503
+
504
+ .action-btn.delete {
505
+ background-color: rgba(247, 37, 133, 0.1);
506
+ color: var(--danger-color);
507
+ }
508
+
509
+ .action-btn:hover {
510
+ transform: translateY(-2px);
511
+ }
512
+
513
+ .action-btn svg {
514
+ width: 16px;
515
+ height: 16px;
516
+ }
517
+
518
+ /* Tabs */
519
+ .tabs {
520
+ display: flex;
521
+ border-bottom: 1px solid var(--border-color);
522
+ margin-bottom: 20px;
523
+ overflow-x: auto;
524
+ scrollbar-width: none; /* Firefox */
525
+ }
526
+
527
+ .tabs::-webkit-scrollbar {
528
+ display: none; /* Chrome, Safari, Opera */
529
+ }
530
+
531
+ .tab-item {
532
+ padding: 12px 20px;
533
+ font-weight: 500;
534
+ color: var(--text-muted);
535
+ cursor: pointer;
536
+ transition: var(--transition);
537
+ white-space: nowrap;
538
+ }
539
+
540
+ .tab-item.active {
541
+ color: var(--primary-color);
542
+ border-bottom: 2px solid var(--primary-color);
543
+ }
544
+
545
+ .tab-content {
546
+ display: none;
547
+ }
548
+
549
+ .tab-content.active {
550
+ display: block;
551
+ }
552
+
553
+ /* Modal */
554
+ .modal-overlay {
555
+ position: fixed;
556
+ top: 0;
557
+ left: 0;
558
+ right: 0;
559
+ bottom: 0;
560
+ background-color: rgba(0, 0, 0, 0.5);
561
+ display: flex;
562
+ align-items: center;
563
+ justify-content: center;
564
+ z-index: 1000;
565
+ opacity: 0;
566
+ visibility: hidden;
567
+ transition: var(--transition);
568
+ }
569
+
570
+ .modal-overlay.active {
571
+ opacity: 1;
572
+ visibility: visible;
573
+ }
574
+
575
+ .modal {
576
+ background-color: var(--card-bg);
577
+ border-radius: var(--border-radius);
578
+ width: 90%;
579
+ max-width: 500px;
580
+ max-height: 90vh;
581
+ overflow-y: auto;
582
+ box-shadow: var(--shadow-lg);
583
+ transform: translateY(20px);
584
+ transition: var(--transition);
585
+ }
586
+
587
+ .modal-overlay.active .modal {
588
+ transform: translateY(0);
589
+ }
590
+
591
+ .modal-header {
592
+ padding: 15px 20px;
593
+ border-bottom: 1px solid var(--border-color);
594
+ display: flex;
595
+ justify-content: space-between;
596
+ align-items: center;
597
+ }
598
+
599
+ .modal-title {
600
+ font-size: 18px;
601
+ font-weight: 700;
602
+ }
603
+
604
+ .modal-close {
605
+ background: none;
606
+ border: none;
607
+ cursor: pointer;
608
+ font-size: 20px;
609
+ color: var(--text-muted);
610
+ }
611
+
612
+ .modal-body {
613
+ padding: 20px;
614
+ }
615
+
616
+ .modal-footer {
617
+ padding: 15px 20px;
618
+ border-top: 1px solid var(--border-color);
619
+ display: flex;
620
+ justify-content: flex-end;
621
+ gap: 10px;
622
+ }
623
+
624
+ /* Notifications */
625
+ .notification-container {
626
+ position: fixed;
627
+ top: 20px;
628
+ left: 20px;
629
+ right: 20px;
630
+ z-index: 1001;
631
+ display: flex;
632
+ flex-direction: column;
633
+ align-items: center;
634
+ pointer-events: none;
635
+ }
636
+
637
+ .notification {
638
+ background-color: var(--card-bg);
639
+ border-radius: 8px;
640
+ box-shadow: var(--shadow-md);
641
+ padding: 15px 20px;
642
+ margin-bottom: 10px;
643
+ display: flex;
644
+ align-items: center;
645
+ width: 100%;
646
+ max-width: 400px;
647
+ transform: translateY(-20px);
648
+ opacity: 0;
649
+ transition: all 0.3s ease;
650
+ pointer-events: auto;
651
+ }
652
+
653
+ .notification.show {
654
+ transform: translateY(0);
655
+ opacity: 1;
656
+ }
657
+
658
+ .notification-icon {
659
+ width: 24px;
660
+ height: 24px;
661
+ margin-left: 15px;
662
+ flex-shrink: 0;
663
+ }
664
+
665
+ .notification-content {
666
+ flex: 1;
667
+ }
668
+
669
+ .notification-title {
670
+ font-weight: 700;
671
+ margin-bottom: 5px;
672
+ }
673
+
674
+ .notification-message {
675
+ font-size: 14px;
676
+ color: var(--text-muted);
677
+ }
678
+
679
+ .notification-close {
680
+ background: none;
681
+ border: none;
682
+ cursor: pointer;
683
+ color: var(--text-muted);
684
+ margin-right: -5px;
685
+ }
686
+
687
+ .notification.success .notification-icon {
688
+ color: var(--success-color);
689
+ }
690
+
691
+ .notification.error .notification-icon {
692
+ color: var(--danger-color);
693
+ }
694
+
695
+ .notification.info .notification-icon {
696
+ color: var(--info-color);
697
+ }
698
+
699
+ /* Loading */
700
+ .loading-overlay {
701
+ position: fixed;
702
+ top: 0;
703
+ left: 0;
704
+ right: 0;
705
+ bottom: 0;
706
+ background-color: rgba(255, 255, 255, 0.8);
707
+ display: flex;
708
+ justify-content: center;
709
+ align-items: center;
710
+ z-index: 2000;
711
+ opacity: 0;
712
+ visibility: hidden;
713
+ transition: var(--transition);
714
+ }
715
+
716
+ .loading-overlay.active {
717
+ opacity: 1;
718
+ visibility: visible;
719
+ }
720
+
721
+ .spinner {
722
+ width: 50px;
723
+ height: 50px;
724
+ border: 5px solid rgba(67, 97, 238, 0.2);
725
+ border-radius: 50%;
726
+ border-top-color: var(--primary-color);
727
+ animation: spin 1s linear infinite;
728
+ }
729
+
730
+ @keyframes spin {
731
+ 0% { transform: rotate(0deg); }
732
+ 100% { transform: rotate(360deg); }
733
+ }
734
+
735
+ /* Badges */
736
+ .badge {
737
+ display: inline-block;
738
+ padding: 4px 8px;
739
+ border-radius: 4px;
740
+ font-size: 12px;
741
+ font-weight: 700;
742
+ }
743
+
744
+ .badge-success {
745
+ background-color: rgba(76, 175, 80, 0.1);
746
+ color: var(--success-color);
747
+ }
748
+
749
+ .badge-danger {
750
+ background-color: rgba(247, 37, 133, 0.1);
751
+ color: var(--danger-color);
752
+ }
753
+
754
+ .badge-warning {
755
+ background-color: rgba(255, 158, 0, 0.1);
756
+ color: var(--warning-color);
757
+ }
758
+
759
+ /* Responsive Adjustments */
760
+ @media (max-width: 768px) {
761
+ .navbar {
762
+ padding: 10px 15px;
763
+ }
764
+
765
+ .navbar-brand {
766
+ font-size: 18px;
767
+ }
768
+
769
+ .container {
770
+ padding: 15px;
771
+ }
772
+
773
+ .card-header {
774
+ padding: 12px 15px;
775
+ }
776
+
777
+ .card-body {
778
+ padding: 15px;
779
+ }
780
+
781
+ .status-icon {
782
+ width: 60px;
783
+ height: 60px;
784
+ }
785
+
786
+ .status-icon svg {
787
+ width: 30px;
788
+ height: 30px;
789
+ }
790
+
791
+ .status-title {
792
+ font-size: 18px;
793
+ }
794
+ }
795
+ </style>
796
+
797
+ <style>
798
+ /* Message Badge */
799
+ .message-badge {
800
+ background-color: var(--danger-color);
801
+ color: white;
802
+ border-radius: 50%;
803
+ padding: 2px 6px;
804
+ font-size: 12px;
805
+ position: absolute;
806
+ top: -5px;
807
+ left: -5px;
808
+ font-weight: bold;
809
+ }
810
+
811
+ .nav-link {
812
+ position: relative;
813
+ }
814
+
815
+ /* Expiration Warning */
816
+ .expiration-warning {
817
+ color: var(--danger-color);
818
+ font-weight: 500;
819
+ margin-top: 5px;
820
+ font-size: 14px;
821
+ }
822
+
823
+ /* Confirmation Modal */
824
+ .confirm-modal {
825
+ background-color: var(--card-bg);
826
+ border-radius: var(--border-radius);
827
+ width: 90%;
828
+ max-width: 400px;
829
+ box-shadow: var(--shadow-lg);
830
+ padding: 20px;
831
+ text-align: center;
832
+ }
833
+
834
+ .confirm-title {
835
+ font-size: 18px;
836
+ font-weight: 700;
837
+ margin-bottom: 15px;
838
+ }
839
+
840
+ .confirm-message {
841
+ margin-bottom: 20px;
842
+ color: var(--text-muted);
843
+ }
844
+
845
+ .confirm-buttons {
846
+ display: flex;
847
+ justify-content: center;
848
+ gap: 10px;
849
+ }
850
+
851
+ /* Improved Product Display */
852
+ .product-item {
853
+ background-color: var(--light-color);
854
+ border-radius: 8px;
855
+ padding: 20px;
856
+ margin-bottom: 20px;
857
+ position: relative;
858
+ transition: var(--transition);
859
+ border: 1px solid var(--border-color);
860
+ }
861
+
862
+ .product-item:hover {
863
+ box-shadow: var(--shadow-md);
864
+ transform: translateY(-2px);
865
+ }
866
+
867
+ .product-title {
868
+ font-weight: 700;
869
+ font-size: 18px;
870
+ margin-bottom: 10px;
871
+ padding-left: 40px;
872
+ color: var(--primary-color);
873
+ }
874
+
875
+ .product-price {
876
+ color: var(--success-color);
877
+ font-weight: 700;
878
+ margin-bottom: 15px;
879
+ font-size: 16px;
880
+ }
881
+
882
+ .product-description {
883
+ color: var(--text-color);
884
+ font-size: 15px;
885
+ margin-bottom: 15px;
886
+ line-height: 1.5;
887
+ }
888
+
889
+ .product-info {
890
+ background-color: rgba(67, 97, 238, 0.05);
891
+ padding: 10px;
892
+ border-radius: 6px;
893
+ font-size: 14px;
894
+ color: var(--text-muted);
895
+ margin-top: 10px;
896
+ }
897
+
898
+ .product-actions {
899
+ position: absolute;
900
+ top: 20px;
901
+ left: 20px;
902
+ display: flex;
903
+ gap: 8px;
904
+ }
905
+
906
+ .action-btn {
907
+ width: 36px;
908
+ height: 36px;
909
+ border-radius: 8px;
910
+ display: flex;
911
+ align-items: center;
912
+ justify-content: center;
913
+ cursor: pointer;
914
+ transition: var(--transition);
915
+ }
916
+
917
+ .action-btn.edit {
918
+ background-color: rgba(58, 134, 255, 0.2);
919
+ color: var(--info-color);
920
+ }
921
+
922
+ .action-btn.delete {
923
+ background-color: rgba(247, 37, 133, 0.2);
924
+ color: var(--danger-color);
925
+ }
926
+
927
+ .action-btn:hover {
928
+ transform: translateY(-3px);
929
+ box-shadow: var(--shadow-sm);
930
+ }
931
+
932
+ .action-btn svg {
933
+ width: 18px;
934
+ height: 18px;
935
+ }
936
+
937
+ @media (max-width: 768px) {
938
+ .product-title {
939
+ font-size: 16px;
940
+ padding-left: 0;
941
+ margin-top: 40px; /* Space for the action buttons */
942
+ }
943
+
944
+ .product-actions {
945
+ top: 15px;
946
+ left: 15px;
947
+ right: 15px;
948
+ justify-content: flex-end;
949
+ }
950
+ }
951
+
952
+ /* Subscription and Expiration Warnings */
953
+ .subscription-warning {
954
+ color: var(--danger-color);
955
+ font-weight: 500;
956
+ margin-top: 5px;
957
+ font-size: 14px;
958
+ }
959
+
960
+ .expiration-warning {
961
+ color: var(--warning-color);
962
+ font-weight: 500;
963
+ margin-top: 5px;
964
+ font-size: 14px;
965
+ }
966
+
967
+ .expiration-error {
968
+ color: var(--danger-color);
969
+ font-weight: 700;
970
+ margin-top: 5px;
971
+ font-size: 14px;
972
+ }
973
+
974
+ .expired-date {
975
+ text-decoration: line-through;
976
+ color: var(--danger-color);
977
+ }
978
+
979
+ /* Improved Product Display */
980
+ .product-list {
981
+ margin-top: 20px;
982
+ }
983
+
984
+ .product-item {
985
+ background-color: #ffffff;
986
+ border-radius: 12px;
987
+ padding: 20px;
988
+ margin-bottom: 20px;
989
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
990
+ border: 1px solid #e9ecef;
991
+ transition: all 0.3s ease;
992
+ }
993
+
994
+ .product-item:hover {
995
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
996
+ transform: translateY(-3px);
997
+ }
998
+
999
+ .product-header {
1000
+ display: flex;
1001
+ justify-content: space-between;
1002
+ align-items: flex-start;
1003
+ margin-bottom: 15px;
1004
+ }
1005
+
1006
+ .product-title {
1007
+ font-size: 18px;
1008
+ font-weight: 700;
1009
+ color: #4361ee;
1010
+ flex: 1;
1011
+ }
1012
+
1013
+ .product-actions {
1014
+ display: flex;
1015
+ gap: 8px;
1016
+ }
1017
+
1018
+ .action-btn {
1019
+ width: 36px;
1020
+ height: 36px;
1021
+ border-radius: 8px;
1022
+ display: flex;
1023
+ align-items: center;
1024
+ justify-content: center;
1025
+ cursor: pointer;
1026
+ transition: all 0.3s ease;
1027
+ }
1028
+
1029
+ .action-btn.edit {
1030
+ background-color: rgba(58, 134, 255, 0.1);
1031
+ color: #3a86ff;
1032
+ }
1033
+
1034
+ .action-btn.delete {
1035
+ background-color: rgba(247, 37, 133, 0.1);
1036
+ color: #f72585;
1037
+ }
1038
+
1039
+ .action-btn:hover {
1040
+ transform: translateY(-2px);
1041
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
1042
+ }
1043
+
1044
+ .action-btn svg {
1045
+ width: 18px;
1046
+ height: 18px;
1047
+ }
1048
+
1049
+ .product-price {
1050
+ color: #4caf50;
1051
+ font-weight: 700;
1052
+ font-size: 16px;
1053
+ margin-bottom: 10px;
1054
+ background-color: rgba(76, 175, 80, 0.1);
1055
+ display: inline-block;
1056
+ padding: 5px 10px;
1057
+ border-radius: 6px;
1058
+ }
1059
+
1060
+ .product-description {
1061
+ margin-bottom: 15px;
1062
+ line-height: 1.5;
1063
+ color: #333;
1064
+ }
1065
+
1066
+ .product-info {
1067
+ background-color: rgba(67, 97, 238, 0.05);
1068
+ padding: 12px;
1069
+ border-radius: 8px;
1070
+ font-size: 14px;
1071
+ color: #6c757d;
1072
+ }
1073
+
1074
+ .info-label {
1075
+ font-weight: 700;
1076
+ color: #4361ee;
1077
+ }
1078
+
1079
+ /* Mobile Responsiveness for Products */
1080
+ @media (max-width: 768px) {
1081
+ .product-item {
1082
+ padding: 15px;
1083
+ }
1084
+
1085
+ .product-header {
1086
+ flex-direction: column;
1087
+ }
1088
+
1089
+ .product-title {
1090
+ margin-bottom: 10px;
1091
+ }
1092
+
1093
+ .product-actions {
1094
+ align-self: flex-end;
1095
+ }
1096
+ }
1097
+
1098
+ .navbar .logo-icon {
1099
+ width: 40px;
1100
+ height: 40px;
1101
+ background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
1102
+ border-radius: 12px;
1103
+ display: flex;
1104
+ align-items: center;
1105
+ justify-content: center;
1106
+ box-shadow: 0 5px 15px rgba(67, 97, 238, 0.2);
1107
+ position: relative;
1108
+ overflow: hidden;
1109
+ margin-left: 10px;
1110
+ }
1111
+
1112
+ .navbar .logo-icon::before {
1113
+ content: '';
1114
+ position: absolute;
1115
+ top: -10px;
1116
+ left: -10px;
1117
+ right: -10px;
1118
+ bottom: -10px;
1119
+ background: linear-gradient(135deg, rgba(255,255,255,0.2), rgba(255,255,255,0));
1120
+ transform: rotate(35deg);
1121
+ }
1122
+
1123
+ .navbar .logo-icon i {
1124
+ color: white;
1125
+ font-size: 20px;
1126
+ position: relative;
1127
+ z-index: 2;
1128
+ }
1129
+
1130
+ .navbar .logo-text h1 {
1131
+ font-size: 18px;
1132
+ font-weight: 800;
1133
+ margin: 0;
1134
+ }
1135
+
1136
+ .navbar .logo-text p {
1137
+ font-size: 12px;
1138
+ margin: 0;
1139
+ }
1140
+
1141
+ .navbar-brand {
1142
+ display: flex;
1143
+ align-items: center;
1144
+ }
1145
+ </style>
1146
+ </head>
1147
+ <body>
1148
+ <!-- Loading Overlay -->
1149
+ <div class="loading-overlay" id="loadingOverlay">
1150
+ <div class="spinner"></div>
1151
+ </div>
1152
+
1153
+ <!-- Notification Container -->
1154
+ <div class="notification-container" id="notificationContainer"></div>
1155
+
1156
+ <!-- Navbar -->
1157
+ <nav class="navbar">
1158
+ <div class="navbar-brand">
1159
+ <div class="logo-icon">
1160
+ <i class="fas fa-robot"></i>
1161
+ </div>
1162
+ <div class="logo-text">
1163
+ <h1>NANO BOT</h1>
1164
+ </div>
1165
+ </div>
1166
+ <div class="navbar-nav">
1167
+ <div class="nav-item">
1168
+ <a href="{{ url_for('messages_page') }}" class="nav-link">
1169
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1170
+ <path d="M20 4H4c-1.103 0-2 .897-2 2v12c0 1.103.897 2 2 2h16c1.103 0 2-.897 2-2V6c0-1.103-.897-2-2-2zm0 2v.511l-8 6.223-8-6.222V6h16zM4 18V9.044l7.386 5.745a.994.994 0 0 0 1.228 0L20 9.044 20.002 18H4z"/>
1171
+ </svg>
1172
+ الرسائل
1173
+ {% if unread_count > 0 %}
1174
+ <span class="message-badge">{{ unread_count }}</span>
1175
+ {% endif %}
1176
+ </a>
1177
+ </div>
1178
+ <div class="nav-item">
1179
+ <a href="#" class="nav-link" id="logoutBtn">
1180
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1181
+ <path d="M16 13v-2H7V8l-5 4 5 4v-3z"/>
1182
+ <path d="M20 3h-9c-1.103 0-2 .897-2 2v4h2V5h9v14h-9v-4H9v4c0 1.103.897 2 2 2h9c1.103 0 2-.897 2-2V5c0-1.103-.897-2-2-2z"/>
1183
+ </svg>
1184
+ تسجيل الخروج
1185
+ </a>
1186
+ </div>
1187
+ </div>
1188
+ </nav>
1189
+
1190
+ <!-- Main Container -->
1191
+ <div class="container">
1192
+ <div class="dashboard-grid">
1193
+ <!-- Status Card -->
1194
+ <div class="card">
1195
+ <div class="card-header">
1196
+ <h2 class="card-title">
1197
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1198
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
1199
+ <path d="M11 11h2v6h-2zm0-4h2v2h-2z"/>
1200
+ </svg>
1201
+ حالة البوت
1202
+ </h2>
1203
+ </div>
1204
+ <div class="card-body status-card">
1205
+ <div class="status-icon">
1206
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1207
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
1208
+ <path d="M9.999 13.587 7.7 11.292l-1.412 1.416 3.713 3.705 6.706-6.706-1.414-1.414z"/>
1209
+ </svg>
1210
+ </div>
1211
+ <h3 class="status-title">بوت الماسنجر</h3>
1212
+ <p class="status-subtitle">تحكم في حالة البوت الخاص بك</p>
1213
+
1214
+ <div class="switch-container">
1215
+ <span class="switch-label">تشغيل</span>
1216
+ <label class="switch">
1217
+ <input type="checkbox" id="botStatusToggle" {% if bot_status == 'ON' %}checked{% endif %}>
1218
+ <span class="slider"></span>
1219
+ </label>
1220
+ <span class="switch-label">إيقاف</span>
1221
+ </div>
1222
+ </div>
1223
+ </div>
1224
+
1225
+ <!-- Account Info Card -->
1226
+ <div class="card">
1227
+ <div class="card-header">
1228
+ <h2 class="card-title">
1229
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1230
+ <path d="M12 2a5 5 0 1 0 5 5 5 5 0 0 0-5-5zm0 8a3 3 0 1 1 3-3 3 3 0 0 1-3 3zm9 11v-1a7 7 0 0 0-7-7h-4a7 7 0 0 0-7 7v1h2v-1a5 5 0 0 1 5-5h4a5 5 0 0 1 5 5v1z"/>
1231
+ </svg>
1232
+ معلومات الحساب
1233
+ </h2>
1234
+ </div>
1235
+ <div class="card-body">
1236
+ <div class="info-item">
1237
+ <div class="info-icon primary">
1238
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1239
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
1240
+ <path d="M11 11h2v6h-2zm0-4h2v2h-2z"/>
1241
+ </svg>
1242
+ </div>
1243
+ <div class="info-content">
1244
+ <div class="info-label">اسم الصفحة</div>
1245
+ <div class="info-value">{{ page.username }}</div>
1246
+ </div>
1247
+ </div>
1248
+ <div class="info-item">
1249
+ <div class="info-icon success">
1250
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1251
+ <path d="M21 11h-3V4a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v14c0 1.654 1.346 3 3 3h14c1.654 0 3-1.346 3-3v-6a1 1 0 0 0-1-1zM5 19a1 1 0 0 1-1-1V5h12v13c0 .351.061.688.171 1H5zm15-1a1 1 0 0 1-2 0v-5h2v5z"/>
1252
+ <path d="M6 7h8v2H6zm0 4h8v2H6zm0 4h5v2H6z"/>
1253
+ </svg>
1254
+ </div>
1255
+ <div class="info-content">
1256
+ <div class="info-label">نوع الاشتراك</div>
1257
+ <div class="info-value">{{ subscription_status }}</div>
1258
+ {% if subscription_message %}
1259
+ <div class="subscription-warning">{{ subscription_message }}</div>
1260
+ {% endif %}
1261
+ </div>
1262
+ </div>
1263
+ <div class="info-item">
1264
+ <div class="info-icon warning">
1265
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1266
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
1267
+ <path d="M13 7h-2v5.414l3.293 3.293 1.414-1.414L13 11.586z"/>
1268
+ </svg>
1269
+ </div>
1270
+ <div class="info-content">
1271
+ <div class="info-label">تاريخ انتهاء الاشتراك</div>
1272
+ <div class="info-value {% if is_expired %}expired-date{% endif %}">{{ expiration_date }}</div>
1273
+ {% if expiration_message %}
1274
+ <div class="{% if is_expired %}expiration-error{% else %}expiration-warning{% endif %}">{{ expiration_message }}</div>
1275
+ {% endif %}
1276
+ </div>
1277
+ </div>
1278
+ </div>
1279
+ </div>
1280
+
1281
+ <!-- System Settings Card -->
1282
+ <div class="card">
1283
+ <div class="card-header">
1284
+ <h2 class="card-title">
1285
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1286
+ <path d="M12 16c2.206 0 4-1.794 4-4s-1.794-4-4-4-4 1.794-4 4 1.794 4 4 4zm0-6c1.084 0 2 .916 2 2s-.916 2-2 2-2-.916-2-2 .916-2 2-2z"/>
1287
+ <path d="m2.845 16.136 1 1.73c.531.917 1.809 1.261 2.73.73l.529-.306A8.1 8.1 0 0 0 9 19.402V20c0 1.103.897 2 2 2h2c1.103 0 2-.897 2-2v-.598a8.132 8.132 0 0 0 1.896-1.111l.529.306c.923.53 2.198.188 2.731-.731l.999-1.729a2.001 2.001 0 0 0-.731-2.732l-.505-.292a7.718 7.718 0 0 0 0-2.224l.505-.292a2.002 2.002 0 0 0 .731-2.732l-.999-1.729c-.531-.92-1.808-1.265-2.731-.732l-.529.306A8.1 8.1 0 0 0 15 4.598V4c0-1.103-.897-2-2-2h-2c-1.103 0-2 .897-2 2v.598a8.132 8.132 0 0 0-1.896 1.111l-.529-.306c-.924-.531-2.2-.187-2.731.732l-.999 1.729a2.001 2.001 0 0 0 .731 2.732l.505.292a7.683 7.683 0 0 0 0 2.223l-.505.292a2.003 2.003 0 0 0-.731 2.733zm3.326-2.758A5.703 5.703 0 0 1 6 12c0-.462.058-.926.17-1.378a.999.999 0 0 0-.47-1.108l-1.123-.65.998-1.729 1.145.662a.997.997 0 0 0 1.188-.142 6.071 6.071 0 0 1 2.384-1.399A1 1 0 0 0 11 5.3V4h2v1.3a1 1 0 0 0 .708.956 6.083 6.083 0 0 1 2.384 1.399.999.999 0 0 0 1.188.142l1.144-.661 1 1.729-1.124.649a1 1 0 0 0-.47 1.108c.112.452.17.916.17 1.378 0 .461-.058.925-.171 1.378a1 1 0 0 0 .471 1.108l1.123.649-.998 1.729-1.145-.661a.996.996 0 0 0-1.188.142 6.071 6.071 0 0 1-2.384 1.399A1 1 0 0 0 13 18.7l.002 1.3H11v-1.3a1 1 0 0 0-.708-.956 6.083 6.083 0 0 1-2.384-1.399.992.992 0 0 0-1.188-.141l-1.144.662-1-1.729 1.124-.651a1 1 0 0 0 .471-1.108z"/>
1288
+ </svg>
1289
+ إعدادات النظام
1290
+ </h2>
1291
+ </div>
1292
+ <div class="card-body">
1293
+ <div class="tabs">
1294
+ <div class="tab-item active" data-tab="style">أسلوب الرد</div>
1295
+ <div class="tab-item" data-tab="products">المنتجات</div>
1296
+ </div>
1297
+
1298
+ <div class="tab-content active" id="style-tab">
1299
+ <div class="form-group">
1300
+ <label class="form-label">أسلوب الرد للبوت</label>
1301
+ <textarea class="form-control" id="styleInput" rows="6" placeholder="أدخل أسلوب الرد الذي تريده للبوت...">{{ style }}</textarea>
1302
+ </div>
1303
+ <button class="btn btn-primary btn-block" id="saveStyleBtn">حفظ الأسلوب</button>
1304
+ </div>
1305
+
1306
+ <div class="tab-content" id="products-tab">
1307
+ <button class="btn btn-primary" id="addProductBtn">إضافة منتج جديد</button>
1308
+
1309
+ <div class="product-list" id="productsList">
1310
+ {% for product in products %}
1311
+ <div class="product-item" data-index="{{ loop.index0 }}">
1312
+ <div class="product-header">
1313
+ <div class="product-title">{{ product.name }}</div>
1314
+ <div class="product-actions">
1315
+ <div class="action-btn edit" onclick="editProduct({{ loop.index0 }})">
1316
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1317
+ <path d="M19.045 7.401c.378-.378.586-.88.586-1.414s-.208-1.036-.586-1.414l-1.586-1.586c-.378-.378-.88-.586-1.414-.586s-1.036.208-1.413.585L4 13.585V18h4.413L19.045 7.401zm-3-3 1.587 1.585-1.59 1.584-1.586-1.585 1.589-1.584zM6 16v-1.585l7.04-7.018 1.586 1.586L7.587 16H6zm-2 4h16v2H4z"/>
1318
+ </svg>
1319
+ </div>
1320
+ <div class="action-btn delete" onclick="deleteProduct({{ loop.index0 }})">
1321
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1322
+ <path d="M5 20a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8h2V6h-4V4a2 2 0 0 0-2-2H9a2 2 0 0 0-2 2v2H3v2h2zM9 4h6v2H9zM8 8h9v12H7V8z"/>
1323
+ <path d="M9 10h2v8H9zm4 0h2v8h-2z"/>
1324
+ </svg>
1325
+ </div>
1326
+ </div>
1327
+ </div>
1328
+ <div class="product-price">{{ product.price }} دينار ليبي</div>
1329
+ <div class="product-description">{{ product.description }}</div>
1330
+ {% if product.info %}
1331
+ <div class="product-info">
1332
+ <span class="info-label">معلومات إضافية:</span> {{ product.info }}
1333
+ </div>
1334
+ {% endif %}
1335
+ </div>
1336
+ {% endfor %}
1337
+ </div>
1338
+ </div>
1339
+ </div>
1340
+ </div>
1341
+
1342
+ <!-- Add/Edit Product Modal -->
1343
+ <div class="modal-overlay" id="productModal">
1344
+ <div class="modal">
1345
+ <div class="modal-header">
1346
+ <h3 class="modal-title" id="productModalTitle">إضافة منتج جديد</h3>
1347
+ <button class="modal-close" id="closeProductModal">&times;</button>
1348
+ </div>
1349
+ <div class="modal-body">
1350
+ <div class="form-group">
1351
+ <label class="form-label">اسم المنتج</label>
1352
+ <input type="text" class="form-control" id="productName" placeholder="أدخل اسم المنتج">
1353
+ </div>
1354
+ <div class="form-group">
1355
+ <label class="form-label">وصف المنتج</label>
1356
+ <textarea class="form-control" id="productDescription" rows="3" placeholder="أدخل وصف المنتج"></textarea>
1357
+ </div>
1358
+ <div class="form-group">
1359
+ <label class="form-label">السعر (دينار ليبي)</label>
1360
+ <input type="text" class="form-control" id="productPrice" placeholder="أدخل سعر المنتج">
1361
+ </div>
1362
+ <div class="form-group">
1363
+ <label class="form-label">معلومات إضافية</label>
1364
+ <textarea class="form-control" id="productInfo" rows="2" placeholder="أدخل أي معلومات إضافية عن المنتج"></textarea>
1365
+ </div>
1366
+ <input type="hidden" id="productIndex" value="-1">
1367
+ </div>
1368
+ <div class="modal-footer">
1369
+ <button class="btn btn-danger" id="cancelProductBtn">إلغاء</button>
1370
+ <button class="btn btn-primary" id="saveProductBtn">حفظ المنتج</button>
1371
+ </div>
1372
+ </div>
1373
+ </div>
1374
+
1375
+ <script>
1376
+ // DOM Elements
1377
+ const loadingOverlay = document.getElementById('loadingOverlay');
1378
+ const notificationContainer = document.getElementById('notificationContainer');
1379
+ const botStatusToggle = document.getElementById('botStatusToggle');
1380
+ const styleInput = document.getElementById('styleInput');
1381
+ const saveStyleBtn = document.getElementById('saveStyleBtn');
1382
+ const addProductBtn = document.getElementById('addProductBtn');
1383
+ const productsList = document.getElementById('productsList');
1384
+ const productModal = document.getElementById('productModal');
1385
+ const closeProductModal = document.getElementById('closeProductModal');
1386
+ const cancelProductBtn = document.getElementById('cancelProductBtn');
1387
+ const saveProductBtn = document.getElementById('saveProductBtn');
1388
+ const productModalTitle = document.getElementById('productModalTitle');
1389
+ const productName = document.getElementById('productName');
1390
+ const productDescription = document.getElementById('productDescription');
1391
+ const productPrice = document.getElementById('productPrice');
1392
+ const productInfo = document.getElementById('productInfo');
1393
+ const productIndex = document.getElementById('productIndex');
1394
+ const tabItems = document.querySelectorAll('.tab-item');
1395
+ const tabContents = document.querySelectorAll('.tab-content');
1396
+
1397
+ // WebSocket Connection
1398
+ let socket;
1399
+
1400
+ function connectWebSocket() {
1401
+ socket = io.connect(window.location.origin);
1402
+
1403
+ socket.on('connect', function() {
1404
+ console.log('WebSocket connected');
1405
+ });
1406
+
1407
+ socket.on('status_updated', function(data) {
1408
+ showNotification('تم تحديث الحالة', 'تم تحديث حالة البوت بنجاح', 'success');
1409
+ });
1410
+
1411
+ socket.on('style_updated', function(data) {
1412
+ showNotification('تم تحديث الأسلوب', 'تم تحديث أسلوب الرد بنجاح', 'success');
1413
+ });
1414
+
1415
+ socket.on('product_added', function(data) {
1416
+ showNotification('تمت الإضافة', 'تمت إضافة المنتج بنجاح', 'success');
1417
+ // Refresh the page to show the new product
1418
+ setTimeout(() => {
1419
+ window.location.reload();
1420
+ }, 1500);
1421
+ });
1422
+
1423
+ socket.on('product_deleted', function(data) {
1424
+ showNotification('تم الحذف', 'تم حذف المنتج بنجاح', 'success');
1425
+ // Refresh the page to update the products list
1426
+ setTimeout(() => {
1427
+ window.location.reload();
1428
+ }, 1500);
1429
+ });
1430
+
1431
+ socket.on('data_refreshed', function(data) {
1432
+ showNotification('تم التحديث', 'تم تحديث البيانات بنجاح', 'info');
1433
+ });
1434
+ }
1435
+
1436
+ // Initialize
1437
+ document.addEventListener('DOMContentLoaded', function() {
1438
+ // Connect WebSocket
1439
+ connectWebSocket();
1440
+
1441
+ // Initialize tabs
1442
+ tabItems.forEach(item => {
1443
+ item.addEventListener('click', () => {
1444
+ const tabId = item.getAttribute('data-tab');
1445
+
1446
+ // Remove active class from all tabs
1447
+ tabItems.forEach(tab => tab.classList.remove('active'));
1448
+ tabContents.forEach(content => content.classList.remove('active'));
1449
+
1450
+ // Add active class to current tab
1451
+ item.classList.add('active');
1452
+ document.getElementById(`${tabId}-tab`).classList.add('active');
1453
+ });
1454
+ });
1455
+
1456
+ // Bot Status Toggle
1457
+ botStatusToggle.addEventListener('change', function() {
1458
+ updateBotStatus(this.checked ? 'ON' : 'OFF');
1459
+ });
1460
+
1461
+ // Save Style Button
1462
+ saveStyleBtn.addEventListener('click', function() {
1463
+ updateStyle(styleInput.value);
1464
+ });
1465
+
1466
+ // Add Product Button
1467
+ addProductBtn.addEventListener('click', function() {
1468
+ openProductModal();
1469
+ });
1470
+
1471
+ // Close Product Modal
1472
+ closeProductModal.addEventListener('click', function() {
1473
+ closeModal(productModal);
1474
+ });
1475
+
1476
+ // Cancel Product Button
1477
+ cancelProductBtn.addEventListener('click', function() {
1478
+ closeModal(productModal);
1479
+ });
1480
+
1481
+ // Save Product Button
1482
+ saveProductBtn.addEventListener('click', function() {
1483
+ saveProduct();
1484
+ });
1485
+ });
1486
+
1487
+ // Functions
1488
+ function showLoading() {
1489
+ loadingOverlay.classList.add('active');
1490
+ }
1491
+
1492
+ function hideLoading() {
1493
+ loadingOverlay.classList.remove('active');
1494
+ }
1495
+
1496
+ function showNotification(title, message, type = 'info') {
1497
+ const notification = document.createElement('div');
1498
+ notification.className = `notification ${type}`;
1499
+
1500
+ let iconSvg;
1501
+ if (type === 'success') {
1502
+ iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="notification-icon">
1503
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
1504
+ <path d="M9.999 13.587 7.7 11.292l-1.412 1.416 3.713 3.705 6.706-6.706-1.414-1.414z"/>
1505
+ </svg>`;
1506
+ } else if (type === 'error') {
1507
+ iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="notification-icon">
1508
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
1509
+ <path d="M13 7h-2v7h2zm0 8h-2v2h2z"/>
1510
+ </svg>`;
1511
+ } else {
1512
+ iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="notification-icon">
1513
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
1514
+ <path d="M11 11h2v6h-2zm0-4h2v2h-2z"/>
1515
+ </svg>`;
1516
+ }
1517
+
1518
+ notification.innerHTML = `
1519
+ ${iconSvg}
1520
+ <div class="notification-content">
1521
+ <div class="notification-title">${title}</div>
1522
+ <div class="notification-message">${message}</div>
1523
+ </div>
1524
+ <button class="notification-close">&times;</button>
1525
+ `;
1526
+
1527
+ notificationContainer.appendChild(notification);
1528
+
1529
+ // Show notification with animation
1530
+ setTimeout(() => {
1531
+ notification.classList.add('show');
1532
+ }, 10);
1533
+
1534
+ // Auto close after 5 seconds
1535
+ setTimeout(() => {
1536
+ closeNotification(notification);
1537
+ }, 5000);
1538
+
1539
+ // Close button
1540
+ notification.querySelector('.notification-close').addEventListener('click', function() {
1541
+ closeNotification(notification);
1542
+ });
1543
+ }
1544
+
1545
+ function closeNotification(notification) {
1546
+ notification.classList.remove('show');
1547
+ setTimeout(() => {
1548
+ notification.remove();
1549
+ }, 300);
1550
+ }
1551
+
1552
+ function updateBotStatus(status) {
1553
+ showLoading();
1554
+
1555
+ fetch('/api/update_status', {
1556
+ method: 'POST',
1557
+ headers: {
1558
+ 'Content-Type': 'application/json',
1559
+ },
1560
+ body: JSON.stringify({ status: status }),
1561
+ })
1562
+ .then(response => response.json())
1563
+ .then(data => {
1564
+ hideLoading();
1565
+ if (data.success) {
1566
+ showNotification('تم تحديث الحالة', 'تم تحديث حالة البوت بنجاح', 'success');
1567
+ } else {
1568
+ showNotification('خطأ', data.message, 'error');
1569
+ // Reset toggle to previous state
1570
+ botStatusToggle.checked = status === 'OFF' ? false : true;
1571
+ }
1572
+ })
1573
+ .catch(error => {
1574
+ hideLoading();
1575
+ showNotification('خطأ', 'حدث خطأ أثناء تحديث الحالة', 'error');
1576
+ console.error('Error:', error);
1577
+ // Reset toggle to previous state
1578
+ botStatusToggle.checked = status === 'OFF' ? false : true;
1579
+ });
1580
+ }
1581
+
1582
+ function updateStyle(style) {
1583
+ showLoading();
1584
+
1585
+ fetch('/api/update_system', {
1586
+ method: 'POST',
1587
+ headers: {
1588
+ 'Content-Type': 'application/json',
1589
+ },
1590
+ body: JSON.stringify({ style: style }),
1591
+ })
1592
+ .then(response => response.json())
1593
+ .then(data => {
1594
+ hideLoading();
1595
+ if (data.success) {
1596
+ showNotification('تم تحديث الأسلوب', 'تم تحديث أسلوب الرد بنجاح', 'success');
1597
+ } else {
1598
+ showNotification('خطأ', data.message, 'error');
1599
+ }
1600
+ })
1601
+ .catch(error => {
1602
+ hideLoading();
1603
+ showNotification('خطأ', 'حدث خطأ أثناء تحديث الأسلوب', 'error');
1604
+ console.error('Error:', error);
1605
+ });
1606
+ }
1607
+
1608
+ function openProductModal(index = -1) {
1609
+ productModalTitle.textContent = index === -1 ? 'إضافة منتج جديد' : 'تعديل المنتج';
1610
+ productIndex.value = index;
1611
+
1612
+ if (index !== -1) {
1613
+ // Edit existing product
1614
+ const productItem = document.querySelector(`.product-item[data-index="${index}"]`);
1615
+ const productTitle = productItem.querySelector('.product-title').textContent;
1616
+ const productPriceText = productItem.querySelector('.product-price').textContent;
1617
+ const productDescText = productItem.querySelector('.product-description').textContent;
1618
+ const productInfoElem = productItem.querySelector('.product-info');
1619
+
1620
+ productName.value = productTitle;
1621
+ productDescription.value = productDescText;
1622
+ productPrice.value = productPriceText.replace(' دينار ليبي', '');
1623
+ productInfo.value = productInfoElem ? productInfoElem.textContent : '';
1624
+ } else {
1625
+ // Add new product
1626
+ productName.value = '';
1627
+ productDescription.value = '';
1628
+ productPrice.value = '';
1629
+ productInfo.value = '';
1630
+ }
1631
+
1632
+ openModal(productModal);
1633
+ }
1634
+
1635
+ function openModal(modal) {
1636
+ modal.classList.add('active');
1637
+ }
1638
+
1639
+ function closeModal(modal) {
1640
+ modal.classList.remove('active');
1641
+ }
1642
+
1643
+ function saveProduct() {
1644
+ const name = productName.value.trim();
1645
+ const description = productDescription.value.trim();
1646
+ const price = productPrice.value.trim();
1647
+ const info = productInfo.value.trim();
1648
+ const index = parseInt(productIndex.value);
1649
+
1650
+ if (!name || !description || !price) {
1651
+ showNotification('خطأ', 'يرجى ملء جميع الحقول المطلوبة', 'error');
1652
+ return;
1653
+ }
1654
+
1655
+ showLoading();
1656
+
1657
+ if (index === -1) {
1658
+ // Add new product
1659
+ fetch('/api/add_product', {
1660
+ method: 'POST',
1661
+ headers: {
1662
+ 'Content-Type': 'application/json',
1663
+ },
1664
+ body: JSON.stringify({
1665
+ product: {
1666
+ name: name,
1667
+ description: description,
1668
+ price: price,
1669
+ info: info
1670
+ }
1671
+ }),
1672
+ })
1673
+ .then(response => response.json())
1674
+ .then(data => {
1675
+ hideLoading();
1676
+ closeModal(productModal);
1677
+
1678
+ if (data.success) {
1679
+ showNotification('تمت الإضافة', 'تمت إضافة المنتج بنجاح', 'success');
1680
+ // Refresh the page to show the new product
1681
+ setTimeout(() => {
1682
+ window.location.reload();
1683
+ }, 1500);
1684
+ } else {
1685
+ showNotification('خطأ', data.message, 'error');
1686
+ }
1687
+ })
1688
+ .catch(error => {
1689
+ hideLoading();
1690
+ closeModal(productModal);
1691
+ showNotification('خطأ', 'حدث خطأ أثناء إضافة المنتج', 'error');
1692
+ console.error('Error:', error);
1693
+ });
1694
+ } else {
1695
+ // First delete the old product
1696
+ deleteProduct(index, false).then(() => {
1697
+ // Then add the updated product
1698
+ fetch('/api/add_product', {
1699
+ method: 'POST',
1700
+ headers: {
1701
+ 'Content-Type': 'application/json',
1702
+ },
1703
+ body: JSON.stringify({
1704
+ product: {
1705
+ name: name,
1706
+ description: description,
1707
+ price: price,
1708
+ info: info
1709
+ }
1710
+ }),
1711
+ })
1712
+ .then(response => response.json())
1713
+ .then(data => {
1714
+ hideLoading();
1715
+ closeModal(productModal);
1716
+
1717
+ if (data.success) {
1718
+ showNotification('تم التحديث', 'تم تحديث المنتج بنجاح', 'success');
1719
+ // Refresh the page to show the updated product
1720
+ setTimeout(() => {
1721
+ window.location.reload();
1722
+ }, 1500);
1723
+ } else {
1724
+ showNotification('خطأ', data.message, 'error');
1725
+ }
1726
+ })
1727
+ .catch(error => {
1728
+ hideLoading();
1729
+ closeModal(productModal);
1730
+ showNotification('خطأ', 'حدث خطأ أثناء تحديث المنتج', 'error');
1731
+ console.error('Error:', error);
1732
+ });
1733
+ });
1734
+ }
1735
+ }
1736
+
1737
+ function editProduct(index) {
1738
+ openProductModal(index);
1739
+ }
1740
+
1741
+ function deleteProduct(index, showConfirm = true) {
1742
+ if (showConfirm && !confirm('هل أنت متأكد من حذف هذا المنتج؟')) {
1743
+ return Promise.resolve();
1744
+ }
1745
+
1746
+ showLoading();
1747
+
1748
+ return fetch('/api/delete_product', {
1749
+ method: 'POST',
1750
+ headers: {
1751
+ 'Content-Type': 'application/json',
1752
+ },
1753
+ body: JSON.stringify({ index: index }),
1754
+ })
1755
+ .then(response => response.json())
1756
+ .then(data => {
1757
+ if (showConfirm) {
1758
+ hideLoading();
1759
+ }
1760
+
1761
+ if (data.success && showConfirm) {
1762
+ showNotification('تم الحذف', 'تم حذف المنتج بنجاح', 'success');
1763
+ // Refresh the page to update the products list
1764
+ setTimeout(() => {
1765
+ window.location.reload();
1766
+ }, 1500);
1767
+ } else if (!data.success && showConfirm) {
1768
+ showNotification('خطأ', data.message, 'error');
1769
+ }
1770
+
1771
+ return data;
1772
+ })
1773
+ .catch(error => {
1774
+ if (showConfirm) {
1775
+ hideLoading();
1776
+ showNotification('خطأ', 'حدث خطأ أثناء حذف المنتج', 'error');
1777
+ console.error('Error:', error);
1778
+ }
1779
+ throw error;
1780
+ });
1781
+ }
1782
+
1783
+ </script>
1784
+
1785
+ <script>
1786
+ // Logout confirmation
1787
+ document.getElementById('logoutBtn').addEventListener('click', function(e) {
1788
+ e.preventDefault();
1789
+
1790
+ // Create confirmation modal
1791
+ const modalOverlay = document.createElement('div');
1792
+ modalOverlay.className = 'modal-overlay';
1793
+
1794
+ const confirmModal = document.createElement('div');
1795
+ confirmModal.className = 'confirm-modal';
1796
+
1797
+ confirmModal.innerHTML = `
1798
+ <div class="confirm-title">تأكيد تسجيل الخروج</div>
1799
+ <div class="confirm-message">هل أنت متأكد من رغبتك في تسجيل الخروج؟</div>
1800
+ <div class="confirm-buttons">
1801
+ <button class="btn btn-danger" id="confirmLogout">تأكيد</button>
1802
+ <button class="btn btn-primary" id="cancelLogout">إلغاء</button>
1803
+ </div>
1804
+ `;
1805
+
1806
+ modalOverlay.appendChild(confirmModal);
1807
+ document.body.appendChild(modalOverlay);
1808
+
1809
+ // Show modal
1810
+ setTimeout(() => {
1811
+ modalOverlay.classList.add('active');
1812
+ }, 10);
1813
+
1814
+ // Confirm button
1815
+ document.getElementById('confirmLogout').addEventListener('click', function() {
1816
+ window.location.href = "{{ url_for('logout') }}";
1817
+ });
1818
+
1819
+ // Cancel button
1820
+ document.getElementById('cancelLogout').addEventListener('click', function() {
1821
+ modalOverlay.classList.remove('active');
1822
+ setTimeout(() => {
1823
+ modalOverlay.remove();
1824
+ }, 300);
1825
+ });
1826
+ });
1827
+
1828
+ // Improved delete product function
1829
+ function deleteProduct(index) {
1830
+ // Create confirmation modal
1831
+ const modalOverlay = document.createElement('div');
1832
+ modalOverlay.className = 'modal-overlay';
1833
+
1834
+ const confirmModal = document.createElement('div');
1835
+ confirmModal.className = 'confirm-modal';
1836
+
1837
+ confirmModal.innerHTML = `
1838
+ <div class="confirm-title">تأكيد حذف المنتج</div>
1839
+ <div class="confirm-message">هل أنت متأكد من رغبتك في حذف هذا المنتج؟ لا يمكن التراجع عن هذه العملية.</div>
1840
+ <div class="confirm-buttons">
1841
+ <button class="btn btn-danger" id="confirmDelete">حذف</button>
1842
+ <button class="btn btn-primary" id="cancelDelete">إلغاء</button>
1843
+ </div>
1844
+ `;
1845
+
1846
+ modalOverlay.appendChild(confirmModal);
1847
+ document.body.appendChild(modalOverlay);
1848
+
1849
+ // Show modal
1850
+ setTimeout(() => {
1851
+ modalOverlay.classList.add('active');
1852
+ }, 10);
1853
+
1854
+ // Confirm button
1855
+ document.getElementById('confirmDelete').addEventListener('click', function() {
1856
+ modalOverlay.classList.remove('active');
1857
+
1858
+ showLoading();
1859
+
1860
+ fetch('/api/delete_product', {
1861
+ method: 'POST',
1862
+ headers: {
1863
+ 'Content-Type': 'application/json',
1864
+ },
1865
+ body: JSON.stringify({ index: index }),
1866
+ })
1867
+ .then(response => response.json())
1868
+ .then(data => {
1869
+ hideLoading();
1870
+
1871
+ if (data.success) {
1872
+ showNotification('تم الحذف', 'تم حذف المنتج بنجاح', 'success');
1873
+ // Refresh the page to update the products list
1874
+ setTimeout(() => {
1875
+ window.location.reload();
1876
+ }, 1500);
1877
+ } else {
1878
+ showNotification('خطأ', data.message, 'error');
1879
+ }
1880
+
1881
+ setTimeout(() => {
1882
+ modalOverlay.remove();
1883
+ }, 300);
1884
+ })
1885
+ .catch(error => {
1886
+ hideLoading();
1887
+ showNotification('خطأ', 'حدث خطأ أثناء حذف المنتج', 'error');
1888
+ console.error('Error:', error);
1889
+
1890
+ setTimeout(() => {
1891
+ modalOverlay.remove();
1892
+ }, 300);
1893
+ });
1894
+ });
1895
+
1896
+ // Cancel button
1897
+ document.getElementById('cancelDelete').addEventListener('click', function() {
1898
+ modalOverlay.classList.remove('active');
1899
+ setTimeout(() => {
1900
+ modalOverlay.remove();
1901
+ }, 300);
1902
+ });
1903
+ }
1904
+
1905
+ // Improved edit product function
1906
+ function editProduct(index) {
1907
+ productModalTitle.textContent = 'تعديل المنتج';
1908
+ productIndex.value = index;
1909
+
1910
+ // Get the product data from the DOM
1911
+ const productItem = document.querySelector(`.product-item[data-index="${index}"]`);
1912
+
1913
+ if (productItem) {
1914
+ const titleElem = productItem.querySelector('.product-title');
1915
+ const priceElem = productItem.querySelector('.product-price');
1916
+ const descElem = productItem.querySelector('.product-description');
1917
+ const infoElem = productItem.querySelector('.product-info');
1918
+
1919
+ // Extract values
1920
+ let name = titleElem ? titleElem.textContent.trim() : '';
1921
+ let price = priceElem ? priceElem.textContent.replace(' دينار ليبي', '').trim() : '';
1922
+ let description = descElem ? descElem.textContent.trim() : '';
1923
+ let info = '';
1924
+
1925
+ if (infoElem) {
1926
+ // Remove the label if present
1927
+ info = infoElem.textContent.replace('معلومات إضافية:', '').trim();
1928
+ }
1929
+
1930
+ // Set form values
1931
+ productName.value = name;
1932
+ productDescription.value = description;
1933
+ productPrice.value = price;
1934
+ productInfo.value = info;
1935
+ }
1936
+
1937
+ // Open modal
1938
+ openModal(productModal);
1939
+ }
1940
+
1941
+ // Update the saveProduct function to handle editing better
1942
+ function saveProduct() {
1943
+ const name = productName.value.trim();
1944
+ const description = productDescription.value.trim();
1945
+ const price = productPrice.value.trim();
1946
+ const info = productInfo.value.trim();
1947
+ const index = parseInt(productIndex.value);
1948
+
1949
+ if (!name || !description || !price) {
1950
+ showNotification('خطأ', 'يرجى ملء جميع الحقول المطلوبة', 'error');
1951
+ return;
1952
+ }
1953
+
1954
+ showLoading();
1955
+
1956
+ // Prepare product data
1957
+ const productData = {
1958
+ product: {
1959
+ name: name,
1960
+ description: description,
1961
+ price: price,
1962
+ info: info
1963
+ }
1964
+ };
1965
+
1966
+ if (index === -1) {
1967
+ // Add new product
1968
+ fetch('/api/add_product', {
1969
+ method: 'POST',
1970
+ headers: {
1971
+ 'Content-Type': 'application/json',
1972
+ },
1973
+ body: JSON.stringify(productData),
1974
+ })
1975
+ .then(response => response.json())
1976
+ .then(data => {
1977
+ hideLoading();
1978
+ closeModal(productModal);
1979
+
1980
+ if (data.success) {
1981
+ showNotification('تمت الإضافة', 'تمت إضافة المنتج بنجاح', 'success');
1982
+ // Refresh the page to show the new product
1983
+ setTimeout(() => {
1984
+ window.location.reload();
1985
+ }, 1500);
1986
+ } else {
1987
+ showNotification('خطأ', data.message, 'error');
1988
+ }
1989
+ })
1990
+ .catch(error => {
1991
+ hideLoading();
1992
+ closeModal(productModal);
1993
+ showNotification('خطأ', 'حدث خطأ أثناء إضافة المنتج', 'error');
1994
+ console.error('Error:', error);
1995
+ });
1996
+ } else {
1997
+ // Update existing product (delete then add)
1998
+ fetch('/api/delete_product', {
1999
+ method: 'POST',
2000
+ headers: {
2001
+ 'Content-Type': 'application/json',
2002
+ },
2003
+ body: JSON.stringify({ index: index }),
2004
+ })
2005
+ .then(response => response.json())
2006
+ .then(data => {
2007
+ if (data.success) {
2008
+ // Now add the updated product
2009
+ return fetch('/api/add_product', {
2010
+ method: 'POST',
2011
+ headers: {
2012
+ 'Content-Type': 'application/json',
2013
+ },
2014
+ body: JSON.stringify(productData),
2015
+ });
2016
+ } else {
2017
+ throw new Error(data.message || 'Failed to delete product');
2018
+ }
2019
+ })
2020
+ .then(response => response.json())
2021
+ .then(data => {
2022
+ hideLoading();
2023
+ closeModal(productModal);
2024
+
2025
+ if (data.success) {
2026
+ showNotification('تم التحديث', 'تم تحديث المنتج بنجاح', 'success');
2027
+ // Refresh the page to show the updated product
2028
+ setTimeout(() => {
2029
+ window.location.reload();
2030
+ }, 1500);
2031
+ } else {
2032
+ showNotification('خطأ', data.message, 'error');
2033
+ }
2034
+ })
2035
+ .catch(error => {
2036
+ hideLoading();
2037
+ closeModal(productModal);
2038
+ showNotification('خطأ', 'حدث خطأ أثناء تحديث المنتج', 'error');
2039
+ console.error('Error:', error);
2040
+ });
2041
+ }
2042
+ }
2043
+ </script>
2044
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
2045
+ </body>
2046
+ </html>
templates/login.html ADDED
@@ -0,0 +1,488 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>NANO BOT - تسجيل الدخول</title>
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
8
+ <style>
9
+ @import url('https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800&display=swap');
10
+
11
+ :root {
12
+ --primary: #4361ee;
13
+ --primary-dark: #3a56d4;
14
+ --secondary: #7209b7;
15
+ --accent: #4cc9f0;
16
+ --dark: #2b2d42;
17
+ --light: #f8f9fa;
18
+ --gray-100: #f1f3f5;
19
+ --gray-200: #e9ecef;
20
+ --gray-300: #dee2e6;
21
+ --success: #38b000;
22
+ --warning: #ffaa00;
23
+ --danger: #e63946;
24
+ --info: #3a86ff;
25
+ }
26
+
27
+ * {
28
+ margin: 0;
29
+ padding: 0;
30
+ box-sizing: border-box;
31
+ font-family: 'Tajawal', sans-serif;
32
+ }
33
+
34
+ body {
35
+ background: #f5f7ff;
36
+ min-height: 100vh;
37
+ display: flex;
38
+ justify-content: center;
39
+ align-items: center;
40
+ padding: 15px;
41
+ direction: rtl;
42
+ }
43
+
44
+ .app-container {
45
+ width: 100%;
46
+ max-width: 480px;
47
+ background: linear-gradient(145deg, #ffffff, #f8f9ff);
48
+ border-radius: 24px;
49
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08);
50
+ overflow: hidden;
51
+ position: relative;
52
+ }
53
+
54
+ .header {
55
+ padding: 30px 25px 0;
56
+ position: relative;
57
+ z-index: 1;
58
+ }
59
+
60
+ .header::before {
61
+ content: '';
62
+ position: absolute;
63
+ top: -100px;
64
+ right: -100px;
65
+ width: 250px;
66
+ height: 250px;
67
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
68
+ border-radius: 50%;
69
+ opacity: 0.1;
70
+ z-index: -1;
71
+ }
72
+
73
+ .header::after {
74
+ content: '';
75
+ position: absolute;
76
+ bottom: -50px;
77
+ left: -50px;
78
+ width: 150px;
79
+ height: 150px;
80
+ background: linear-gradient(135deg, var(--accent), var(--primary));
81
+ border-radius: 50%;
82
+ opacity: 0.1;
83
+ z-index: -1;
84
+ }
85
+
86
+ .logo-container {
87
+ display: flex;
88
+ align-items: center;
89
+ margin-bottom: 25px;
90
+ }
91
+
92
+ .logo-icon {
93
+ width: 60px;
94
+ height: 60px;
95
+ background: linear-gradient(135deg, var(--primary), var(--secondary));
96
+ border-radius: 18px;
97
+ display: flex;
98
+ align-items: center;
99
+ justify-content: center;
100
+ box-shadow: 0 10px 20px rgba(67, 97, 238, 0.2);
101
+ position: relative;
102
+ overflow: hidden;
103
+ }
104
+
105
+ .logo-icon::before {
106
+ content: '';
107
+ position: absolute;
108
+ top: -10px;
109
+ left: -10px;
110
+ right: -10px;
111
+ bottom: -10px;
112
+ background: linear-gradient(135deg, rgba(255,255,255,0.2), rgba(255,255,255,0));
113
+ transform: rotate(35deg);
114
+ }
115
+
116
+ .logo-icon i {
117
+ color: white;
118
+ font-size: 28px;
119
+ position: relative;
120
+ z-index: 2;
121
+ }
122
+
123
+ .logo-text {
124
+ margin-right: 15px;
125
+ }
126
+
127
+ .logo-text h1 {
128
+ font-size: 24px;
129
+ font-weight: 800;
130
+ color: var(--dark);
131
+ margin: 0;
132
+ letter-spacing: -0.5px;
133
+ }
134
+
135
+ .logo-text p {
136
+ font-size: 14px;
137
+ color: #6c757d;
138
+ margin: 0;
139
+ }
140
+
141
+ .main-content {
142
+ padding: 0 25px 30px;
143
+ }
144
+
145
+ .form-intro {
146
+ text-align: right;
147
+ margin-bottom: 25px;
148
+ }
149
+
150
+ .form-intro p {
151
+ color: #4b5563;
152
+ font-size: 16px;
153
+ line-height: 1.6;
154
+ }
155
+
156
+ .form-group {
157
+ margin-bottom: 20px;
158
+ position: relative;
159
+ }
160
+
161
+ .form-group label {
162
+ display: block;
163
+ margin-bottom: 8px;
164
+ color: var(--dark);
165
+ font-weight: 600;
166
+ font-size: 15px;
167
+ }
168
+
169
+ .form-group input {
170
+ width: 100%;
171
+ padding: 15px;
172
+ background: white;
173
+ border: 1px solid var(--gray-300);
174
+ border-radius: 12px;
175
+ font-size: 15px;
176
+ transition: all 0.3s ease;
177
+ color: var(--dark);
178
+ }
179
+
180
+ .form-group input:focus {
181
+ border-color: var(--primary);
182
+ box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.15);
183
+ outline: none;
184
+ }
185
+
186
+ .password-toggle {
187
+ position: absolute;
188
+ left: 15px;
189
+ top: 45px;
190
+ color: #6c757d;
191
+ cursor: pointer;
192
+ font-size: 16px;
193
+ }
194
+
195
+ .submit-btn {
196
+ width: 100%;
197
+ padding: 16px;
198
+ background: linear-gradient(135deg, var(--primary), var(--primary-dark));
199
+ color: white;
200
+ border: none;
201
+ border-radius: 14px;
202
+ font-size: 16px;
203
+ font-weight: 700;
204
+ cursor: pointer;
205
+ transition: all 0.3s ease;
206
+ position: relative;
207
+ overflow: hidden;
208
+ box-shadow: 0 8px 20px rgba(67, 97, 238, 0.25);
209
+ margin-top: 10px;
210
+ }
211
+
212
+ .submit-btn::before {
213
+ content: '';
214
+ position: absolute;
215
+ top: 0;
216
+ left: -100%;
217
+ width: 100%;
218
+ height: 100%;
219
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
220
+ transition: 0.5s;
221
+ }
222
+
223
+ .submit-btn:hover::before {
224
+ left: 100%;
225
+ }
226
+
227
+ .submit-btn:hover {
228
+ transform: translateY(-3px);
229
+ box-shadow: 0 12px 25px rgba(67, 97, 238, 0.35);
230
+ }
231
+
232
+ .submit-btn:active {
233
+ transform: translateY(0);
234
+ }
235
+
236
+ .spinner {
237
+ display: none;
238
+ width: 20px;
239
+ height: 20px;
240
+ border: 2px solid rgba(255, 255, 255, 0.3);
241
+ border-radius: 50%;
242
+ border-top-color: white;
243
+ animation: spin 0.8s linear infinite;
244
+ position: absolute;
245
+ left: 50%;
246
+ top: 50%;
247
+ transform: translate(-50%, -50%);
248
+ }
249
+
250
+ @keyframes spin {
251
+ to { transform: translate(-50%, -50%) rotate(360deg); }
252
+ }
253
+
254
+ .button-text {
255
+ transition: opacity 0.3s ease;
256
+ }
257
+
258
+ .footer {
259
+ background: var(--gray-100);
260
+ padding: 20px;
261
+ text-align: center;
262
+ border-top: 1px solid var(--gray-200);
263
+ }
264
+
265
+ .footer-text {
266
+ font-size: 13px;
267
+ color: #6c757d;
268
+ margin-bottom: 10px;
269
+ }
270
+
271
+ .social-links {
272
+ display: flex;
273
+ justify-content: center;
274
+ gap: 15px;
275
+ }
276
+
277
+ .social-link {
278
+ width: 36px;
279
+ height: 36px;
280
+ border-radius: 50%;
281
+ background: white;
282
+ display: flex;
283
+ align-items: center;
284
+ justify-content: center;
285
+ color: var(--primary);
286
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
287
+ transition: all 0.3s ease;
288
+ }
289
+
290
+ .social-link:hover {
291
+ transform: translateY(-3px);
292
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
293
+ }
294
+
295
+ .notification {
296
+ position: fixed;
297
+ top: 20px;
298
+ left: 50%;
299
+ transform: translateX(-50%);
300
+ padding: 16px 25px;
301
+ border-radius: 12px;
302
+ color: white;
303
+ font-weight: 500;
304
+ display: none;
305
+ z-index: 1000;
306
+ box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
307
+ text-align: center;
308
+ min-width: 300px;
309
+ max-width: 90%;
310
+ font-size: 15px;
311
+ transition: all 0.3s ease;
312
+ }
313
+
314
+ .success {
315
+ background: linear-gradient(135deg, #10b981, #059669);
316
+ }
317
+
318
+ .error {
319
+ background: linear-gradient(135deg, #ef4444, #dc2626);
320
+ }
321
+
322
+ .alert {
323
+ background: linear-gradient(145deg, #fff1f1, #ffe6e6);
324
+ border-radius: 12px;
325
+ padding: 15px;
326
+ margin-bottom: 20px;
327
+ color: var(--danger);
328
+ font-size: 14px;
329
+ border-right: 4px solid var(--danger);
330
+ }
331
+
332
+ /* Responsive adjustments */
333
+ @media (max-width: 480px) {
334
+ body {
335
+ padding: 0;
336
+ background: linear-gradient(145deg, #ffffff, #f8f9ff);
337
+ }
338
+
339
+ .app-container {
340
+ max-width: 100%;
341
+ height: 100vh;
342
+ border-radius: 0;
343
+ box-shadow: none;
344
+ display: flex;
345
+ flex-direction: column;
346
+ }
347
+
348
+ .main-content {
349
+ flex: 1;
350
+ display: flex;
351
+ flex-direction: column;
352
+ justify-content: center;
353
+ padding: 0 20px;
354
+ }
355
+
356
+ .header {
357
+ padding: 25px 20px 0;
358
+ }
359
+
360
+ .logo-icon {
361
+ width: 50px;
362
+ height: 50px;
363
+ }
364
+
365
+ .logo-icon i {
366
+ font-size: 24px;
367
+ }
368
+
369
+ .logo-text h1 {
370
+ font-size: 22px;
371
+ }
372
+
373
+ .form-group input {
374
+ padding: 12px;
375
+ }
376
+
377
+ .submit-btn {
378
+ padding: 14px;
379
+ }
380
+
381
+ .footer {
382
+ margin-top: auto;
383
+ }
384
+ }
385
+ </style>
386
+ </head>
387
+ <body>
388
+ <div class="notification" id="notification"></div>
389
+
390
+ <div class="app-container">
391
+ <div class="header">
392
+ <div class="logo-container">
393
+ <div class="logo-icon">
394
+ <i class="fas fa-robot"></i>
395
+ </div>
396
+ <div class="logo-text">
397
+ <h1>NANO BOT</h1>
398
+ <p>الذكاء الاصطناعي لخدمة العملاء</p>
399
+ </div>
400
+ </div>
401
+ </div>
402
+
403
+ <div class="main-content">
404
+ <div class="form-intro">
405
+ <p>قم بتسجيل الدخول للوصول إلى لوحة التحكم والاستفادة من خدمات الذكاء الاصطناعي المتقدمة للرد التلقائي على رسائل العملاء.</p>
406
+ </div>
407
+
408
+ {% if error %}
409
+ <div class="alert">
410
+ {{ error }}
411
+ </div>
412
+ {% endif %}
413
+
414
+ <form id="loginForm" method="post" onsubmit="showLoading()">
415
+ <div class="form-group">
416
+ <label for="username">اسم المستخدم</label>
417
+ <input type="text" id="username" name="username" required autofocus>
418
+ </div>
419
+
420
+ <div class="form-group">
421
+ <label for="password">كلمة المرور</label>
422
+ <input type="password" id="password" name="password" required>
423
+ <span class="password-toggle" onclick="togglePassword()">
424
+ <i class="fas fa-eye" id="toggleIcon"></i>
425
+ </span>
426
+ </div>
427
+
428
+ <button type="submit" class="submit-btn" id="submitButton">
429
+ <span class="button-text">تسجيل الدخول</span>
430
+ <span class="spinner" id="loadingSpinner"></span>
431
+ </button>
432
+ </form>
433
+ </div>
434
+
435
+ <div class="footer">
436
+ <p class="footer-text">NANO BOT © 2023 - روبوت الذكاء الاصطناعي للتواصل مع العملاء</p>
437
+ <div class="social-links">
438
+ <a href="#" class="social-link"><i class="fab fa-facebook-f"></i></a>
439
+ <a href="#" class="social-link"><i class="fab fa-twitter"></i></a>
440
+ <a href="#" class="social-link"><i class="fab fa-instagram"></i></a>
441
+ <a href="#" class="social-link"><i class="fab fa-linkedin-in"></i></a>
442
+ </div>
443
+ </div>
444
+ </div>
445
+
446
+ <script>
447
+ function showLoading() {
448
+ const buttonText = document.querySelector('.button-text');
449
+ const loadingSpinner = document.getElementById('loadingSpinner');
450
+
451
+ buttonText.style.opacity = '0';
452
+ loadingSpinner.style.display = 'block';
453
+ }
454
+
455
+ function togglePassword() {
456
+ const passwordInput = document.getElementById('password');
457
+ const toggleIcon = document.getElementById('toggleIcon');
458
+
459
+ if (passwordInput.type === 'password') {
460
+ passwordInput.type = 'text';
461
+ toggleIcon.classList.remove('fa-eye');
462
+ toggleIcon.classList.add('fa-eye-slash');
463
+ } else {
464
+ passwordInput.type = 'password';
465
+ toggleIcon.classList.remove('fa-eye-slash');
466
+ toggleIcon.classList.add('fa-eye');
467
+ }
468
+ }
469
+
470
+ function showNotification(message, type) {
471
+ const notification = document.getElementById('notification');
472
+ notification.textContent = message;
473
+ notification.className = 'notification ' + type;
474
+ notification.style.display = 'block';
475
+
476
+ setTimeout(function() {
477
+ notification.style.opacity = '0';
478
+ notification.style.transform = 'translateX(-50%) translateY(-20px)';
479
+ setTimeout(() => {
480
+ notification.style.display = 'none';
481
+ notification.style.opacity = '1';
482
+ notification.style.transform = 'translateX(-50%) translateY(0)';
483
+ }, 300);
484
+ }, 5000);
485
+ }
486
+ </script>
487
+ </body>
488
+ </html>
templates/messages.html ADDED
@@ -0,0 +1,1160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ar" dir="rtl">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>نانو بوت - الرسائل</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@300;400;500;700;800&display=swap" rel="stylesheet">
10
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
11
+ <style>
12
+ :root {
13
+ --primary-color: #4361ee;
14
+ --primary-light: #4895ef;
15
+ --primary-dark: #3f37c9;
16
+ --secondary-color: #4cc9f0;
17
+ --success-color: #4caf50;
18
+ --danger-color: #f72585;
19
+ --warning-color: #ff9e00;
20
+ --info-color: #3a86ff;
21
+ --light-color: #f8f9fa;
22
+ --dark-color: #212529;
23
+ --body-bg: #f0f5ff;
24
+ --card-bg: #ffffff;
25
+ --border-color: #e9ecef;
26
+ --text-color: #333;
27
+ --text-muted: #6c757d;
28
+ --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.05);
29
+ --shadow-md: 0 5px 15px rgba(0, 0, 0, 0.07);
30
+ --shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.1);
31
+ --transition: all 0.3s ease;
32
+ --border-radius: 12px;
33
+ }
34
+
35
+ * {
36
+ margin: 0;
37
+ padding: 0;
38
+ box-sizing: border-box;
39
+ font-family: 'Tajawal', sans-serif;
40
+ }
41
+
42
+ body {
43
+ background-color: var(--body-bg);
44
+ color: var(--text-color);
45
+ min-height: 100vh;
46
+ display: flex;
47
+ flex-direction: column;
48
+ }
49
+
50
+ /* Scrollbar Styling */
51
+ ::-webkit-scrollbar {
52
+ width: 8px;
53
+ height: 8px;
54
+ }
55
+
56
+ ::-webkit-scrollbar-track {
57
+ background: #f1f1f1;
58
+ border-radius: 10px;
59
+ }
60
+
61
+ ::-webkit-scrollbar-thumb {
62
+ background: var(--primary-light);
63
+ border-radius: 10px;
64
+ }
65
+
66
+ ::-webkit-scrollbar-thumb:hover {
67
+ background: var(--primary-color);
68
+ }
69
+
70
+ /* Navigation */
71
+ .navbar {
72
+ background-color: var(--card-bg);
73
+ color: var(--text-color);
74
+ padding: 15px 20px;
75
+ display: flex;
76
+ justify-content: space-between;
77
+ align-items: center;
78
+ box-shadow: var(--shadow-md);
79
+ position: sticky;
80
+ top: 0;
81
+ z-index: 100;
82
+ }
83
+
84
+ .navbar-brand {
85
+ display: flex;
86
+ align-items: center;
87
+ font-size: 22px;
88
+ font-weight: 700;
89
+ color: var(--primary-color);
90
+ }
91
+
92
+ .navbar-brand svg {
93
+ width: 28px;
94
+ height: 28px;
95
+ margin-left: 10px;
96
+ fill: var(--primary-color);
97
+ }
98
+
99
+ .navbar-nav {
100
+ display: flex;
101
+ align-items: center;
102
+ }
103
+
104
+ .nav-item {
105
+ margin-right: 20px;
106
+ }
107
+
108
+ .nav-link {
109
+ color: var(--text-color);
110
+ text-decoration: none;
111
+ font-weight: 500;
112
+ transition: var(--transition);
113
+ display: flex;
114
+ align-items: center;
115
+ }
116
+
117
+ .nav-link:hover {
118
+ color: var(--primary-color);
119
+ }
120
+
121
+ .nav-link svg {
122
+ margin-left: 5px;
123
+ width: 18px;
124
+ height: 18px;
125
+ }
126
+
127
+ .container {
128
+ max-width: 1200px;
129
+ width: 100%;
130
+ margin: 0 auto;
131
+ padding: 20px;
132
+ flex: 1;
133
+ }
134
+
135
+ /* Page Header */
136
+ .page-header {
137
+ display: flex;
138
+ justify-content: space-between;
139
+ align-items: center;
140
+ margin-bottom: 20px;
141
+ flex-wrap: wrap;
142
+ gap: 15px;
143
+ }
144
+
145
+ .page-title {
146
+ font-size: 24px;
147
+ font-weight: 700;
148
+ color: var(--primary-color);
149
+ display: flex;
150
+ align-items: center;
151
+ }
152
+
153
+ .page-title svg {
154
+ margin-left: 10px;
155
+ width: 24px;
156
+ height: 24px;
157
+ }
158
+
159
+ .page-actions {
160
+ display: flex;
161
+ gap: 10px;
162
+ }
163
+
164
+ /* Messages */
165
+ .messages-container {
166
+ display: grid;
167
+ grid-template-columns: 1fr;
168
+ gap: 20px;
169
+ }
170
+
171
+ @media (min-width: 768px) {
172
+ .messages-container {
173
+ grid-template-columns: repeat(2, 1fr);
174
+ }
175
+ }
176
+
177
+ @media (min-width: 1200px) {
178
+ .messages-container {
179
+ grid-template-columns: repeat(3, 1fr);
180
+ }
181
+ }
182
+
183
+ .message-card {
184
+ background-color: var(--card-bg);
185
+ border-radius: var(--border-radius);
186
+ box-shadow: var(--shadow-sm);
187
+ transition: var(--transition);
188
+ overflow: hidden;
189
+ position: relative;
190
+ }
191
+
192
+ .message-card:hover {
193
+ box-shadow: var(--shadow-md);
194
+ transform: translateY(-3px);
195
+ }
196
+
197
+ .message-card.unread::before {
198
+ content: '';
199
+ position: absolute;
200
+ top: 15px;
201
+ left: 15px;
202
+ width: 10px;
203
+ height: 10px;
204
+ background-color: var(--primary-color);
205
+ border-radius: 50%;
206
+ }
207
+
208
+ .message-header {
209
+ padding: 15px 20px;
210
+ border-bottom: 1px solid var(--border-color);
211
+ display: flex;
212
+ align-items: center;
213
+ }
214
+
215
+ .user-avatar {
216
+ width: 40px;
217
+ height: 40px;
218
+ border-radius: 50%;
219
+ background-color: var(--primary-light);
220
+ display: flex;
221
+ align-items: center;
222
+ justify-content: center;
223
+ color: white;
224
+ font-weight: 700;
225
+ margin-left: 15px;
226
+ flex-shrink: 0;
227
+ overflow: hidden;
228
+ }
229
+
230
+ .user-avatar img {
231
+ width: 100%;
232
+ height: 100%;
233
+ object-fit: cover;
234
+ }
235
+
236
+ .user-info {
237
+ flex: 1;
238
+ }
239
+
240
+ .user-name {
241
+ font-weight: 700;
242
+ margin-bottom: 5px;
243
+ }
244
+
245
+ .message-time {
246
+ font-size: 12px;
247
+ color: var(--text-muted);
248
+ }
249
+
250
+ .message-body {
251
+ padding: 20px;
252
+ min-height: 100px;
253
+ }
254
+
255
+ .message-text {
256
+ line-height: 1.6;
257
+ margin-bottom: 15px;
258
+ }
259
+
260
+ .message-footer {
261
+ padding: 15px 20px;
262
+ border-top: 1px solid var(--border-color);
263
+ display: flex;
264
+ justify-content: space-between;
265
+ align-items: center;
266
+ }
267
+
268
+ .message-actions {
269
+ display: flex;
270
+ gap: 10px;
271
+ }
272
+
273
+ .btn {
274
+ display: inline-block;
275
+ padding: 8px 16px;
276
+ border: none;
277
+ border-radius: 8px;
278
+ font-size: 14px;
279
+ font-weight: 500;
280
+ cursor: pointer;
281
+ transition: var(--transition);
282
+ text-align: center;
283
+ text-decoration: none;
284
+ }
285
+
286
+ .btn-primary {
287
+ background-color: var(--primary-color);
288
+ color: white;
289
+ }
290
+
291
+ .btn-primary:hover {
292
+ background-color: var(--primary-dark);
293
+ }
294
+
295
+ .btn-danger {
296
+ background-color: var(--danger-color);
297
+ color: white;
298
+ }
299
+
300
+ .btn-danger:hover {
301
+ background-color: #d61a6c;
302
+ }
303
+
304
+ .btn-outline {
305
+ background-color: transparent;
306
+ border: 1px solid var(--border-color);
307
+ color: var(--text-color);
308
+ }
309
+
310
+ .btn-outline:hover {
311
+ background-color: var(--light-color);
312
+ }
313
+
314
+ .btn-sm {
315
+ padding: 6px 12px;
316
+ font-size: 12px;
317
+ }
318
+
319
+ .btn svg {
320
+ width: 16px;
321
+ height: 16px;
322
+ margin-left: 5px;
323
+ vertical-align: middle;
324
+ }
325
+
326
+ /* Empty State */
327
+ .empty-state {
328
+ text-align: center;
329
+ padding: 50px 20px;
330
+ background-color: var(--card-bg);
331
+ border-radius: var(--border-radius);
332
+ box-shadow: var(--shadow-sm);
333
+ }
334
+
335
+ .empty-icon {
336
+ width: 80px;
337
+ height: 80px;
338
+ margin: 0 auto 20px;
339
+ color: var(--text-muted);
340
+ }
341
+
342
+ .empty-title {
343
+ font-size: 20px;
344
+ font-weight: 700;
345
+ margin-bottom: 10px;
346
+ color: var(--text-color);
347
+ }
348
+
349
+ .empty-description {
350
+ color: var(--text-muted);
351
+ margin-bottom: 20px;
352
+ }
353
+
354
+ /* Loading */
355
+ .loading-overlay {
356
+ position: fixed;
357
+ top: 0;
358
+ left: 0;
359
+ right: 0;
360
+ bottom: 0;
361
+ background-color: rgba(255, 255, 255, 0.8);
362
+ display: flex;
363
+ justify-content: center;
364
+ align-items: center;
365
+ z-index: 2000;
366
+ opacity: 0;
367
+ visibility: hidden;
368
+ transition: var(--transition);
369
+ }
370
+
371
+ .loading-overlay.active {
372
+ opacity: 1;
373
+ visibility: visible;
374
+ }
375
+
376
+ .spinner {
377
+ width: 50px;
378
+ height: 50px;
379
+ border: 5px solid rgba(67, 97, 238, 0.2);
380
+ border-radius: 50%;
381
+ border-top-color: var(--primary-color);
382
+ animation: spin 1s linear infinite;
383
+ }
384
+
385
+ @keyframes spin {
386
+ 0% { transform: rotate(0deg); }
387
+ 100% { transform: rotate(360deg); }
388
+ }
389
+
390
+ /* Notifications */
391
+ .notification-container {
392
+ position: fixed;
393
+ top: 20px;
394
+ left: 20px;
395
+ right: 20px;
396
+ z-index: 1001;
397
+ display: flex;
398
+ flex-direction: column;
399
+ align-items: center;
400
+ pointer-events: none;
401
+ }
402
+
403
+ .notification {
404
+ background-color: var(--card-bg);
405
+ border-radius: 8px;
406
+ box-shadow: var(--shadow-md);
407
+ padding: 15px 20px;
408
+ margin-bottom: 10px;
409
+ display: flex;
410
+ align-items: center;
411
+ width: 100%;
412
+ max-width: 400px;
413
+ transform: translateY(-20px);
414
+ opacity: 0;
415
+ transition: all 0.3s ease;
416
+ pointer-events: auto;
417
+ }
418
+
419
+ .notification.show {
420
+ transform: translateY(0);
421
+ opacity: 1;
422
+ }
423
+
424
+ .notification-icon {
425
+ width: 24px;
426
+ height: 24px;
427
+ margin-left: 15px;
428
+ flex-shrink: 0;
429
+ }
430
+
431
+ .notification-content {
432
+ flex: 1;
433
+ }
434
+
435
+ .notification-title {
436
+ font-weight: 700;
437
+ margin-bottom: 5px;
438
+ }
439
+
440
+ .notification-message {
441
+ font-size: 14px;
442
+ color: var(--text-muted);
443
+ }
444
+
445
+ .notification-close {
446
+ background: none;
447
+ border: none;
448
+ cursor: pointer;
449
+ color: var(--text-muted);
450
+ margin-right: -5px;
451
+ }
452
+
453
+ .notification.success .notification-icon {
454
+ color: var(--success-color);
455
+ }
456
+
457
+ .notification.error .notification-icon {
458
+ color: var(--danger-color);
459
+ }
460
+
461
+ .notification.info .notification-icon {
462
+ color: var(--info-color);
463
+ }
464
+
465
+ /* Responsive Adjustments */
466
+ @media (max-width: 768px) {
467
+ .navbar {
468
+ padding: 10px 15px;
469
+ }
470
+
471
+ .navbar-brand {
472
+ font-size: 18px;
473
+ }
474
+
475
+ .container {
476
+ padding: 15px;
477
+ }
478
+
479
+ .page-title {
480
+ font-size: 20px;
481
+ }
482
+
483
+ .message-header {
484
+ padding: 12px 15px;
485
+ }
486
+
487
+ .message-body {
488
+ padding: 15px;
489
+ }
490
+
491
+ .message-footer {
492
+ padding: 12px 15px;
493
+ }
494
+ }
495
+
496
+ .message-time {
497
+ font-size: 12px;
498
+ color: var(--text-muted);
499
+ display: flex;
500
+ align-items: center;
501
+ gap: 5px;
502
+ }
503
+
504
+ .seen-status {
505
+ color: var(--text-muted);
506
+ }
507
+
508
+ .seen-status.new {
509
+ color: var(--primary-color);
510
+ font-weight: 500;
511
+ }
512
+
513
+ .navbar .logo-icon {
514
+ width: 40px;
515
+ height: 40px;
516
+ background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
517
+ border-radius: 12px;
518
+ display: flex;
519
+ align-items: center;
520
+ justify-content: center;
521
+ box-shadow: 0 5px 15px rgba(67, 97, 238, 0.2);
522
+ position: relative;
523
+ overflow: hidden;
524
+ margin-left: 10px;
525
+ }
526
+
527
+ .navbar .logo-icon::before {
528
+ content: '';
529
+ position: absolute;
530
+ top: -10px;
531
+ left: -10px;
532
+ right: -10px;
533
+ bottom: -10px;
534
+ background: linear-gradient(135deg, rgba(255,255,255,0.2), rgba(255,255,255,0));
535
+ transform: rotate(35deg);
536
+ }
537
+
538
+ .navbar .logo-icon i {
539
+ color: white;
540
+ font-size: 20px;
541
+ position: relative;
542
+ z-index: 2;
543
+ }
544
+
545
+ .navbar .logo-text h1 {
546
+ font-size: 18px;
547
+ font-weight: 800;
548
+ margin: 0;
549
+ }
550
+
551
+ .navbar .logo-text p {
552
+ font-size: 12px;
553
+ margin: 0;
554
+ }
555
+
556
+ .navbar-brand {
557
+ display: flex;
558
+ align-items: center;
559
+ }
560
+ </style>
561
+ </head>
562
+ <body>
563
+ <!-- Loading Overlay -->
564
+ <div class="loading-overlay" id="loadingOverlay">
565
+ <div class="spinner"></div>
566
+ </div>
567
+
568
+ <!-- Notification Container -->
569
+ <div class="notification-container" id="notificationContainer"></div>
570
+
571
+ <!-- Navbar -->
572
+ <nav class="navbar">
573
+ <div class="navbar-brand">
574
+ <div class="logo-icon">
575
+ <i class="fas fa-robot"></i>
576
+ </div>
577
+ <div class="logo-text">
578
+ <h1>NANO BOT</h1>
579
+ </div>
580
+ </div>
581
+ <div class="navbar-nav">
582
+ <div class="nav-item">
583
+ <a href="{{ url_for('dashboard') }}" class="nav-link">
584
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
585
+ <path d="M4 13h6a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1zm-1 7a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-4a1 1 0 0 0-1-1H4a1 1 0 0 0-1 1v4zm10 0a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-7a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v7zm1-10h6a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1h-6a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1z"/>
586
+ </svg>
587
+ لوحة التحكم
588
+ </a>
589
+ </div>
590
+ <div class="nav-item">
591
+ <a href="{{ url_for('logout') }}" class="nav-link">
592
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
593
+ <path d="M16 13v-2H7V8l-5 4 5 4v-3z"/>
594
+ <path d="M20 3h-9c-1.103 0-2 .897-2 2v4h2V5h9v14h-9v-4H9v4c0 1.103.897 2 2 2h9c1.103 0 2-.897 2-2V5c0-1.103-.897-2-2-2z"/>
595
+ </svg>
596
+ تسجيل الخروج
597
+ </a>
598
+ </div>
599
+ </div>
600
+ </nav>
601
+
602
+ <!-- Main Container -->
603
+ <div class="container">
604
+ <div class="page-header">
605
+ <h1 class="page-title">
606
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
607
+ <path d="M20 4H4c-1.103 0-2 .897-2 2v12c0 1.103.897 2 2 2h16c1.103 0 2-.897 2-2V6c0-1.103-.897-2-2-2zm0 2v.511l-8 6.223-8-6.222V6h16zM4 18V9.044l7.386 5.745a.994.994 0 0 0 1.228 0L20 9.044 20.002 18H4z"/>
608
+ </svg>
609
+ رسائل الإدارة
610
+ </h1>
611
+ <div class="page-actions">
612
+ <button class="btn btn-primary" id="refreshBtn">
613
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
614
+ <path d="M10 11H7.101l.001-.009a4.956 4.956 0 0 1 .752-1.787 5.054 5.054 0 0 1 2.2-1.811c.302-.128.617-.226.938-.291a5.078 5.078 0 0 1 2.018 0 4.978 4.978 0 0 1 2.525 1.361l1.416-1.412a7.036 7.036 0 0 0-2.224-1.501 6.921 6.921 0 0 0-1.315-.408 7.079 7.079 0 0 0-2.819 0 6.94 6.94 0 0 0-1.316.409 7.04 7.04 0 0 0-3.08 2.534 6.978 6.978 0 0 0-1.054 2.505c-.028.135-.043.273-.063.41H2l4 4 4-4zm4 2h2.899l-.001.008a4.976 4.976 0 0 1-2.103 3.138 4.943 4.943 0 0 1-1.787.752 5.073 5.073 0 0 1-2.017 0 4.956 4.956 0 0 1-1.787-.752 5.072 5.072 0 0 1-.74-.61L7.05 16.95a7.032 7.032 0 0 0 2.225 1.5c.424.18.867.317 1.315.408a7.07 7.07 0 0 0 2.818 0 7.031 7.031 0 0 0 4.395-2.945 6.974 6.974 0 0 0 1.053-2.503c.027-.135.043-.273.063-.41H22l-4-4-4 4z"/>
615
+ </svg>
616
+ تحديث
617
+ </button>
618
+ </div>
619
+ </div>
620
+
621
+ {% if messages|length > 0 %}
622
+ <div class="messages-container">
623
+ {% for message in messages %}
624
+ <div class="message-card {% if 'seen' not in message %}unread{% endif %}" data-index="{{ loop.index0 }}">
625
+ <div class="message-header">
626
+ <div class="user-avatar">
627
+ {{ message.full_name[0] }}
628
+ </div>
629
+ <div class="user-info">
630
+ <div class="user-name">{{ message.full_name }}</div>
631
+ <div class="message-time">
632
+ {% if message.timestamp %}
633
+ {% set timestamp = message.timestamp.split('T') %}
634
+ <span>{{ timestamp[0] }} {{ timestamp[1].split('.')[0] }}</span>
635
+ {% if 'seen' in message %}
636
+ <span class="seen-status">• تم القراءة</span>
637
+ {% else %}
638
+ <span class="seen-status new">• جديد</span>
639
+ {% endif %}
640
+ {% else %}
641
+ {% if 'seen' in message %}
642
+ <span>تم القراءة</span>
643
+ {% else %}
644
+ <span>جديد</span>
645
+ {% endif %}
646
+ {% endif %}
647
+ </div>
648
+ </div>
649
+ </div>
650
+ <div class="message-body">
651
+ <div class="message-text">{{ message.message }}</div>
652
+ </div>
653
+ <div class="message-footer">
654
+ <div class="message-actions">
655
+ {% if 'seen' not in message %}
656
+ <button class="btn btn-outline btn-sm mark-seen-btn" data-index="{{ loop.index0 }}">
657
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
658
+ <path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/>
659
+ </svg>
660
+ تعليم كمقروء
661
+ </button>
662
+ {% endif %}
663
+ </div>
664
+ <button class="btn btn-danger btn-sm delete-btn" data-index="{{ loop.index0 }}">
665
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
666
+ <path d="M5 20a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8h2V6h-4V4a2 2 0 0 0-2-2H9a2 2 0 0 0-2 2v2H3v2h2zM9 4h6v2H9zM8 8h9v12H7V8z"/>
667
+ <path d="M9 10h2v8H9zm4 0h2v8h-2z"/>
668
+ </svg>
669
+ حذف
670
+ </button>
671
+ </div>
672
+ </div>
673
+ {% endfor %}
674
+ </div>
675
+ {% else %}
676
+ <div class="empty-state">
677
+ <svg class="empty-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
678
+ <path d="M20 4H4c-1.103 0-2 .897-2 2v12c0 1.103.897 2 2 2h16c1.103 0 2-.897 2-2V6c0-1.103-.897-2-2-2zm0 2v.511l-8 6.223-8-6.222V6h16zM4 18V9.044l7.386 5.745a.994.994 0 0 0 1.228 0L20 9.044 20.002 18H4z"/>
679
+ </svg>
680
+ <h3 class="empty-title">لا توجد رسائل</h3>
681
+ <p class="empty-description">لم يتم العثور على أي رسائل من العملاء في الوقت الحالي.</p>
682
+ <button class="btn btn-primary" id="emptyRefreshBtn">
683
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
684
+ <path d="M10 11H7.101l.001-.009a4.956 4.956 0 0 1 .752-1.787 5.054 5.054 0 0 1 2.2-1.811c.302-.128.617-.226.938-.291a5.078 5.078 0 0 1 2.018 0 4.978 4.978 0 0 1 2.525 1.361l1.416-1.412a7.036 7.036 0 0 0-2.224-1.501 6.921 6.921 0 0 0-1.315-.408 7.079 7.079 0 0 0-2.819 0 6.94 6.94 0 0 0-1.316.409 7.04 7.04 0 0 0-3.08 2.534 6.978 6.978 0 0 0-1.054 2.505c-.028.135-.043.273-.063.41H2l4 4 4-4zm4 2h2.899l-.001.008a4.976 4.976 0 0 1-2.103 3.138 4.943 4.943 0 0 1-1.787.752 5.073 5.073 0 0 1-2.017 0 4.956 4.956 0 0 1-1.787-.752 5.072 5.072 0 0 1-.74-.61L7.05 16.95a7.032 7.032 0 0 0 2.225 1.5c.424.18.867.317 1.315.408a7.07 7.07 0 0 0 2.818 0 7.031 7.031 0 0 0 4.395-2.945 6.974 6.974 0 0 0 1.053-2.503c.027-.135.043-.273.063-.41H22l-4-4-4 4z"/>
685
+ </svg>
686
+ تحديث
687
+ </button>
688
+ </div>
689
+ {% endif %}
690
+ </div>
691
+ <!-- Confirmation Dialog -->
692
+ <div class="confirmation-dialog" id="confirmationDialog">
693
+ <div class="confirmation-content">
694
+ <div class="confirmation-header">
695
+ <h3>تأكيد الحذف</h3>
696
+ <button class="close-btn" id="closeConfirmBtn">&times;</button>
697
+ </div>
698
+ <div class="confirmation-body">
699
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="confirmation-icon">
700
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
701
+ <path d="M13 7h-2v6h2zm0 8h-2v2h2z"/>
702
+ </svg>
703
+ <p>هل أنت متأكد من حذف هذه الرسالة؟</p>
704
+ <p class="confirmation-note">لا يمكن التراجع عن هذا الإجراء.</p>
705
+ </div>
706
+ <div class="confirmation-footer">
707
+ <button class="btn btn-outline" id="cancelDeleteBtn">إلغاء</button>
708
+ <button class="btn btn-danger" id="confirmDeleteBtn">تأكيد الحذف</button>
709
+ </div>
710
+ </div>
711
+ </div>
712
+
713
+ <style>
714
+ /* Confirmation Dialog */
715
+ .confirmation-dialog {
716
+ position: fixed;
717
+ top: 0;
718
+ left: 0;
719
+ right: 0;
720
+ bottom: 0;
721
+ background-color: rgba(0, 0, 0, 0.5);
722
+ display: flex;
723
+ justify-content: center;
724
+ align-items: center;
725
+ z-index: 2000;
726
+ opacity: 0;
727
+ visibility: hidden;
728
+ transition: var(--transition);
729
+ }
730
+
731
+ .confirmation-dialog.active {
732
+ opacity: 1;
733
+ visibility: visible;
734
+ }
735
+
736
+ .confirmation-content {
737
+ background-color: var(--card-bg);
738
+ border-radius: var(--border-radius);
739
+ box-shadow: var(--shadow-lg);
740
+ width: 90%;
741
+ max-width: 400px;
742
+ transform: translateY(-20px);
743
+ transition: transform 0.3s ease;
744
+ }
745
+
746
+ .confirmation-dialog.active .confirmation-content {
747
+ transform: translateY(0);
748
+ }
749
+
750
+ .confirmation-header {
751
+ padding: 15px 20px;
752
+ border-bottom: 1px solid var(--border-color);
753
+ display: flex;
754
+ justify-content: space-between;
755
+ align-items: center;
756
+ }
757
+
758
+ .confirmation-header h3 {
759
+ margin: 0;
760
+ color: var(--danger-color);
761
+ font-weight: 700;
762
+ }
763
+
764
+ .close-btn {
765
+ background: none;
766
+ border: none;
767
+ font-size: 24px;
768
+ cursor: pointer;
769
+ color: var(--text-muted);
770
+ }
771
+
772
+ .confirmation-body {
773
+ padding: 20px;
774
+ text-align: center;
775
+ }
776
+
777
+ .confirmation-icon {
778
+ width: 60px;
779
+ height: 60px;
780
+ margin-bottom: 15px;
781
+ color: var(--danger-color);
782
+ }
783
+
784
+ .confirmation-note {
785
+ font-size: 14px;
786
+ color: var(--text-muted);
787
+ margin-top: 10px;
788
+ }
789
+
790
+ .confirmation-footer {
791
+ padding: 15px 20px;
792
+ border-top: 1px solid var(--border-color);
793
+ display: flex;
794
+ justify-content: flex-end;
795
+ gap: 10px;
796
+ }
797
+ </style>
798
+
799
+ <script>
800
+ // DOM Elements
801
+ const loadingOverlay = document.getElementById('loadingOverlay');
802
+ const notificationContainer = document.getElementById('notificationContainer');
803
+ const refreshBtn = document.getElementById('refreshBtn');
804
+ const emptyRefreshBtn = document.getElementById('emptyRefreshBtn');
805
+ const markSeenBtns = document.querySelectorAll('.mark-seen-btn');
806
+ const deleteBtns = document.querySelectorAll('.delete-btn');
807
+ let confirmationDialog;
808
+ let closeConfirmBtn;
809
+ let cancelDeleteBtn;
810
+ let confirmDeleteBtn;
811
+ let messageToDelete = null;
812
+
813
+ // WebSocket Connection
814
+ let socket;
815
+ let recentActions = new Set(); // Track recent actions to prevent duplicate notifications
816
+
817
+ function connectWebSocket() {
818
+ socket = io.connect(window.location.origin);
819
+
820
+ socket.on('connect', function() {
821
+ console.log('WebSocket connected');
822
+ });
823
+
824
+ socket.on('message_seen', function(data) {
825
+ const actionKey = `seen_${data.page_id}_${data.index}`;
826
+ // Only show notification if this wasn't a local action
827
+ if (!recentActions.has(actionKey)) {
828
+ showNotification('تم تحديث الحالة', 'تم تعليم الرسالة كمقروءة', 'success');
829
+
830
+ // Update UI if needed
831
+ const messageCard = document.querySelector(`.message-card[data-index="${data.index}"]`);
832
+ if (messageCard) {
833
+ messageCard.classList.remove('unread');
834
+ const markSeenBtn = messageCard.querySelector('.mark-seen-btn');
835
+ if (markSeenBtn) {
836
+ markSeenBtn.remove();
837
+ }
838
+ const seenStatus = messageCard.querySelector('.seen-status');
839
+ if (seenStatus) {
840
+ seenStatus.textContent = '• تم القراءة';
841
+ seenStatus.classList.remove('new');
842
+ }
843
+ }
844
+ }
845
+ });
846
+
847
+ socket.on('message_deleted', function(data) {
848
+ const actionKey = `delete_${data.page_id}_${data.index}`;
849
+ // Only show notification if this wasn't a local action
850
+ if (!recentActions.has(actionKey)) {
851
+ showNotification('تم الحذف', 'تم حذف الرسالة بنجاح', 'success');
852
+
853
+ // Remove message card from UI if needed
854
+ const messageCard = document.querySelector(`.message-card[data-index="${data.index}"]`);
855
+ if (messageCard) {
856
+ messageCard.style.opacity = '0';
857
+ messageCard.style.transform = 'translateY(20px)';
858
+ setTimeout(() => {
859
+ messageCard.remove();
860
+
861
+ // Check if there are no more messages
862
+ const remainingMessages = document.querySelectorAll('.message-card');
863
+ if (remainingMessages.length === 0) {
864
+ // Reload the page to show empty state
865
+ window.location.reload();
866
+ }
867
+ }, 300);
868
+ }
869
+ }
870
+ });
871
+
872
+ socket.on('data_refreshed', function(data) {
873
+ const actionKey = `refresh_${data.type}`;
874
+ // Only show notification if this wasn't a local action
875
+ if (!recentActions.has(actionKey)) {
876
+ showNotification('تم التحديث', 'تم تحديث الرسائل بنجاح', 'info');
877
+ setTimeout(() => {
878
+ window.location.reload();
879
+ }, 1000);
880
+ }
881
+ });
882
+ }
883
+
884
+ // Helper function to track recent actions
885
+ function trackAction(actionType, pageId, index) {
886
+ const actionKey = `${actionType}_${pageId}_${index}`;
887
+ recentActions.add(actionKey);
888
+
889
+ // Remove from tracking after 5 seconds
890
+ setTimeout(() => {
891
+ recentActions.delete(actionKey);
892
+ }, 5000);
893
+
894
+ return actionKey;
895
+ }
896
+
897
+ // Initialize
898
+ document.addEventListener('DOMContentLoaded', function() {
899
+ // Connect WebSocket
900
+ connectWebSocket();
901
+
902
+ // Get confirmation dialog elements
903
+ confirmationDialog = document.getElementById('confirmationDialog');
904
+ closeConfirmBtn = document.getElementById('closeConfirmBtn');
905
+ cancelDeleteBtn = document.getElementById('cancelDeleteBtn');
906
+ confirmDeleteBtn = document.getElementById('confirmDeleteBtn');
907
+
908
+ // Set up confirmation dialog buttons
909
+ closeConfirmBtn.addEventListener('click', closeConfirmation);
910
+ cancelDeleteBtn.addEventListener('click', closeConfirmation);
911
+ confirmDeleteBtn.addEventListener('click', function() {
912
+ if (messageToDelete !== null) {
913
+ proceedWithDelete(messageToDelete);
914
+ closeConfirmation();
915
+ }
916
+ });
917
+
918
+ // Refresh Button
919
+ if (refreshBtn) {
920
+ refreshBtn.addEventListener('click', function() {
921
+ refreshMessages();
922
+ });
923
+ }
924
+
925
+ // Empty Refresh Button
926
+ if (emptyRefreshBtn) {
927
+ emptyRefreshBtn.addEventListener('click', function() {
928
+ refreshMessages();
929
+ });
930
+ }
931
+
932
+ // Mark Seen Buttons
933
+ markSeenBtns.forEach(btn => {
934
+ btn.addEventListener('click', function() {
935
+ const index = this.getAttribute('data-index');
936
+ markMessageAsSeen(index);
937
+ });
938
+ });
939
+
940
+ // Delete Buttons
941
+ deleteBtns.forEach(btn => {
942
+ btn.addEventListener('click', function() {
943
+ const index = this.getAttribute('data-index');
944
+ showDeleteConfirmation(index);
945
+ });
946
+ });
947
+ });
948
+
949
+ // Functions
950
+ function showLoading() {
951
+ loadingOverlay.classList.add('active');
952
+ }
953
+
954
+ function hideLoading() {
955
+ loadingOverlay.classList.remove('active');
956
+ }
957
+
958
+ function showNotification(title, message, type = 'info') {
959
+ const notification = document.createElement('div');
960
+ notification.className = `notification ${type}`;
961
+
962
+ let iconSvg;
963
+ if (type === 'success') {
964
+ iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="notification-icon">
965
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
966
+ <path d="M9.999 13.587 7.7 11.292l-1.412 1.416 3.713 3.705 6.706-6.706-1.414-1.414z"/>
967
+ </svg>`;
968
+ } else if (type === 'error') {
969
+ iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="notification-icon">
970
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
971
+ <path d="M13 7h-2v7h2zm0 8h-2v2h2z"/>
972
+ </svg>`;
973
+ } else {
974
+ iconSvg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="notification-icon">
975
+ <path d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"/>
976
+ <path d="M11 11h2v6h-2zm0-4h2v2h-2z"/>
977
+ </svg>`;
978
+ }
979
+
980
+ notification.innerHTML = `
981
+ ${iconSvg}
982
+ <div class="notification-content">
983
+ <div class="notification-title">${title}</div>
984
+ <div class="notification-message">${message}</div>
985
+ </div>
986
+ <button class="notification-close">&times;</button>
987
+ `;
988
+
989
+ notificationContainer.appendChild(notification);
990
+
991
+ // Show notification with animation
992
+ setTimeout(() => {
993
+ notification.classList.add('show');
994
+ }, 10);
995
+
996
+ // Auto close after 5 seconds
997
+ setTimeout(() => {
998
+ closeNotification(notification);
999
+ }, 5000);
1000
+
1001
+ // Close button
1002
+ notification.querySelector('.notification-close').addEventListener('click', function() {
1003
+ closeNotification(notification);
1004
+ });
1005
+ }
1006
+
1007
+ function closeNotification(notification) {
1008
+ notification.classList.remove('show');
1009
+ setTimeout(() => {
1010
+ notification.remove();
1011
+ }, 300);
1012
+ }
1013
+
1014
+ function refreshMessages() {
1015
+ // Track this action to prevent duplicate notifications
1016
+ trackAction('refresh', 'messages', null);
1017
+
1018
+ showLoading();
1019
+
1020
+ fetch('/api/refresh_data', {
1021
+ method: 'POST',
1022
+ headers: {
1023
+ 'Content-Type': 'application/json',
1024
+ },
1025
+ body: JSON.stringify({ type: 'messages' }),
1026
+ })
1027
+ .then(response => response.json())
1028
+ .then(data => {
1029
+ hideLoading();
1030
+ if (data.success) {
1031
+ showNotification('تم التحديث', 'تم تحديث الرسائل بنجاح', 'success');
1032
+ setTimeout(() => {
1033
+ window.location.reload();
1034
+ }, 1500);
1035
+ } else {
1036
+ showNotification('خطأ', data.message, 'error');
1037
+ }
1038
+ })
1039
+ .catch(error => {
1040
+ hideLoading();
1041
+ showNotification('خطأ', 'حدث خطأ أثناء تحديث الرسائل', 'error');
1042
+ console.error('Error:', error);
1043
+ });
1044
+ }
1045
+
1046
+ function markMessageAsSeen(index) {
1047
+ // Ensure index is a number
1048
+ index = parseInt(index, 10);
1049
+
1050
+ // Track this action to prevent duplicate notifications
1051
+ const pageId = '{{ page.page_id }}'; // Get page_id from template
1052
+ trackAction('seen', pageId, index);
1053
+
1054
+ showLoading();
1055
+
1056
+ fetch('/api/mark_message_seen', {
1057
+ method: 'POST',
1058
+ headers: {
1059
+ 'Content-Type': 'application/json',
1060
+ },
1061
+ body: JSON.stringify({ index: index }),
1062
+ })
1063
+ .then(response => response.json())
1064
+ .then(data => {
1065
+ hideLoading();
1066
+ if (data.success) {
1067
+ showNotification('تم التحديث', 'تم تعليم الرسالة كمقروءة', 'success');
1068
+
1069
+ // Update UI
1070
+ const messageCard = document.querySelector(`.message-card[data-index="${index}"]`);
1071
+ if (messageCard) {
1072
+ messageCard.classList.remove('unread'); // Remove unread class
1073
+ const markSeenBtn = messageCard.querySelector('.mark-seen-btn');
1074
+ if (markSeenBtn) {
1075
+ markSeenBtn.remove(); // Remove the "Mark as Seen" button
1076
+ }
1077
+ const seenStatus = messageCard.querySelector('.seen-status');
1078
+ if (seenStatus) {
1079
+ seenStatus.textContent = '• تم القراءة';
1080
+ seenStatus.classList.remove('new');
1081
+ }
1082
+ }
1083
+ } else {
1084
+ showNotification('خطأ', data.message, 'error');
1085
+ }
1086
+ })
1087
+ .catch(error => {
1088
+ hideLoading();
1089
+ showNotification('خطأ', 'حدث خطأ أثناء تعليم الرسالة كمقروءة', 'error');
1090
+ console.error('Error:', error);
1091
+ });
1092
+ }
1093
+
1094
+ function showDeleteConfirmation(index) {
1095
+ messageToDelete = index;
1096
+ confirmationDialog.classList.add('active');
1097
+ // Prevent scrolling on the body
1098
+ document.body.style.overflow = 'hidden';
1099
+ }
1100
+
1101
+ function closeConfirmation() {
1102
+ confirmationDialog.classList.remove('active');
1103
+ // Re-enable scrolling
1104
+ document.body.style.overflow = '';
1105
+ // Reset the message to delete
1106
+ setTimeout(() => {
1107
+ messageToDelete = null;
1108
+ }, 300);
1109
+ }
1110
+
1111
+ function proceedWithDelete(index) {
1112
+ // Track this action to prevent duplicate notifications
1113
+ const pageId = '{{ page.page_id }}'; // Get page_id from template
1114
+ trackAction('delete', pageId, index);
1115
+
1116
+ showLoading();
1117
+
1118
+ fetch('/api/delete_message', {
1119
+ method: 'POST',
1120
+ headers: {
1121
+ 'Content-Type': 'application/json',
1122
+ },
1123
+ body: JSON.stringify({ index: index }),
1124
+ })
1125
+ .then(response => response.json())
1126
+ .then(data => {
1127
+ hideLoading();
1128
+ if (data.success) {
1129
+ showNotification('تم الحذف', 'تم حذف الرسالة بنجاح', 'success');
1130
+
1131
+ // Remove message card from UI
1132
+ const messageCard = document.querySelector(`.message-card[data-index="${index}"]`);
1133
+ if (messageCard) {
1134
+ messageCard.style.opacity = '0';
1135
+ messageCard.style.transform = 'translateY(20px)';
1136
+ setTimeout(() => {
1137
+ messageCard.remove();
1138
+
1139
+ // Check if there are no more messages
1140
+ const remainingMessages = document.querySelectorAll('.message-card');
1141
+ if (remainingMessages.length === 0) {
1142
+ // Reload the page to show empty state
1143
+ window.location.reload();
1144
+ }
1145
+ }, 300);
1146
+ }
1147
+ } else {
1148
+ showNotification('خطأ', data.message, 'error');
1149
+ }
1150
+ })
1151
+ .catch(error => {
1152
+ hideLoading();
1153
+ showNotification('خطأ', 'حدث خطأ أثناء حذف الرسالة', 'error');
1154
+ console.error('Error:', error);
1155
+ });
1156
+ }
1157
+ </script>
1158
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
1159
+ </body>
1160
+ </html>