Autosave: 20260401-210827
This commit is contained in:
parent
0704729e11
commit
195e1589a3
@ -39,7 +39,7 @@ const config = {
|
||||
},
|
||||
uploadDir: os.tmpdir(),
|
||||
email: {
|
||||
from: 'Multi-Client Detergents POS <app@flatlogic.app>',
|
||||
from: 'نظام إدارة المحل ونقطة البيع <app@flatlogic.app>',
|
||||
host: 'email-smtp.us-east-1.amazonaws.com',
|
||||
port: 587,
|
||||
auth: {
|
||||
|
||||
@ -55,8 +55,8 @@ const options = {
|
||||
openapi: "3.0.0",
|
||||
info: {
|
||||
version: "1.0.0",
|
||||
title: "Multi-Client Detergents POS",
|
||||
description: "Multi-Client Detergents POS Online REST API for Testing and Prototyping application. You can perform all major operations with your entities - create, delete and etc.",
|
||||
title: "نظام إدارة المحل ونقطة البيع",
|
||||
description: "واجهة API خاصة بإدارة المحل ونقطة البيع، وتوفّر عمليات الإدارة الأساسية على الكيانات والبيانات.",
|
||||
},
|
||||
servers: [
|
||||
{
|
||||
|
||||
@ -7,30 +7,23 @@ let publicRoleCache = null;
|
||||
|
||||
// Function to asynchronously fetch and cache the 'Public' role
|
||||
async function fetchAndCachePublicRole() {
|
||||
try {
|
||||
// Use RolesDBApi to find the role by name 'Public'
|
||||
publicRoleCache = await RolesDBApi.findBy({ name: 'Public' });
|
||||
try {
|
||||
// Use RolesDBApi to find the role by name 'Public'
|
||||
publicRoleCache = await RolesDBApi.findBy({ name: 'Public' });
|
||||
|
||||
if (!publicRoleCache) {
|
||||
console.error("WARNING: Role 'Public' not found in database during middleware startup. Check your migrations.");
|
||||
// The system might not function correctly without this role. May need to throw an error or use a fallback stub.
|
||||
} else {
|
||||
console.log("'Public' role successfully loaded and cached.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error fetching 'Public' role during middleware startup:", error);
|
||||
// Handle the error during startup fetch
|
||||
throw error; // Important to know if the app can proceed without the Public role
|
||||
if (!publicRoleCache) {
|
||||
console.error("WARNING: لم يتم العثور على دور 'Public' في قاعدة البيانات أثناء تهيئة الصلاحيات.");
|
||||
} else {
|
||||
console.log("تم تحميل دور 'Public' وحفظه في الذاكرة المؤقتة بنجاح.");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("حدث خطأ أثناء تحميل دور 'Public' عند بدء تشغيل وسيط الصلاحيات:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger the role fetching when the check-permissions.js module is imported/loaded
|
||||
// This should happen during application startup when routes are being configured.
|
||||
fetchAndCachePublicRole().catch(error => {
|
||||
// Handle the case where the fetchAndCachePublicRole promise is rejected
|
||||
console.error("Critical error during permissions middleware initialization:", error);
|
||||
// Decide here if the process should exit if the Public role is essential.
|
||||
// process.exit(1);
|
||||
fetchAndCachePublicRole().catch((error) => {
|
||||
console.error('خطأ حرج أثناء تهيئة وسيط الصلاحيات:', error);
|
||||
});
|
||||
|
||||
/**
|
||||
@ -39,85 +32,63 @@ fetchAndCachePublicRole().catch(error => {
|
||||
* @return {import("express").RequestHandler} Express middleware function.
|
||||
*/
|
||||
function checkPermissions(permission) {
|
||||
return async (req, res, next) => {
|
||||
const { currentUser } = req;
|
||||
return async (req, res, next) => {
|
||||
const { currentUser } = req;
|
||||
|
||||
// 1. Check self-access bypass (only if the user is authenticated)
|
||||
if (currentUser && (currentUser.id === req.params.id || currentUser.id === req.body.id)) {
|
||||
return next(); // User has access to their own resource
|
||||
if (currentUser && (currentUser.id === req.params.id || currentUser.id === req.body.id)) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (currentUser) {
|
||||
const customPermissions = Array.isArray(currentUser.custom_permissions)
|
||||
? currentUser.custom_permissions
|
||||
: [];
|
||||
const userPermission = customPermissions.find(
|
||||
(cp) => cp.name === permission,
|
||||
);
|
||||
if (userPermission) {
|
||||
return next();
|
||||
}
|
||||
}
|
||||
|
||||
let effectiveRole = null;
|
||||
try {
|
||||
if (currentUser && currentUser.app_role) {
|
||||
effectiveRole = currentUser.app_role;
|
||||
} else if (!publicRoleCache) {
|
||||
console.error("ذاكرة دور 'Public' فارغة. سيتم إعادة تحميله مباشرةً من قاعدة البيانات.");
|
||||
effectiveRole = await RolesDBApi.findBy({ name: 'Public' });
|
||||
if (!effectiveRole) {
|
||||
return next(new Error('خطأ داخلي: تعذر تحميل دور الوصول العام.'));
|
||||
}
|
||||
} else {
|
||||
effectiveRole = publicRoleCache;
|
||||
}
|
||||
|
||||
// 2. Check Custom Permissions (only if the user is authenticated)
|
||||
if (currentUser) {
|
||||
// Ensure custom_permissions is an array before using find
|
||||
const customPermissions = Array.isArray(currentUser.custom_permissions)
|
||||
? currentUser.custom_permissions
|
||||
: [];
|
||||
const userPermission = customPermissions.find(
|
||||
(cp) => cp.name === permission,
|
||||
);
|
||||
if (userPermission) {
|
||||
return next(); // User has a custom permission
|
||||
}
|
||||
}
|
||||
if (!effectiveRole) {
|
||||
return next(new Error('خطأ داخلي: تعذر تحديد الدور الفعّال للتحقق من الصلاحية.'));
|
||||
}
|
||||
|
||||
// 3. Determine the "effective" role for permission check
|
||||
let effectiveRole = null;
|
||||
try {
|
||||
if (currentUser && currentUser.app_role) {
|
||||
// User is authenticated and has an assigned role
|
||||
effectiveRole = currentUser.app_role;
|
||||
} else {
|
||||
// User is NOT authenticated OR is authenticated but has no role
|
||||
// Use the cached 'Public' role
|
||||
if (!publicRoleCache) {
|
||||
// If the cache is unexpectedly empty (e.g., startup error caught),
|
||||
// we can try fetching the role again synchronously (less ideal) or just deny access.
|
||||
console.error("Public role cache is empty. Attempting synchronous fetch...");
|
||||
// Less efficient fallback option:
|
||||
effectiveRole = await RolesDBApi.findBy({ name: 'Public' }); // Could be slow
|
||||
if (!effectiveRole) {
|
||||
// If even the synchronous attempt failed
|
||||
return next(new Error("Internal Server Error: Public role missing and cannot be fetched."));
|
||||
}
|
||||
} else {
|
||||
effectiveRole = publicRoleCache; // Use the cached object
|
||||
}
|
||||
}
|
||||
let rolePermissions = [];
|
||||
if (typeof effectiveRole.getPermissions === 'function') {
|
||||
rolePermissions = await effectiveRole.getPermissions();
|
||||
} else if (Array.isArray(effectiveRole.permissions)) {
|
||||
rolePermissions = effectiveRole.permissions;
|
||||
} else {
|
||||
console.error('تنسيق كائن الدور غير صالح ولا يحتوي على الصلاحيات المطلوبة:', effectiveRole);
|
||||
return next(new Error('خطأ داخلي: بيانات الدور غير صالحة للتحقق من الصلاحيات.'));
|
||||
}
|
||||
|
||||
// Check if we got a valid role object
|
||||
if (!effectiveRole) {
|
||||
return next(new Error("Internal Server Error: Could not determine effective role."));
|
||||
}
|
||||
|
||||
// 4. Check Permissions on the "effective" role
|
||||
// Assume the effectiveRole object (from app_role or RolesDBApi) has a getPermissions() method
|
||||
// or a 'permissions' property (if permissions are eagerly loaded).
|
||||
let rolePermissions = [];
|
||||
if (typeof effectiveRole.getPermissions === 'function') {
|
||||
rolePermissions = await effectiveRole.getPermissions(); // Get permissions asynchronously if the method exists
|
||||
} else if (Array.isArray(effectiveRole.permissions)) {
|
||||
rolePermissions = effectiveRole.permissions; // Or take from property if permissions are pre-loaded
|
||||
} else {
|
||||
console.error("Role object lacks getPermissions() method or permissions property:", effectiveRole);
|
||||
return next(new Error("Internal Server Error: Invalid role object format."));
|
||||
}
|
||||
|
||||
|
||||
if (rolePermissions.find((p) => p.name === permission)) {
|
||||
next(); // The "effective" role has the required permission
|
||||
} else {
|
||||
// The "effective" role does not have the required permission
|
||||
const roleName = effectiveRole.name || 'unknown role';
|
||||
next(new ValidationError('auth.forbidden', `Role '${roleName}' denied access to '${permission}'.`));
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
// Handle errors during role or permission fetching
|
||||
console.error("Error during permission check:", e);
|
||||
next(e); // Pass the error to the next middleware
|
||||
}
|
||||
};
|
||||
if (rolePermissions.find((p) => p.name === permission)) {
|
||||
next();
|
||||
} else {
|
||||
next(new ValidationError('auth.forbidden', `Role '${effectiveRole.name || 'unknown'}' denied '${permission}'.`));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('حدث خطأ أثناء التحقق من الصلاحيات:', error);
|
||||
next(error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const METHOD_MAP = {
|
||||
@ -134,16 +105,13 @@ const METHOD_MAP = {
|
||||
* @return {import("express").RequestHandler} Express middleware function.
|
||||
*/
|
||||
function checkCrudPermissions(name) {
|
||||
return (req, res, next) => {
|
||||
// Dynamically determine the permission name (e.g., 'READ_USERS')
|
||||
const permissionName = `${METHOD_MAP[req.method]}_${name.toUpperCase()}`;
|
||||
// Call the checkPermissions middleware with the determined permission
|
||||
checkPermissions(permissionName)(req, res, next);
|
||||
};
|
||||
return (req, res, next) => {
|
||||
const permissionName = `${METHOD_MAP[req.method]}_${name.toUpperCase()}`;
|
||||
checkPermissions(permissionName)(req, res, next);
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
checkPermissions,
|
||||
checkCrudPermissions,
|
||||
checkPermissions,
|
||||
checkCrudPermissions,
|
||||
};
|
||||
|
||||
|
||||
@ -13,8 +13,8 @@ const loadRolesModules = () => {
|
||||
RolesDBApi: require('../db/api/roles'),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Roles modules are missing. Advanced roles are required for this endpoint.', error);
|
||||
const err = new Error('Roles modules are missing. Advanced roles are required for this endpoint.');
|
||||
console.error('تعذر تحميل وحدات الأدوار المطلوبة لهذا المسار.', error);
|
||||
const err = new Error('تعذر تحميل وحدات الأدوار المطلوبة لهذا المسار.');
|
||||
err.originalError = error;
|
||||
throw err;
|
||||
}
|
||||
@ -310,7 +310,7 @@ router.post(
|
||||
if (!prompt) {
|
||||
return res.status(400).send({
|
||||
success: false,
|
||||
error: 'Prompt is required',
|
||||
error: 'النص المطلوب للذكاء الاصطناعي فارغ',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ router.get('/image', async (req, res) => {
|
||||
const data = await response.json();
|
||||
res.status(200).json(data.photos[0]);
|
||||
} catch (error) {
|
||||
res.status(200).json({ error: 'Failed to fetch image' });
|
||||
res.status(200).json({ error: 'تعذر جلب الصورة' });
|
||||
}
|
||||
});
|
||||
|
||||
@ -37,7 +37,7 @@ router.get('/video', async (req, res) => {
|
||||
const data = await response.json();
|
||||
res.status(200).json(data.videos[0]);
|
||||
} catch (error) {
|
||||
res.status(200).json({ error: 'Failed to fetch video' });
|
||||
res.status(200).json({ error: 'تعذر جلب الفيديو' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -41,15 +41,15 @@ router.post('/', async (req, res) => {
|
||||
const globalAccess = req.currentUser.app_role.globalAccess;
|
||||
|
||||
if (!searchQuery) {
|
||||
return res.status(400).json({ error: 'Please enter a search query' });
|
||||
return res.status(400).json({ error: 'يرجى إدخال عبارة للبحث' });
|
||||
}
|
||||
|
||||
try {
|
||||
const foundMatches = await SearchService.search(searchQuery, req.currentUser , organizationId, globalAccess,);
|
||||
res.json(foundMatches);
|
||||
} catch (error) {
|
||||
console.error('Internal Server Error', error);
|
||||
res.status(500).json({ error: 'Internal Server Error' });
|
||||
console.error('حدث خطأ داخلي في البحث', error);
|
||||
res.status(500).json({ error: 'حدث خطأ داخلي أثناء تنفيذ البحث' });
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -38,16 +38,16 @@ router.post(
|
||||
wrapAsync(async (req, res) => {
|
||||
const { sql } = req.body;
|
||||
if (typeof sql !== 'string' || !sql.trim()) {
|
||||
return res.status(400).json({ error: 'SQL is required' });
|
||||
return res.status(400).json({ error: 'يرجى إدخال استعلام SQL' });
|
||||
}
|
||||
|
||||
const normalized = sql.trim().replace(/;+\s*$/, '');
|
||||
if (!/^select\b/i.test(normalized)) {
|
||||
return res.status(400).json({ error: 'Only SELECT statements are allowed' });
|
||||
return res.status(400).json({ error: 'يسمح فقط باستعلامات SELECT' });
|
||||
}
|
||||
|
||||
if (normalized.includes(';')) {
|
||||
return res.status(400).json({ error: 'Only a single SELECT statement is allowed' });
|
||||
return res.status(400).json({ error: 'يسمح باستعلام SELECT واحد فقط في كل طلب' });
|
||||
}
|
||||
|
||||
const rows = await db.sequelize.query(normalized, {
|
||||
|
||||
@ -2,7 +2,7 @@ const formidable = require('formidable');
|
||||
const fs = require('fs');
|
||||
const config = require('../config');
|
||||
const path = require('path');
|
||||
const { format } = require("util");
|
||||
const { format } = require('util');
|
||||
|
||||
const ensureDirectoryExistence = (filePath) => {
|
||||
const dirname = path.dirname(filePath);
|
||||
@ -13,7 +13,7 @@ const ensureDirectoryExistence = (filePath) => {
|
||||
|
||||
ensureDirectoryExistence(dirname);
|
||||
fs.mkdirSync(dirname);
|
||||
}
|
||||
};
|
||||
|
||||
const uploadLocal = (
|
||||
folder,
|
||||
@ -29,9 +29,7 @@ const uploadLocal = (
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
validations.entity
|
||||
) {
|
||||
if (validations.entity) {
|
||||
res.sendStatus(403);
|
||||
return;
|
||||
}
|
||||
@ -63,7 +61,7 @@ const uploadLocal = (
|
||||
|
||||
if (!filename) {
|
||||
fs.unlinkSync(fileTempUrl);
|
||||
res.sendStatus(500);
|
||||
res.status(500).send({ message: 'تعذر تحديد اسم الملف المطلوب رفعه' });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -80,59 +78,57 @@ const uploadLocal = (
|
||||
form.on('error', function (err) {
|
||||
res.status(500).send(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const downloadLocal = async (req, res) => {
|
||||
const privateUrl = req.query.privateUrl;
|
||||
if (!privateUrl) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
res.download(path.join(config.uploadDir, privateUrl));
|
||||
}
|
||||
const privateUrl = req.query.privateUrl;
|
||||
if (!privateUrl) {
|
||||
return res.sendStatus(404);
|
||||
}
|
||||
res.download(path.join(config.uploadDir, privateUrl));
|
||||
};
|
||||
|
||||
const initGCloud = () => {
|
||||
const processFile = require("../middlewares/upload");
|
||||
const { Storage } = require("@google-cloud/storage");
|
||||
const processFile = require('../middlewares/upload');
|
||||
const { Storage } = require('@google-cloud/storage');
|
||||
|
||||
const crypto = require('crypto')
|
||||
const hash = config.gcloud.hash
|
||||
|
||||
const privateKey = process.env.GC_PRIVATE_KEY.replace(/\\\n/g, "\n");
|
||||
const hash = config.gcloud.hash;
|
||||
const privateKey = process.env.GC_PRIVATE_KEY.replace(/\\\n/g, '\n');
|
||||
|
||||
const storage = new Storage({
|
||||
projectId: process.env.GC_PROJECT_ID,
|
||||
credentials: {
|
||||
client_email: process.env.GC_CLIENT_EMAIL,
|
||||
private_key: privateKey
|
||||
}
|
||||
projectId: process.env.GC_PROJECT_ID,
|
||||
credentials: {
|
||||
client_email: process.env.GC_CLIENT_EMAIL,
|
||||
private_key: privateKey,
|
||||
},
|
||||
});
|
||||
|
||||
const bucket = storage.bucket(config.gcloud.bucket);
|
||||
return {hash, bucket, processFile};
|
||||
}
|
||||
return { hash, bucket, processFile };
|
||||
};
|
||||
|
||||
const uploadGCloud = async (folder, req, res) => {
|
||||
try {
|
||||
const {hash, bucket, processFile} = initGCloud();
|
||||
const { hash, bucket, processFile } = initGCloud();
|
||||
await processFile(req, res);
|
||||
let buffer = await req.file.buffer;
|
||||
let filename = await req.body.filename;
|
||||
|
||||
if (!req.file) {
|
||||
return res.status(400).send({ message: "Please upload a file!" });
|
||||
return res.status(400).send({ message: 'يرجى اختيار ملف للرفع' });
|
||||
}
|
||||
|
||||
let path = `${hash}/${folder}/${filename}`;
|
||||
let blob = bucket.file(path);
|
||||
const buffer = req.file.buffer;
|
||||
const filename = req.body.filename;
|
||||
const filePath = `${hash}/${folder}/${filename}`;
|
||||
const blob = bucket.file(filePath);
|
||||
|
||||
console.log(path);
|
||||
console.log(filePath);
|
||||
|
||||
const blobStream = blob.createWriteStream({
|
||||
resumable: false,
|
||||
});
|
||||
|
||||
blobStream.on("error", (err) => {
|
||||
blobStream.on('error', (err) => {
|
||||
console.log('Upload error');
|
||||
console.log(err.message);
|
||||
res.status(500).send({ message: err.message });
|
||||
@ -140,58 +136,58 @@ const uploadGCloud = async (folder, req, res) => {
|
||||
|
||||
console.log(`https://storage.googleapis.com/${bucket.name}/${blob.name}`);
|
||||
|
||||
blobStream.on("finish", async (data) => {
|
||||
blobStream.on('finish', async () => {
|
||||
const publicUrl = format(
|
||||
`https://storage.googleapis.com/${bucket.name}/${blob.name}`
|
||||
`https://storage.googleapis.com/${bucket.name}/${blob.name}`,
|
||||
);
|
||||
|
||||
res.status(200).send({
|
||||
message: "Uploaded the file successfully: " + path,
|
||||
message: `تم رفع الملف بنجاح: ${filePath}`,
|
||||
url: publicUrl,
|
||||
});
|
||||
});
|
||||
|
||||
blobStream.end(buffer)
|
||||
blobStream.end(buffer);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
|
||||
res.status(500).send({
|
||||
message: `Could not upload the file. ${err}`
|
||||
message: `تعذر رفع الملف. ${err}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const downloadGCloud = async (req, res) => {
|
||||
try {
|
||||
const {hash, bucket, processFile} = initGCloud();
|
||||
const { hash, bucket } = initGCloud();
|
||||
|
||||
const privateUrl = await req.query.privateUrl;
|
||||
const privateUrl = req.query.privateUrl;
|
||||
const filePath = `${hash}/${privateUrl}`;
|
||||
const file = bucket.file(filePath)
|
||||
const file = bucket.file(filePath);
|
||||
const fileExists = await file.exists();
|
||||
|
||||
if (fileExists[0]) {
|
||||
const stream = file.createReadStream();
|
||||
stream.pipe(res);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
res.status(404).send({
|
||||
message: "Could not download the file. " + err,
|
||||
});
|
||||
}
|
||||
|
||||
res.status(404).send({
|
||||
message: 'تعذر العثور على الملف المطلوب تنزيله',
|
||||
});
|
||||
} catch (err) {
|
||||
res.status(404).send({
|
||||
message: "Could not download the file. " + err,
|
||||
message: 'تعذر تنزيل الملف.',
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const deleteGCloud = async (privateUrl) => {
|
||||
try {
|
||||
const {hash, bucket, processFile} = initGCloud();
|
||||
const { hash, bucket } = initGCloud();
|
||||
const filePath = `${hash}/${privateUrl}`;
|
||||
|
||||
const file = bucket.file(filePath)
|
||||
const file = bucket.file(filePath);
|
||||
const fileExists = await file.exists();
|
||||
|
||||
if (fileExists[0]) {
|
||||
@ -200,7 +196,7 @@ const deleteGCloud = async (privateUrl) => {
|
||||
} catch (err) {
|
||||
console.log(`Cannot find the file ${privateUrl}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
initGCloud,
|
||||
@ -208,6 +204,5 @@ module.exports = {
|
||||
downloadLocal,
|
||||
deleteGCloud,
|
||||
uploadGCloud,
|
||||
downloadGCloud
|
||||
}
|
||||
|
||||
downloadGCloud,
|
||||
};
|
||||
|
||||
@ -1,101 +1,96 @@
|
||||
const errors = {
|
||||
app: {
|
||||
title: 'Multi-Client Detergents POS',
|
||||
title: 'نظام إدارة المحل ونقطة البيع',
|
||||
},
|
||||
|
||||
auth: {
|
||||
userDisabled: 'Your account is disabled',
|
||||
forbidden: 'Forbidden',
|
||||
unauthorized: 'Unauthorized',
|
||||
userNotFound: `Sorry, we don't recognize your credentials`,
|
||||
wrongPassword: `Sorry, we don't recognize your credentials`,
|
||||
weakPassword: 'This password is too weak',
|
||||
emailAlreadyInUse: 'Email is already in use',
|
||||
invalidEmail: 'Please provide a valid email',
|
||||
userDisabled: 'تم تعطيل هذا الحساب',
|
||||
forbidden: 'ليس لديك صلاحية لتنفيذ هذا الإجراء',
|
||||
unauthorized: 'يجب تسجيل الدخول أولاً',
|
||||
userNotFound: 'البريد الإلكتروني أو كلمة المرور غير صحيحة',
|
||||
wrongPassword: 'البريد الإلكتروني أو كلمة المرور غير صحيحة',
|
||||
weakPassword: 'كلمة المرور ضعيفة جدًا',
|
||||
emailAlreadyInUse: 'هذا البريد الإلكتروني مستخدم بالفعل',
|
||||
invalidEmail: 'يرجى إدخال بريد إلكتروني صحيح',
|
||||
passwordReset: {
|
||||
invalidToken:
|
||||
'Password reset link is invalid or has expired',
|
||||
error: `Email not recognized`,
|
||||
invalidToken: 'رابط إعادة تعيين كلمة المرور غير صالح أو منتهي الصلاحية',
|
||||
error: 'هذا البريد الإلكتروني غير مسجل في النظام',
|
||||
},
|
||||
passwordUpdate: {
|
||||
samePassword: `You can't use the same password. Please create new password`
|
||||
samePassword: 'لا يمكن استخدام كلمة المرور الحالية نفسها. اختر كلمة مرور جديدة',
|
||||
},
|
||||
userNotVerified: `Sorry, your email has not been verified yet`,
|
||||
userNotVerified: 'لم يتم تأكيد البريد الإلكتروني لهذا الحساب بعد',
|
||||
emailAddressVerificationEmail: {
|
||||
invalidToken:
|
||||
'Email verification link is invalid or has expired',
|
||||
error: `Email not recognized`,
|
||||
invalidToken: 'رابط تأكيد البريد الإلكتروني غير صالح أو منتهي الصلاحية',
|
||||
error: 'هذا البريد الإلكتروني غير مسجل في النظام',
|
||||
},
|
||||
},
|
||||
|
||||
iam: {
|
||||
errors: {
|
||||
userAlreadyExists:
|
||||
'User with this email already exists',
|
||||
userNotFound: 'User not found',
|
||||
disablingHimself: `You can't disable yourself`,
|
||||
revokingOwnPermission: `You can't revoke your own owner permission`,
|
||||
deletingHimself: `You can't delete yourself`,
|
||||
emailRequired: 'Email is required',
|
||||
userAlreadyExists: 'يوجد مستخدم بهذا البريد الإلكتروني بالفعل',
|
||||
userNotFound: 'المستخدم غير موجود',
|
||||
disablingHimself: 'لا يمكنك تعطيل حسابك الحالي',
|
||||
revokingOwnPermission: 'لا يمكنك إزالة صلاحية المالك من حسابك الحالي',
|
||||
deletingHimself: 'لا يمكنك حذف حسابك الحالي',
|
||||
emailRequired: 'البريد الإلكتروني مطلوب',
|
||||
},
|
||||
},
|
||||
|
||||
importer: {
|
||||
errors: {
|
||||
invalidFileEmpty: 'The file is empty',
|
||||
invalidFileExcel:
|
||||
'Only excel (.xlsx) files are allowed',
|
||||
invalidFileUpload:
|
||||
'Invalid file. Make sure you are using the last version of the template.',
|
||||
importHashRequired: 'Import hash is required',
|
||||
importHashExistent: 'Data has already been imported',
|
||||
userEmailMissing: 'Some items in the CSV do not have an email',
|
||||
invalidFileEmpty: 'الملف فارغ',
|
||||
invalidFileExcel: 'يسمح فقط بملفات Excel بصيغة .xlsx',
|
||||
invalidFileUpload: 'الملف غير صالح. تأكد من استخدام آخر نسخة من القالب المعتمد.',
|
||||
importHashRequired: 'معرّف الاستيراد مطلوب',
|
||||
importHashExistent: 'تم استيراد هذه البيانات مسبقًا',
|
||||
userEmailMissing: 'بعض الصفوف في ملف CSV لا تحتوي على بريد إلكتروني',
|
||||
},
|
||||
},
|
||||
|
||||
errors: {
|
||||
forbidden: {
|
||||
message: 'Forbidden',
|
||||
message: 'ليس لديك صلاحية للوصول',
|
||||
},
|
||||
validation: {
|
||||
message: 'An error occurred',
|
||||
message: 'حدث خطأ في التحقق من البيانات',
|
||||
},
|
||||
searchQueryRequired: {
|
||||
message: 'Search query is required',
|
||||
message: 'يرجى إدخال عبارة البحث',
|
||||
},
|
||||
},
|
||||
|
||||
emails: {
|
||||
invitation: {
|
||||
subject: `You've been invited to {0}`,
|
||||
body: `
|
||||
<p>Hello,</p>
|
||||
<p>You've been invited to {0} set password for your {1} account.</p>
|
||||
subject: 'تمت دعوتك إلى {0}',
|
||||
body: `
|
||||
<p>مرحبًا،</p>
|
||||
<p>تمت دعوتك إلى {0}. يرجى تعيين كلمة المرور لحسابك في {1}.</p>
|
||||
<p><a href='{2}'>{2}</a></p>
|
||||
<p>Thanks,</p>
|
||||
<p>Your {0} team</p>
|
||||
<p>شكرًا لك،</p>
|
||||
<p>فريق {0}</p>
|
||||
`,
|
||||
},
|
||||
emailAddressVerification: {
|
||||
subject: `Verify your email for {0}`,
|
||||
subject: 'تأكيد البريد الإلكتروني لـ {0}',
|
||||
body: `
|
||||
<p>Hello,</p>
|
||||
<p>Follow this link to verify your email address.</p>
|
||||
<p>مرحبًا،</p>
|
||||
<p>استخدم هذا الرابط لتأكيد عنوان بريدك الإلكتروني.</p>
|
||||
<p><a href='{0}'>{0}</a></p>
|
||||
<p>If you didn't ask to verify this address, you can ignore this email.</p>
|
||||
<p>Thanks,</p>
|
||||
<p>Your {1} team</p>
|
||||
<p>إذا لم تطلب هذا الإجراء، يمكنك تجاهل هذه الرسالة.</p>
|
||||
<p>شكرًا لك،</p>
|
||||
<p>فريق {1}</p>
|
||||
`,
|
||||
},
|
||||
passwordReset: {
|
||||
subject: `Reset your password for {0}`,
|
||||
subject: 'إعادة تعيين كلمة المرور لـ {0}',
|
||||
body: `
|
||||
<p>Hello,</p>
|
||||
<p>Follow this link to reset your {0} password for your {1} account.</p>
|
||||
<p>مرحبًا،</p>
|
||||
<p>استخدم هذا الرابط لإعادة تعيين كلمة المرور الخاصة بك في {0} لحساب {1}.</p>
|
||||
<p><a href='{2}'>{2}</a></p>
|
||||
<p>If you didn't ask to reset your password, you can ignore this email.</p>
|
||||
<p>Thanks,</p>
|
||||
<p>Your {0} team</p>
|
||||
<p>إذا لم تطلب إعادة التعيين، يمكنك تجاهل هذه الرسالة.</p>
|
||||
<p>شكرًا لك،</p>
|
||||
<p>فريق {0}</p>
|
||||
`,
|
||||
},
|
||||
},
|
||||
|
||||
@ -6,8 +6,8 @@ const loadRoleService = () => {
|
||||
try {
|
||||
return require('./roles');
|
||||
} catch (error) {
|
||||
console.error('Role service is missing. Advanced roles are required for this operation.', error);
|
||||
const err = new Error('Role service is missing. Advanced roles are required for this operation.');
|
||||
console.error('تعذر تحميل خدمة الأدوار المطلوبة لهذه العملية.', error);
|
||||
const err = new Error('تعذر تحميل خدمة الأدوار المطلوبة لهذه العملية.');
|
||||
err.originalError = error;
|
||||
throw err;
|
||||
}
|
||||
@ -25,17 +25,17 @@ module.exports = class OpenAiService {
|
||||
const { widget_id } = await response.data;
|
||||
await RoleService.addRoleInfo(roleId, userId, 'widgets', widget_id);
|
||||
return widget_id;
|
||||
} else {
|
||||
console.error('=======error=======', response.data);
|
||||
return { value: null, error: response.data };
|
||||
}
|
||||
|
||||
console.error('Widget generation failed:', response.data);
|
||||
return { value: null, error: response.data };
|
||||
}
|
||||
|
||||
static async askGpt(prompt) {
|
||||
if (!prompt) {
|
||||
return {
|
||||
success: false,
|
||||
error: 'Prompt is required'
|
||||
error: 'النص المطلوب للذكاء الاصطناعي فارغ',
|
||||
};
|
||||
}
|
||||
|
||||
@ -59,7 +59,7 @@ module.exports = class OpenAiService {
|
||||
console.error('AI JSON decode failed:', error);
|
||||
return {
|
||||
success: false,
|
||||
error: 'AI response parsing failed',
|
||||
error: 'تعذر قراءة رد الذكاء الاصطناعي',
|
||||
details: error.message || String(error),
|
||||
};
|
||||
}
|
||||
@ -73,7 +73,7 @@ module.exports = class OpenAiService {
|
||||
console.error('AI proxy error:', response);
|
||||
return {
|
||||
success: false,
|
||||
error: response.error || response.message || 'AI proxy error',
|
||||
error: response.error || response.message || 'حدث خطأ أثناء التواصل مع خدمة الذكاء الاصطناعي',
|
||||
response,
|
||||
};
|
||||
}
|
||||
|
||||
2
frontend/next-env.d.ts
vendored
2
frontend/next-env.d.ts
vendored
@ -1,6 +1,6 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference path="./build/types/routes.d.ts" />
|
||||
/// <reference path="./.next/types/routes.d.ts" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.
|
||||
|
||||
@ -63,13 +63,13 @@ const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
|
||||
)
|
||||
|
||||
const componentClass = [
|
||||
'flex cursor-pointer py-1.5 ',
|
||||
'flex cursor-pointer py-1.5 font-medium transition-all duration-200 ease-out',
|
||||
isDropdownList ? 'px-6 text-sm' : '',
|
||||
item.color
|
||||
? getButtonColor(item.color, false, true)
|
||||
: `${asideMenuItemStyle}`,
|
||||
isLinkActive
|
||||
? `text-black ${activeLinkColor} dark:text-white dark:bg-dark-800`
|
||||
? `text-black ${activeLinkColor} shadow-sm dark:text-white dark:bg-dark-800`
|
||||
: '',
|
||||
].join(' ');
|
||||
|
||||
|
||||
@ -56,17 +56,17 @@ export default function AsideMenuLayer({ menu, className = '', ...props }: Props
|
||||
return (
|
||||
<aside
|
||||
id='asideMenu'
|
||||
className={`${className} zzz lg:py-2 lg:pl-2 w-60 fixed flex z-40 top-0 h-screen transition-position overflow-hidden`}
|
||||
className={`${className} zzz lg:py-2 lg:pl-2 w-60 fixed top-0 z-40 flex h-screen overflow-hidden transition-all duration-300 ease-out`}
|
||||
>
|
||||
<div
|
||||
className={`flex-1 flex flex-col overflow-hidden dark:bg-dark-900 ${asideStyle} ${corners}`}
|
||||
className={`flex flex-1 flex-col overflow-hidden border border-slate-200/70 shadow-sm transition-all duration-300 ease-out dark:bg-dark-900 dark:border-dark-700 ${asideStyle} ${corners}`}
|
||||
>
|
||||
<div
|
||||
className={`flex flex-row h-14 items-center justify-between ${asideBrandStyle}`}
|
||||
>
|
||||
<div className="text-center flex-1 lg:text-left lg:pl-6 xl:text-center xl:pl-0">
|
||||
|
||||
<b className="font-black">Multi-Client Detergents POS</b>
|
||||
<b className="font-black tracking-[0.01em]">Multi-Client Detergents POS</b>
|
||||
|
||||
|
||||
{organizationName && <p>{organizationName}</p>}
|
||||
|
||||
@ -48,10 +48,13 @@ export default function BaseButton({
|
||||
'justify-center',
|
||||
'items-center',
|
||||
'whitespace-nowrap',
|
||||
'font-semibold',
|
||||
'tracking-[0.01em]',
|
||||
'focus:outline-none',
|
||||
'transition-colors',
|
||||
'transition-all',
|
||||
'duration-200',
|
||||
'ease-out',
|
||||
'focus:ring',
|
||||
'duration-150',
|
||||
'border',
|
||||
disabled ? 'cursor-not-allowed' : 'cursor-pointer',
|
||||
roundedFull ? 'rounded-full' : `${corners}`,
|
||||
@ -60,7 +63,7 @@ export default function BaseButton({
|
||||
]
|
||||
|
||||
if (!label && icon) {
|
||||
componentClass.push('p-1')
|
||||
componentClass.push('p-1.5')
|
||||
} else if (small) {
|
||||
componentClass.push('text-sm', roundedFull ? 'px-3 py-1' : 'p-1')
|
||||
} else {
|
||||
@ -69,6 +72,8 @@ export default function BaseButton({
|
||||
|
||||
if (disabled) {
|
||||
componentClass.push(outline ? 'opacity-50' : 'opacity-70')
|
||||
} else {
|
||||
componentClass.push('hover:-translate-y-px', 'hover:shadow-sm', 'active:translate-y-0')
|
||||
}
|
||||
|
||||
const componentClassString = componentClass.join(' ')
|
||||
|
||||
@ -37,16 +37,16 @@ export default function CardBox({
|
||||
const corners = useAppSelector((state) => state.style.corners);
|
||||
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
|
||||
const componentClass = [
|
||||
`flex dark:border-dark-700 dark:bg-dark-900`,
|
||||
`flex dark:border-dark-700 dark:bg-dark-900 transition-all duration-300 ease-out motion-reduce:transition-none`,
|
||||
className,
|
||||
corners !== 'rounded-full'? corners : 'rounded-3xl',
|
||||
flex,
|
||||
isList ? '' : `${cardsStyle}`,
|
||||
hasTable ? '' : `border-dark-700 dark:border-dark-700`,
|
||||
hasTable ? '' : `border-dark-700 dark:border-dark-700`,
|
||||
]
|
||||
|
||||
if (isHoverable) {
|
||||
componentClass.push('hover:shadow-lg transition-shadow duration-500')
|
||||
componentClass.push('hover:-translate-y-0.5 hover:shadow-lg')
|
||||
}
|
||||
|
||||
return React.createElement(
|
||||
|
||||
@ -35,9 +35,9 @@ export default function NavBar({ menu, className = '', children }: Props) {
|
||||
|
||||
return (
|
||||
<nav
|
||||
className={`${className} top-0 inset-x-0 fixed ${bgColor} h-14 z-30 transition-position w-screen lg:w-auto dark:bg-dark-800`}
|
||||
className={`${className} top-0 inset-x-0 fixed ${bgColor} h-14 z-30 w-screen transition-all duration-300 ease-out backdrop-blur-sm lg:w-auto dark:bg-dark-800`}
|
||||
>
|
||||
<div className={`flex lg:items-stretch ${containerMaxW} ${isScrolled && `border-b border-pavitra-400 dark:border-dark-700`}`}>
|
||||
<div className={`flex lg:items-stretch ${containerMaxW} ${isScrolled ? 'border-b border-pavitra-400/70 shadow-sm shadow-slate-200/60 dark:border-dark-700 dark:shadow-none' : ''}`}>
|
||||
<div className="flex flex-1 items-stretch h-14">{children}</div>
|
||||
<div className="flex-none items-stretch flex h-14 lg:hidden">
|
||||
<NavBarItemPlain onClick={handleMenuNavBarToggleClick}>
|
||||
@ -47,7 +47,7 @@ export default function NavBar({ menu, className = '', children }: Props) {
|
||||
<div
|
||||
className={`${
|
||||
isMenuNavBarActive ? 'block' : 'hidden'
|
||||
} flex items-center max-h-screen-menu overflow-y-auto lg:overflow-visible absolute w-screen top-14 left-0 ${bgColor} shadow-lg lg:w-auto lg:flex lg:static lg:shadow-none dark:bg-dark-800`}
|
||||
} absolute left-0 top-14 flex max-h-screen-menu w-screen items-center overflow-y-auto ${bgColor} shadow-lg transition-all duration-300 ease-out lg:static lg:w-auto lg:flex lg:overflow-visible lg:shadow-none dark:bg-dark-800`}
|
||||
>
|
||||
<NavBarMenuList menu={menu} />
|
||||
</div>
|
||||
|
||||
@ -17,7 +17,7 @@ export default function NavBarItemPlain({
|
||||
const navBarItemLabelStyle = useAppSelector((state) => state.style.navBarItemLabelStyle)
|
||||
const navBarItemLabelHoverStyle = useAppSelector((state) => state.style.navBarItemLabelHoverStyle)
|
||||
|
||||
const classBase = 'items-center cursor-pointer dark:text-white dark:hover:text-slate-400'
|
||||
const classBase = 'items-center cursor-pointer font-medium transition-colors duration-200 ease-out dark:text-white dark:hover:text-slate-400'
|
||||
const classAddon = `${display} ${navBarItemLabelStyle} ${navBarItemLabelHoverStyle} ${
|
||||
useMargin ? 'my-2 mx-3' : 'py-2 px-3'
|
||||
}`
|
||||
|
||||
@ -93,7 +93,7 @@ const CardOrganizations = ({
|
||||
))}
|
||||
{!loading && organizations.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</ul>
|
||||
|
||||
@ -70,7 +70,7 @@ const ListOrganizations = ({ organizations, loading, onDelete, currentPage, numP
|
||||
))}
|
||||
{!loading && organizations.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -395,12 +395,12 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col">
|
||||
<div className=" text-gray-500 font-bold">Action</div>
|
||||
<div className=" text-gray-500 font-bold">إجراء</div>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
type='reset'
|
||||
color='danger'
|
||||
label='Delete'
|
||||
label='حذف'
|
||||
onClick={() => {
|
||||
deleteFilter(filterItem.id)
|
||||
}}
|
||||
@ -413,13 +413,13 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
|
||||
<BaseButton
|
||||
className="my-2 mr-3"
|
||||
color="success"
|
||||
label='Apply'
|
||||
label='تطبيق'
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
color='info'
|
||||
label='Cancel'
|
||||
label='إلغاء'
|
||||
onClick={handleReset}
|
||||
/>
|
||||
</div>
|
||||
@ -429,14 +429,14 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
|
||||
</CardBox> : null
|
||||
}
|
||||
<CardBoxModal
|
||||
title="Please confirm"
|
||||
title="تأكيد العملية"
|
||||
buttonColor="info"
|
||||
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
|
||||
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
|
||||
isActive={isModalTrashActive}
|
||||
onConfirm={handleDeleteAction}
|
||||
onCancel={handleModalAction}
|
||||
>
|
||||
<p>Are you sure you want to delete this item?</p>
|
||||
<p>هل أنت متأكد من حذف هذا العنصر؟</p>
|
||||
</CardBoxModal>
|
||||
|
||||
|
||||
@ -450,7 +450,7 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
|
||||
<BaseButton
|
||||
className='me-4'
|
||||
color='danger'
|
||||
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
|
||||
label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
|
||||
onClick={() => onDeleteRows(selectedRows)}
|
||||
/>,
|
||||
document.getElementById('delete-rows-button'),
|
||||
|
||||
@ -93,7 +93,7 @@ const CardPermissions = ({
|
||||
))}
|
||||
{!loading && permissions.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</ul>
|
||||
|
||||
@ -70,7 +70,7 @@ const ListPermissions = ({ permissions, loading, onDelete, currentPage, numPages
|
||||
))}
|
||||
{!loading && permissions.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -395,12 +395,12 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col">
|
||||
<div className=" text-gray-500 font-bold">Action</div>
|
||||
<div className=" text-gray-500 font-bold">إجراء</div>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
type='reset'
|
||||
color='danger'
|
||||
label='Delete'
|
||||
label='حذف'
|
||||
onClick={() => {
|
||||
deleteFilter(filterItem.id)
|
||||
}}
|
||||
@ -413,13 +413,13 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
|
||||
<BaseButton
|
||||
className="my-2 mr-3"
|
||||
color="success"
|
||||
label='Apply'
|
||||
label='تطبيق'
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
color='info'
|
||||
label='Cancel'
|
||||
label='إلغاء'
|
||||
onClick={handleReset}
|
||||
/>
|
||||
</div>
|
||||
@ -429,14 +429,14 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
|
||||
</CardBox> : null
|
||||
}
|
||||
<CardBoxModal
|
||||
title="Please confirm"
|
||||
title="تأكيد العملية"
|
||||
buttonColor="info"
|
||||
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
|
||||
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
|
||||
isActive={isModalTrashActive}
|
||||
onConfirm={handleDeleteAction}
|
||||
onCancel={handleModalAction}
|
||||
>
|
||||
<p>Are you sure you want to delete this item?</p>
|
||||
<p>هل أنت متأكد من حذف هذا العنصر؟</p>
|
||||
</CardBoxModal>
|
||||
|
||||
|
||||
@ -450,7 +450,7 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
|
||||
<BaseButton
|
||||
className='me-4'
|
||||
color='danger'
|
||||
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
|
||||
label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
|
||||
onClick={() => onDeleteRows(selectedRows)}
|
||||
/>,
|
||||
document.getElementById('delete-rows-button'),
|
||||
|
||||
@ -165,7 +165,7 @@ const CardPrice_change_logs = ({
|
||||
))}
|
||||
{!loading && price_change_logs.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</ul>
|
||||
|
||||
@ -118,7 +118,7 @@ const ListPrice_change_logs = ({ price_change_logs, loading, onDelete, currentPa
|
||||
))}
|
||||
{!loading && price_change_logs.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -395,12 +395,12 @@ const TableSamplePrice_change_logs = ({ filterItems, setFilterItems, filters, sh
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col">
|
||||
<div className=" text-gray-500 font-bold">Action</div>
|
||||
<div className=" text-gray-500 font-bold">إجراء</div>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
type='reset'
|
||||
color='danger'
|
||||
label='Delete'
|
||||
label='حذف'
|
||||
onClick={() => {
|
||||
deleteFilter(filterItem.id)
|
||||
}}
|
||||
@ -413,13 +413,13 @@ const TableSamplePrice_change_logs = ({ filterItems, setFilterItems, filters, sh
|
||||
<BaseButton
|
||||
className="my-2 mr-3"
|
||||
color="success"
|
||||
label='Apply'
|
||||
label='تطبيق'
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
color='info'
|
||||
label='Cancel'
|
||||
label='إلغاء'
|
||||
onClick={handleReset}
|
||||
/>
|
||||
</div>
|
||||
@ -429,14 +429,14 @@ const TableSamplePrice_change_logs = ({ filterItems, setFilterItems, filters, sh
|
||||
</CardBox> : null
|
||||
}
|
||||
<CardBoxModal
|
||||
title="Please confirm"
|
||||
title="تأكيد العملية"
|
||||
buttonColor="info"
|
||||
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
|
||||
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
|
||||
isActive={isModalTrashActive}
|
||||
onConfirm={handleDeleteAction}
|
||||
onCancel={handleModalAction}
|
||||
>
|
||||
<p>Are you sure you want to delete this item?</p>
|
||||
<p>هل أنت متأكد من حذف هذا العنصر؟</p>
|
||||
</CardBoxModal>
|
||||
|
||||
|
||||
@ -450,7 +450,7 @@ const TableSamplePrice_change_logs = ({ filterItems, setFilterItems, filters, sh
|
||||
<BaseButton
|
||||
className='me-4'
|
||||
color='danger'
|
||||
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
|
||||
label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
|
||||
onClick={() => onDeleteRows(selectedRows)}
|
||||
/>,
|
||||
document.getElementById('delete-rows-button'),
|
||||
|
||||
@ -117,7 +117,7 @@ const CardRoles = ({
|
||||
))}
|
||||
{!loading && roles.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</ul>
|
||||
|
||||
@ -86,7 +86,7 @@ const ListRoles = ({ roles, loading, onDelete, currentPage, numPages, onPageChan
|
||||
))}
|
||||
{!loading && roles.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -395,12 +395,12 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col">
|
||||
<div className=" text-gray-500 font-bold">Action</div>
|
||||
<div className=" text-gray-500 font-bold">إجراء</div>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
type='reset'
|
||||
color='danger'
|
||||
label='Delete'
|
||||
label='حذف'
|
||||
onClick={() => {
|
||||
deleteFilter(filterItem.id)
|
||||
}}
|
||||
@ -413,13 +413,13 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
|
||||
<BaseButton
|
||||
className="my-2 mr-3"
|
||||
color="success"
|
||||
label='Apply'
|
||||
label='تطبيق'
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
color='info'
|
||||
label='Cancel'
|
||||
label='إلغاء'
|
||||
onClick={handleReset}
|
||||
/>
|
||||
</div>
|
||||
@ -429,14 +429,14 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
|
||||
</CardBox> : null
|
||||
}
|
||||
<CardBoxModal
|
||||
title="Please confirm"
|
||||
title="تأكيد العملية"
|
||||
buttonColor="info"
|
||||
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
|
||||
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
|
||||
isActive={isModalTrashActive}
|
||||
onConfirm={handleDeleteAction}
|
||||
onCancel={handleModalAction}
|
||||
>
|
||||
<p>Are you sure you want to delete this item?</p>
|
||||
<p>هل أنت متأكد من حذف هذا العنصر؟</p>
|
||||
</CardBoxModal>
|
||||
|
||||
|
||||
@ -450,7 +450,7 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
|
||||
<BaseButton
|
||||
className='me-4'
|
||||
color='danger'
|
||||
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
|
||||
label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
|
||||
onClick={() => onDeleteRows(selectedRows)}
|
||||
/>,
|
||||
document.getElementById('delete-rows-button'),
|
||||
|
||||
@ -177,7 +177,7 @@ const CardSales_invoice_items = ({
|
||||
))}
|
||||
{!loading && sales_invoice_items.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</ul>
|
||||
|
||||
@ -126,7 +126,7 @@ const ListSales_invoice_items = ({ sales_invoice_items, loading, onDelete, curre
|
||||
))}
|
||||
{!loading && sales_invoice_items.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -395,12 +395,12 @@ const TableSampleSales_invoice_items = ({ filterItems, setFilterItems, filters,
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col">
|
||||
<div className=" text-gray-500 font-bold">Action</div>
|
||||
<div className=" text-gray-500 font-bold">إجراء</div>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
type='reset'
|
||||
color='danger'
|
||||
label='Delete'
|
||||
label='حذف'
|
||||
onClick={() => {
|
||||
deleteFilter(filterItem.id)
|
||||
}}
|
||||
@ -413,13 +413,13 @@ const TableSampleSales_invoice_items = ({ filterItems, setFilterItems, filters,
|
||||
<BaseButton
|
||||
className="my-2 mr-3"
|
||||
color="success"
|
||||
label='Apply'
|
||||
label='تطبيق'
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
color='info'
|
||||
label='Cancel'
|
||||
label='إلغاء'
|
||||
onClick={handleReset}
|
||||
/>
|
||||
</div>
|
||||
@ -429,14 +429,14 @@ const TableSampleSales_invoice_items = ({ filterItems, setFilterItems, filters,
|
||||
</CardBox> : null
|
||||
}
|
||||
<CardBoxModal
|
||||
title="Please confirm"
|
||||
title="تأكيد العملية"
|
||||
buttonColor="info"
|
||||
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
|
||||
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
|
||||
isActive={isModalTrashActive}
|
||||
onConfirm={handleDeleteAction}
|
||||
onCancel={handleModalAction}
|
||||
>
|
||||
<p>Are you sure you want to delete this item?</p>
|
||||
<p>هل أنت متأكد من حذف هذا العنصر؟</p>
|
||||
</CardBoxModal>
|
||||
|
||||
|
||||
@ -450,7 +450,7 @@ const TableSampleSales_invoice_items = ({ filterItems, setFilterItems, filters,
|
||||
<BaseButton
|
||||
className='me-4'
|
||||
color='danger'
|
||||
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
|
||||
label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
|
||||
onClick={() => onDeleteRows(selectedRows)}
|
||||
/>,
|
||||
document.getElementById('delete-rows-button'),
|
||||
|
||||
@ -37,7 +37,7 @@ const Search = () => {
|
||||
name='search'
|
||||
validate={validateSearch}
|
||||
placeholder='ابحث عن صفحة أو عنصر' dir='rtl'
|
||||
className={` ${corners} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-2 relative ml-2 w-full dark:placeholder-dark-600 ${focusRing} shadow-none`}
|
||||
className={`${corners} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 relative ml-2 w-full p-2.5 text-sm font-medium shadow-none transition-all duration-200 ease-out placeholder:font-normal dark:placeholder-dark-600 ${focusRing}`}
|
||||
/>
|
||||
{errors.search && touched.search && values.search.length < 2 ? (
|
||||
<div className='text-red-500 text-sm ml-2 absolute'>{errors.search}</div>
|
||||
|
||||
@ -202,7 +202,7 @@ const CardUsers = ({
|
||||
))}
|
||||
{!loading && users.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</ul>
|
||||
|
||||
@ -145,7 +145,7 @@ const ListUsers = ({ users, loading, onDelete, currentPage, numPages, onPageChan
|
||||
))}
|
||||
{!loading && users.length === 0 && (
|
||||
<div className='col-span-full flex items-center justify-center h-40'>
|
||||
<p className=''>No data to display</p>
|
||||
<p className=''>لا توجد بيانات للعرض</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -395,12 +395,12 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col">
|
||||
<div className=" text-gray-500 font-bold">Action</div>
|
||||
<div className=" text-gray-500 font-bold">إجراء</div>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
type='reset'
|
||||
color='danger'
|
||||
label='Delete'
|
||||
label='حذف'
|
||||
onClick={() => {
|
||||
deleteFilter(filterItem.id)
|
||||
}}
|
||||
@ -413,13 +413,13 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
|
||||
<BaseButton
|
||||
className="my-2 mr-3"
|
||||
color="success"
|
||||
label='Apply'
|
||||
label='تطبيق'
|
||||
onClick={handleSubmit}
|
||||
/>
|
||||
<BaseButton
|
||||
className="my-2"
|
||||
color='info'
|
||||
label='Cancel'
|
||||
label='إلغاء'
|
||||
onClick={handleReset}
|
||||
/>
|
||||
</div>
|
||||
@ -429,14 +429,14 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
|
||||
</CardBox> : null
|
||||
}
|
||||
<CardBoxModal
|
||||
title="Please confirm"
|
||||
title="تأكيد العملية"
|
||||
buttonColor="info"
|
||||
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
|
||||
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
|
||||
isActive={isModalTrashActive}
|
||||
onConfirm={handleDeleteAction}
|
||||
onCancel={handleModalAction}
|
||||
>
|
||||
<p>Are you sure you want to delete this item?</p>
|
||||
<p>هل أنت متأكد من حذف هذا العنصر؟</p>
|
||||
</CardBoxModal>
|
||||
|
||||
|
||||
@ -450,7 +450,7 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
|
||||
<BaseButton
|
||||
className='me-4'
|
||||
color='danger'
|
||||
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
|
||||
label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
|
||||
onClick={() => onDeleteRows(selectedRows)}
|
||||
/>,
|
||||
document.getElementById('delete-rows-button'),
|
||||
|
||||
@ -35,14 +35,57 @@
|
||||
@apply bg-transparent border border-blue-600 text-blue-600 !important;
|
||||
}
|
||||
|
||||
:root {
|
||||
--app-font-primary: 'Tajawal', 'Segoe UI', Tahoma, Arial, sans-serif;
|
||||
--app-transition-fast: 180ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||
--app-transition-base: 260ms cubic-bezier(0.22, 1, 0.36, 1);
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
html, body {
|
||||
font-family: 'Tajawal', 'Segoe UI', Tahoma, Arial, sans-serif;
|
||||
font-family: var(--app-font-primary);
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
body {
|
||||
text-rendering: optimizeLegibility;
|
||||
}
|
||||
|
||||
body,
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
a,
|
||||
button,
|
||||
input,
|
||||
select,
|
||||
textarea {
|
||||
transition:
|
||||
color var(--app-transition-fast),
|
||||
background-color var(--app-transition-fast),
|
||||
border-color var(--app-transition-fast),
|
||||
box-shadow var(--app-transition-fast),
|
||||
opacity var(--app-transition-fast),
|
||||
transform var(--app-transition-fast);
|
||||
}
|
||||
|
||||
.app-rtl {
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
|
||||
@ -109,10 +109,10 @@ const EditOrganizations = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit organizations')}</title>
|
||||
<title>{getPageTitle('تعديل منظمة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit organizations'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل منظمة'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -164,9 +164,9 @@ const EditOrganizations = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/organizations/organizations-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/organizations/organizations-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -106,10 +106,10 @@ const EditOrganizationsPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit organizations')}</title>
|
||||
<title>{getPageTitle('تعديل منظمة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit organizations'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل منظمة'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -161,9 +161,9 @@ const EditOrganizationsPage = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/organizations/organizations-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/organizations/organizations-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -86,28 +86,28 @@ const OrganizationsTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Organizations')}</title>
|
||||
<title>{getPageTitle('المنظمات')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Organizations" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المنظمات" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/organizations/organizations-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/organizations/organizations-new'} color='info' label='إضافة منظمة'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getOrganizationsCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getOrganizationsCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -62,10 +62,10 @@ const OrganizationsNew = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('New Item')}</title>
|
||||
<title>{getPageTitle('إضافة منظمة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة منظمة" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -116,9 +116,9 @@ const OrganizationsNew = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/organizations/organizations-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/organizations/organizations-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -86,28 +86,28 @@ const OrganizationsTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Organizations')}</title>
|
||||
<title>{getPageTitle('المنظمات')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Organizations" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المنظمات" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/organizations/organizations-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/organizations/organizations-new'} color='info' label='إضافة منظمة'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getOrganizationsCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getOrganizationsCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -33,11 +33,6 @@ const OrganizationsView = () => {
|
||||
|
||||
const { id } = router.query;
|
||||
|
||||
function removeLastCharacter(str) {
|
||||
console.log(str,`str`)
|
||||
return str.slice(0, -1);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetch({ id }));
|
||||
}, [dispatch, id]);
|
||||
@ -46,13 +41,13 @@ const OrganizationsView = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('View organizations')}</title>
|
||||
<title>{getPageTitle('عرض منظمة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View organizations')} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض منظمة" main>
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Edit'
|
||||
label='تعديل'
|
||||
href={`/organizations/organizations-edit/?id=${id}`}
|
||||
/>
|
||||
</SectionTitleLineWithButton>
|
||||
|
||||
@ -109,10 +109,10 @@ const EditPermissions = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit permissions')}</title>
|
||||
<title>{getPageTitle('تعديل صلاحية')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit permissions'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل صلاحية'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -164,9 +164,9 @@ const EditPermissions = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/permissions/permissions-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/permissions/permissions-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -106,10 +106,10 @@ const EditPermissionsPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit permissions')}</title>
|
||||
<title>{getPageTitle('تعديل صلاحية')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit permissions'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل صلاحية'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -161,9 +161,9 @@ const EditPermissionsPage = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/permissions/permissions-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/permissions/permissions-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -86,28 +86,28 @@ const PermissionsTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Permissions')}</title>
|
||||
<title>{getPageTitle('الصلاحيات')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Permissions" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الصلاحيات" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/permissions/permissions-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/permissions/permissions-new'} color='info' label='إضافة صلاحية'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getPermissionsCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getPermissionsCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -62,10 +62,10 @@ const PermissionsNew = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('New Item')}</title>
|
||||
<title>{getPageTitle('إضافة صلاحية')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة صلاحية" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -116,9 +116,9 @@ const PermissionsNew = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/permissions/permissions-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/permissions/permissions-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -86,28 +86,28 @@ const PermissionsTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Permissions')}</title>
|
||||
<title>{getPageTitle('الصلاحيات')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Permissions" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الصلاحيات" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/permissions/permissions-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/permissions/permissions-new'} color='info' label='إضافة صلاحية'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getPermissionsCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getPermissionsCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -33,11 +33,6 @@ const PermissionsView = () => {
|
||||
|
||||
const { id } = router.query;
|
||||
|
||||
function removeLastCharacter(str) {
|
||||
console.log(str,`str`)
|
||||
return str.slice(0, -1);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetch({ id }));
|
||||
}, [dispatch, id]);
|
||||
@ -46,13 +41,13 @@ const PermissionsView = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('View permissions')}</title>
|
||||
<title>{getPageTitle('عرض صلاحية')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View permissions')} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض صلاحية" main>
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Edit'
|
||||
label='تعديل'
|
||||
href={`/permissions/permissions-edit/?id=${id}`}
|
||||
/>
|
||||
</SectionTitleLineWithButton>
|
||||
|
||||
@ -305,10 +305,10 @@ const EditPrice_change_logs = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit price_change_logs')}</title>
|
||||
<title>{getPageTitle('تعديل سجل تغيير السعر')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit price_change_logs'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل سجل تغيير السعر'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -706,9 +706,9 @@ const EditPrice_change_logs = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -302,10 +302,10 @@ const EditPrice_change_logsPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit price_change_logs')}</title>
|
||||
<title>{getPageTitle('تعديل سجل تغيير السعر')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit price_change_logs'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل سجل تغيير السعر'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -703,9 +703,9 @@ const EditPrice_change_logsPage = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -94,28 +94,28 @@ const Price_change_logsTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Price_change_logs')}</title>
|
||||
<title>{getPageTitle('سجلات تغيير السعر')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Price_change_logs" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="سجلات تغيير السعر" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/price_change_logs/price_change_logs-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/price_change_logs/price_change_logs-new'} color='info' label='إضافة سجل تغيير السعر'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getPrice_change_logsCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getPrice_change_logsCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -175,10 +175,10 @@ const Price_change_logsNew = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('New Item')}</title>
|
||||
<title>{getPageTitle('إضافة سجل تغيير السعر')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة سجل تغيير السعر" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -460,9 +460,9 @@ const Price_change_logsNew = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -94,28 +94,28 @@ const Price_change_logsTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Price_change_logs')}</title>
|
||||
<title>{getPageTitle('سجلات تغيير السعر')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Price_change_logs" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="سجلات تغيير السعر" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/price_change_logs/price_change_logs-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/price_change_logs/price_change_logs-new'} color='info' label='إضافة سجل تغيير السعر'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getPrice_change_logsCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getPrice_change_logsCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -33,11 +33,6 @@ const Price_change_logsView = () => {
|
||||
|
||||
const { id } = router.query;
|
||||
|
||||
function removeLastCharacter(str) {
|
||||
console.log(str,`str`)
|
||||
return str.slice(0, -1);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetch({ id }));
|
||||
}, [dispatch, id]);
|
||||
@ -46,13 +41,13 @@ const Price_change_logsView = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('View price_change_logs')}</title>
|
||||
<title>{getPageTitle('عرض سجل تغيير السعر')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View price_change_logs')} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض سجل تغيير السعر" main>
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Edit'
|
||||
label='تعديل'
|
||||
href={`/price_change_logs/price_change_logs-edit/?id=${id}`}
|
||||
/>
|
||||
</SectionTitleLineWithButton>
|
||||
|
||||
@ -165,10 +165,10 @@ const EditRoles = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit roles')}</title>
|
||||
<title>{getPageTitle('تعديل دور')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit roles'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل دور'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -317,9 +317,9 @@ const EditRoles = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/roles/roles-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/roles/roles-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -162,10 +162,10 @@ const EditRolesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit roles')}</title>
|
||||
<title>{getPageTitle('تعديل دور')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit roles'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل دور'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -314,9 +314,9 @@ const EditRolesPage = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/roles/roles-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/roles/roles-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -86,28 +86,28 @@ const RolesTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Roles')}</title>
|
||||
<title>{getPageTitle('الأدوار')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Roles" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الأدوار" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/roles/roles-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/roles/roles-new'} color='info' label='إضافة دور'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getRolesCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getRolesCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -94,10 +94,10 @@ const RolesNew = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('New Item')}</title>
|
||||
<title>{getPageTitle('إضافة دور')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة دور" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -218,9 +218,9 @@ const RolesNew = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/roles/roles-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/roles/roles-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -86,28 +86,28 @@ const RolesTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Roles')}</title>
|
||||
<title>{getPageTitle('الأدوار')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Roles" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الأدوار" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/roles/roles-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/roles/roles-new'} color='info' label='إضافة دور'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getRolesCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getRolesCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -33,11 +33,6 @@ const RolesView = () => {
|
||||
|
||||
const { id } = router.query;
|
||||
|
||||
function removeLastCharacter(str) {
|
||||
console.log(str,`str`)
|
||||
return str.slice(0, -1);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetch({ id }));
|
||||
}, [dispatch, id]);
|
||||
@ -46,13 +41,13 @@ const RolesView = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('View roles')}</title>
|
||||
<title>{getPageTitle('عرض دور')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View roles')} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض دور" main>
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Edit'
|
||||
label='تعديل'
|
||||
href={`/roles/roles-edit/?id=${id}`}
|
||||
/>
|
||||
</SectionTitleLineWithButton>
|
||||
|
||||
@ -333,10 +333,10 @@ const EditSales_invoice_items = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit sales_invoice_items')}</title>
|
||||
<title>{getPageTitle('تعديل بند الفاتورة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit sales_invoice_items'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل بند الفاتورة'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -770,9 +770,9 @@ const EditSales_invoice_items = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -330,10 +330,10 @@ const EditSales_invoice_itemsPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit sales_invoice_items')}</title>
|
||||
<title>{getPageTitle('تعديل بند الفاتورة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit sales_invoice_items'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل بند الفاتورة'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -767,9 +767,9 @@ const EditSales_invoice_itemsPage = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -94,28 +94,28 @@ const Sales_invoice_itemsTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Sales_invoice_items')}</title>
|
||||
<title>{getPageTitle('بنود الفاتورة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Sales_invoice_items" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="بنود الفاتورة" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/sales_invoice_items/sales_invoice_items-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/sales_invoice_items/sales_invoice_items-new'} color='info' label='إضافة بند الفاتورة'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getSales_invoice_itemsCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getSales_invoice_itemsCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -190,10 +190,10 @@ const Sales_invoice_itemsNew = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('New Item')}</title>
|
||||
<title>{getPageTitle('إضافة بند الفاتورة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة بند الفاتورة" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -514,9 +514,9 @@ const Sales_invoice_itemsNew = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -94,28 +94,28 @@ const Sales_invoice_itemsTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Sales_invoice_items')}</title>
|
||||
<title>{getPageTitle('بنود الفاتورة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Sales_invoice_items" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="بنود الفاتورة" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/sales_invoice_items/sales_invoice_items-new'} color='info' label='New Item'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/sales_invoice_items/sales_invoice_items-new'} color='info' label='إضافة بند الفاتورة'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getSales_invoice_itemsCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getSales_invoice_itemsCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -33,11 +33,6 @@ const Sales_invoice_itemsView = () => {
|
||||
|
||||
const { id } = router.query;
|
||||
|
||||
function removeLastCharacter(str) {
|
||||
console.log(str,`str`)
|
||||
return str.slice(0, -1);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetch({ id }));
|
||||
}, [dispatch, id]);
|
||||
@ -46,13 +41,13 @@ const Sales_invoice_itemsView = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('View sales_invoice_items')}</title>
|
||||
<title>{getPageTitle('عرض بند الفاتورة')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View sales_invoice_items')} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض بند الفاتورة" main>
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Edit'
|
||||
label='تعديل'
|
||||
href={`/sales_invoice_items/sales_invoice_items-edit/?id=${id}`}
|
||||
/>
|
||||
</SectionTitleLineWithButton>
|
||||
|
||||
@ -335,10 +335,10 @@ const EditUsers = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit users')}</title>
|
||||
<title>{getPageTitle('تعديل مستخدم')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit users'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل مستخدم'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -779,9 +779,9 @@ const EditUsers = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/users/users-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/users/users-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -332,10 +332,10 @@ const EditUsersPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Edit users')}</title>
|
||||
<title>{getPageTitle('تعديل مستخدم')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit users'} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل مستخدم'} main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -776,9 +776,9 @@ const EditUsersPage = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/users/users-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/users/users-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -92,28 +92,28 @@ const UsersTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Users')}</title>
|
||||
<title>{getPageTitle('المستخدمون')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Users" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المستخدمون" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox id="usersList" className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/users/users-new'} color='info' label='Add/Invite User'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/users/users-new'} color='info' label='إضافة مستخدم'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getUsersCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getUsersCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -190,10 +190,10 @@ const UsersNew = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('New Item')}</title>
|
||||
<title>{getPageTitle('إضافة مستخدم')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة مستخدم" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox>
|
||||
@ -521,9 +521,9 @@ const UsersNew = () => {
|
||||
|
||||
<BaseDivider />
|
||||
<BaseButtons>
|
||||
<BaseButton type="submit" color="info" label="Submit" />
|
||||
<BaseButton type="reset" color="info" outline label="Reset" />
|
||||
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/users/users-list')}/>
|
||||
<BaseButton type="submit" color="info" label="حفظ" />
|
||||
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
|
||||
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/users/users-list')}/>
|
||||
</BaseButtons>
|
||||
</Form>
|
||||
</Formik>
|
||||
|
||||
@ -92,28 +92,28 @@ const UsersTablesPage = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('Users')}</title>
|
||||
<title>{getPageTitle('المستخدمون')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Users" main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المستخدمون" main>
|
||||
{''}
|
||||
</SectionTitleLineWithButton>
|
||||
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
|
||||
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/users/users-new'} color='info' label='Add/Invite User'/>}
|
||||
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/users/users-new'} color='info' label='إضافة مستخدم'/>}
|
||||
|
||||
<BaseButton
|
||||
className={'mr-3'}
|
||||
color='info'
|
||||
label='Filter'
|
||||
label='تصفية'
|
||||
onClick={addFilter}
|
||||
/>
|
||||
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getUsersCSV} />
|
||||
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getUsersCSV} />
|
||||
|
||||
{hasCreatePermission && (
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Upload CSV'
|
||||
label='رفع CSV'
|
||||
onClick={() => setIsModalActive(true)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -33,11 +33,6 @@ const UsersView = () => {
|
||||
|
||||
const { id } = router.query;
|
||||
|
||||
function removeLastCharacter(str) {
|
||||
console.log(str,`str`)
|
||||
return str.slice(0, -1);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetch({ id }));
|
||||
}, [dispatch, id]);
|
||||
@ -46,13 +41,13 @@ const UsersView = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>{getPageTitle('View users')}</title>
|
||||
<title>{getPageTitle('عرض مستخدم')}</title>
|
||||
</Head>
|
||||
<SectionMain>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View users')} main>
|
||||
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض مستخدم" main>
|
||||
<BaseButton
|
||||
color='info'
|
||||
label='Edit'
|
||||
label='تعديل'
|
||||
href={`/users/users-edit/?id=${id}`}
|
||||
/>
|
||||
</SectionTitleLineWithButton>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user