Autosave: 20260401-210827

This commit is contained in:
Flatlogic Bot 2026-04-01 21:08:28 +00:00
parent 0704729e11
commit 195e1589a3
73 changed files with 499 additions and 523 deletions

View File

@ -39,7 +39,7 @@ const config = {
}, },
uploadDir: os.tmpdir(), uploadDir: os.tmpdir(),
email: { email: {
from: 'Multi-Client Detergents POS <app@flatlogic.app>', from: 'نظام إدارة المحل ونقطة البيع <app@flatlogic.app>',
host: 'email-smtp.us-east-1.amazonaws.com', host: 'email-smtp.us-east-1.amazonaws.com',
port: 587, port: 587,
auth: { auth: {

View File

@ -55,8 +55,8 @@ const options = {
openapi: "3.0.0", openapi: "3.0.0",
info: { info: {
version: "1.0.0", version: "1.0.0",
title: "Multi-Client Detergents POS", title: "نظام إدارة المحل ونقطة البيع",
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.", description: "واجهة API خاصة بإدارة المحل ونقطة البيع، وتوفّر عمليات الإدارة الأساسية على الكيانات والبيانات.",
}, },
servers: [ servers: [
{ {

View File

@ -7,30 +7,23 @@ let publicRoleCache = null;
// Function to asynchronously fetch and cache the 'Public' role // Function to asynchronously fetch and cache the 'Public' role
async function fetchAndCachePublicRole() { async function fetchAndCachePublicRole() {
try { try {
// Use RolesDBApi to find the role by name 'Public' // Use RolesDBApi to find the role by name 'Public'
publicRoleCache = await RolesDBApi.findBy({ name: 'Public' }); publicRoleCache = await RolesDBApi.findBy({ name: 'Public' });
if (!publicRoleCache) { if (!publicRoleCache) {
console.error("WARNING: Role 'Public' not found in database during middleware startup. Check your migrations."); console.error("WARNING: لم يتم العثور على دور 'Public' في قاعدة البيانات أثناء تهيئة الصلاحيات.");
// The system might not function correctly without this role. May need to throw an error or use a fallback stub. } else {
} else { console.log("تم تحميل دور 'Public' وحفظه في الذاكرة المؤقتة بنجاح.");
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
} }
} catch (error) {
console.error("حدث خطأ أثناء تحميل دور 'Public' عند بدء تشغيل وسيط الصلاحيات:", error);
throw error;
}
} }
// Trigger the role fetching when the check-permissions.js module is imported/loaded fetchAndCachePublicRole().catch((error) => {
// This should happen during application startup when routes are being configured. console.error('خطأ حرج أثناء تهيئة وسيط الصلاحيات:', error);
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);
}); });
/** /**
@ -39,85 +32,63 @@ fetchAndCachePublicRole().catch(error => {
* @return {import("express").RequestHandler} Express middleware function. * @return {import("express").RequestHandler} Express middleware function.
*/ */
function checkPermissions(permission) { function checkPermissions(permission) {
return async (req, res, next) => { return async (req, res, next) => {
const { currentUser } = req; 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)) {
if (currentUser && (currentUser.id === req.params.id || currentUser.id === req.body.id)) { return next();
return next(); // User has access to their own resource }
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 (!effectiveRole) {
if (currentUser) { return next(new Error('خطأ داخلي: تعذر تحديد الدور الفعّال للتحقق من الصلاحية.'));
// 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
}
}
// 3. Determine the "effective" role for permission check let rolePermissions = [];
let effectiveRole = null; if (typeof effectiveRole.getPermissions === 'function') {
try { rolePermissions = await effectiveRole.getPermissions();
if (currentUser && currentUser.app_role) { } else if (Array.isArray(effectiveRole.permissions)) {
// User is authenticated and has an assigned role rolePermissions = effectiveRole.permissions;
effectiveRole = currentUser.app_role; } else {
} else { console.error('تنسيق كائن الدور غير صالح ولا يحتوي على الصلاحيات المطلوبة:', effectiveRole);
// User is NOT authenticated OR is authenticated but has no role return next(new Error('خطأ داخلي: بيانات الدور غير صالحة للتحقق من الصلاحيات.'));
// 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
}
}
// Check if we got a valid role object if (rolePermissions.find((p) => p.name === permission)) {
if (!effectiveRole) { next();
return next(new Error("Internal Server Error: Could not determine effective role.")); } else {
} next(new ValidationError('auth.forbidden', `Role '${effectiveRole.name || 'unknown'}' denied '${permission}'.`));
}
// 4. Check Permissions on the "effective" role } catch (error) {
// Assume the effectiveRole object (from app_role or RolesDBApi) has a getPermissions() method console.error('حدث خطأ أثناء التحقق من الصلاحيات:', error);
// or a 'permissions' property (if permissions are eagerly loaded). next(error);
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
}
};
} }
const METHOD_MAP = { const METHOD_MAP = {
@ -134,16 +105,13 @@ const METHOD_MAP = {
* @return {import("express").RequestHandler} Express middleware function. * @return {import("express").RequestHandler} Express middleware function.
*/ */
function checkCrudPermissions(name) { function checkCrudPermissions(name) {
return (req, res, next) => { return (req, res, next) => {
// Dynamically determine the permission name (e.g., 'READ_USERS') const permissionName = `${METHOD_MAP[req.method]}_${name.toUpperCase()}`;
const permissionName = `${METHOD_MAP[req.method]}_${name.toUpperCase()}`; checkPermissions(permissionName)(req, res, next);
// Call the checkPermissions middleware with the determined permission };
checkPermissions(permissionName)(req, res, next);
};
} }
module.exports = { module.exports = {
checkPermissions, checkPermissions,
checkCrudPermissions, checkCrudPermissions,
}; };

View File

@ -13,8 +13,8 @@ const loadRolesModules = () => {
RolesDBApi: require('../db/api/roles'), RolesDBApi: require('../db/api/roles'),
}; };
} catch (error) { } catch (error) {
console.error('Roles modules are missing. Advanced roles are required for this endpoint.', error); console.error('تعذر تحميل وحدات الأدوار المطلوبة لهذا المسار.', error);
const err = new Error('Roles modules are missing. Advanced roles are required for this endpoint.'); const err = new Error('تعذر تحميل وحدات الأدوار المطلوبة لهذا المسار.');
err.originalError = error; err.originalError = error;
throw err; throw err;
} }
@ -310,7 +310,7 @@ router.post(
if (!prompt) { if (!prompt) {
return res.status(400).send({ return res.status(400).send({
success: false, success: false,
error: 'Prompt is required', error: 'النص المطلوب للذكاء الاصطناعي فارغ',
}); });
} }

View File

@ -19,7 +19,7 @@ router.get('/image', async (req, res) => {
const data = await response.json(); const data = await response.json();
res.status(200).json(data.photos[0]); res.status(200).json(data.photos[0]);
} catch (error) { } 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(); const data = await response.json();
res.status(200).json(data.videos[0]); res.status(200).json(data.videos[0]);
} catch (error) { } catch (error) {
res.status(200).json({ error: 'Failed to fetch video' }); res.status(200).json({ error: 'تعذر جلب الفيديو' });
} }
}); });

View File

@ -41,15 +41,15 @@ router.post('/', async (req, res) => {
const globalAccess = req.currentUser.app_role.globalAccess; const globalAccess = req.currentUser.app_role.globalAccess;
if (!searchQuery) { if (!searchQuery) {
return res.status(400).json({ error: 'Please enter a search query' }); return res.status(400).json({ error: 'يرجى إدخال عبارة للبحث' });
} }
try { try {
const foundMatches = await SearchService.search(searchQuery, req.currentUser , organizationId, globalAccess,); const foundMatches = await SearchService.search(searchQuery, req.currentUser , organizationId, globalAccess,);
res.json(foundMatches); res.json(foundMatches);
} catch (error) { } catch (error) {
console.error('Internal Server Error', error); console.error('حدث خطأ داخلي في البحث', error);
res.status(500).json({ error: 'Internal Server Error' }); res.status(500).json({ error: 'حدث خطأ داخلي أثناء تنفيذ البحث' });
} }
}); });

View File

@ -38,16 +38,16 @@ router.post(
wrapAsync(async (req, res) => { wrapAsync(async (req, res) => {
const { sql } = req.body; const { sql } = req.body;
if (typeof sql !== 'string' || !sql.trim()) { 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*$/, ''); const normalized = sql.trim().replace(/;+\s*$/, '');
if (!/^select\b/i.test(normalized)) { 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(';')) { 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, { const rows = await db.sequelize.query(normalized, {

View File

@ -2,7 +2,7 @@ const formidable = require('formidable');
const fs = require('fs'); const fs = require('fs');
const config = require('../config'); const config = require('../config');
const path = require('path'); const path = require('path');
const { format } = require("util"); const { format } = require('util');
const ensureDirectoryExistence = (filePath) => { const ensureDirectoryExistence = (filePath) => {
const dirname = path.dirname(filePath); const dirname = path.dirname(filePath);
@ -13,7 +13,7 @@ const ensureDirectoryExistence = (filePath) => {
ensureDirectoryExistence(dirname); ensureDirectoryExistence(dirname);
fs.mkdirSync(dirname); fs.mkdirSync(dirname);
} };
const uploadLocal = ( const uploadLocal = (
folder, folder,
@ -29,9 +29,7 @@ const uploadLocal = (
return; return;
} }
if ( if (validations.entity) {
validations.entity
) {
res.sendStatus(403); res.sendStatus(403);
return; return;
} }
@ -63,7 +61,7 @@ const uploadLocal = (
if (!filename) { if (!filename) {
fs.unlinkSync(fileTempUrl); fs.unlinkSync(fileTempUrl);
res.sendStatus(500); res.status(500).send({ message: 'تعذر تحديد اسم الملف المطلوب رفعه' });
return; return;
} }
@ -80,59 +78,57 @@ const uploadLocal = (
form.on('error', function (err) { form.on('error', function (err) {
res.status(500).send(err); res.status(500).send(err);
}); });
} };
} };
const downloadLocal = async (req, res) => { const downloadLocal = async (req, res) => {
const privateUrl = req.query.privateUrl; const privateUrl = req.query.privateUrl;
if (!privateUrl) { if (!privateUrl) {
return res.sendStatus(404); return res.sendStatus(404);
} }
res.download(path.join(config.uploadDir, privateUrl)); res.download(path.join(config.uploadDir, privateUrl));
} };
const initGCloud = () => { const initGCloud = () => {
const processFile = require("../middlewares/upload"); const processFile = require('../middlewares/upload');
const { Storage } = require("@google-cloud/storage"); const { Storage } = require('@google-cloud/storage');
const crypto = require('crypto') const hash = config.gcloud.hash;
const hash = config.gcloud.hash const privateKey = process.env.GC_PRIVATE_KEY.replace(/\\\n/g, '\n');
const privateKey = process.env.GC_PRIVATE_KEY.replace(/\\\n/g, "\n");
const storage = new Storage({ const storage = new Storage({
projectId: process.env.GC_PROJECT_ID, projectId: process.env.GC_PROJECT_ID,
credentials: { credentials: {
client_email: process.env.GC_CLIENT_EMAIL, client_email: process.env.GC_CLIENT_EMAIL,
private_key: privateKey private_key: privateKey,
} },
}); });
const bucket = storage.bucket(config.gcloud.bucket); const bucket = storage.bucket(config.gcloud.bucket);
return {hash, bucket, processFile}; return { hash, bucket, processFile };
} };
const uploadGCloud = async (folder, req, res) => { const uploadGCloud = async (folder, req, res) => {
try { try {
const {hash, bucket, processFile} = initGCloud(); const { hash, bucket, processFile } = initGCloud();
await processFile(req, res); await processFile(req, res);
let buffer = await req.file.buffer;
let filename = await req.body.filename;
if (!req.file) { if (!req.file) {
return res.status(400).send({ message: "Please upload a file!" }); return res.status(400).send({ message: 'يرجى اختيار ملف للرفع' });
} }
let path = `${hash}/${folder}/${filename}`; const buffer = req.file.buffer;
let blob = bucket.file(path); 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({ const blobStream = blob.createWriteStream({
resumable: false, resumable: false,
}); });
blobStream.on("error", (err) => { blobStream.on('error', (err) => {
console.log('Upload error'); console.log('Upload error');
console.log(err.message); console.log(err.message);
res.status(500).send({ message: 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}`); console.log(`https://storage.googleapis.com/${bucket.name}/${blob.name}`);
blobStream.on("finish", async (data) => { blobStream.on('finish', async () => {
const publicUrl = format( const publicUrl = format(
`https://storage.googleapis.com/${bucket.name}/${blob.name}` `https://storage.googleapis.com/${bucket.name}/${blob.name}`,
); );
res.status(200).send({ res.status(200).send({
message: "Uploaded the file successfully: " + path, message: `تم رفع الملف بنجاح: ${filePath}`,
url: publicUrl, url: publicUrl,
}); });
}); });
blobStream.end(buffer) blobStream.end(buffer);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
res.status(500).send({ res.status(500).send({
message: `Could not upload the file. ${err}` message: `تعذر رفع الملف. ${err}`,
}); });
} }
} };
const downloadGCloud = async (req, res) => { const downloadGCloud = async (req, res) => {
try { 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 filePath = `${hash}/${privateUrl}`;
const file = bucket.file(filePath) const file = bucket.file(filePath);
const fileExists = await file.exists(); const fileExists = await file.exists();
if (fileExists[0]) { if (fileExists[0]) {
const stream = file.createReadStream(); const stream = file.createReadStream();
stream.pipe(res); stream.pipe(res);
return;
} }
else {
res.status(404).send({ res.status(404).send({
message: "Could not download the file. " + err, message: 'تعذر العثور على الملف المطلوب تنزيله',
}); });
}
} catch (err) { } catch (err) {
res.status(404).send({ res.status(404).send({
message: "Could not download the file. " + err, message: 'تعذر تنزيل الملف.',
}); });
} }
} };
const deleteGCloud = async (privateUrl) => { const deleteGCloud = async (privateUrl) => {
try { try {
const {hash, bucket, processFile} = initGCloud(); const { hash, bucket } = initGCloud();
const filePath = `${hash}/${privateUrl}`; const filePath = `${hash}/${privateUrl}`;
const file = bucket.file(filePath) const file = bucket.file(filePath);
const fileExists = await file.exists(); const fileExists = await file.exists();
if (fileExists[0]) { if (fileExists[0]) {
@ -200,7 +196,7 @@ const deleteGCloud = async (privateUrl) => {
} catch (err) { } catch (err) {
console.log(`Cannot find the file ${privateUrl}`); console.log(`Cannot find the file ${privateUrl}`);
} }
} };
module.exports = { module.exports = {
initGCloud, initGCloud,
@ -208,6 +204,5 @@ module.exports = {
downloadLocal, downloadLocal,
deleteGCloud, deleteGCloud,
uploadGCloud, uploadGCloud,
downloadGCloud downloadGCloud,
} };

View File

@ -1,101 +1,96 @@
const errors = { const errors = {
app: { app: {
title: 'Multi-Client Detergents POS', title: 'نظام إدارة المحل ونقطة البيع',
}, },
auth: { auth: {
userDisabled: 'Your account is disabled', userDisabled: 'تم تعطيل هذا الحساب',
forbidden: 'Forbidden', forbidden: 'ليس لديك صلاحية لتنفيذ هذا الإجراء',
unauthorized: 'Unauthorized', unauthorized: 'يجب تسجيل الدخول أولاً',
userNotFound: `Sorry, we don't recognize your credentials`, userNotFound: 'البريد الإلكتروني أو كلمة المرور غير صحيحة',
wrongPassword: `Sorry, we don't recognize your credentials`, wrongPassword: 'البريد الإلكتروني أو كلمة المرور غير صحيحة',
weakPassword: 'This password is too weak', weakPassword: 'كلمة المرور ضعيفة جدًا',
emailAlreadyInUse: 'Email is already in use', emailAlreadyInUse: 'هذا البريد الإلكتروني مستخدم بالفعل',
invalidEmail: 'Please provide a valid email', invalidEmail: 'يرجى إدخال بريد إلكتروني صحيح',
passwordReset: { passwordReset: {
invalidToken: invalidToken: 'رابط إعادة تعيين كلمة المرور غير صالح أو منتهي الصلاحية',
'Password reset link is invalid or has expired', error: 'هذا البريد الإلكتروني غير مسجل في النظام',
error: `Email not recognized`,
}, },
passwordUpdate: { 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: { emailAddressVerificationEmail: {
invalidToken: invalidToken: 'رابط تأكيد البريد الإلكتروني غير صالح أو منتهي الصلاحية',
'Email verification link is invalid or has expired', error: 'هذا البريد الإلكتروني غير مسجل في النظام',
error: `Email not recognized`,
}, },
}, },
iam: { iam: {
errors: { errors: {
userAlreadyExists: userAlreadyExists: 'يوجد مستخدم بهذا البريد الإلكتروني بالفعل',
'User with this email already exists', userNotFound: 'المستخدم غير موجود',
userNotFound: 'User not found', disablingHimself: 'لا يمكنك تعطيل حسابك الحالي',
disablingHimself: `You can't disable yourself`, revokingOwnPermission: 'لا يمكنك إزالة صلاحية المالك من حسابك الحالي',
revokingOwnPermission: `You can't revoke your own owner permission`, deletingHimself: 'لا يمكنك حذف حسابك الحالي',
deletingHimself: `You can't delete yourself`, emailRequired: 'البريد الإلكتروني مطلوب',
emailRequired: 'Email is required',
}, },
}, },
importer: { importer: {
errors: { errors: {
invalidFileEmpty: 'The file is empty', invalidFileEmpty: 'الملف فارغ',
invalidFileExcel: invalidFileExcel: 'يسمح فقط بملفات Excel بصيغة .xlsx',
'Only excel (.xlsx) files are allowed', invalidFileUpload: 'الملف غير صالح. تأكد من استخدام آخر نسخة من القالب المعتمد.',
invalidFileUpload: importHashRequired: 'معرّف الاستيراد مطلوب',
'Invalid file. Make sure you are using the last version of the template.', importHashExistent: 'تم استيراد هذه البيانات مسبقًا',
importHashRequired: 'Import hash is required', userEmailMissing: 'بعض الصفوف في ملف CSV لا تحتوي على بريد إلكتروني',
importHashExistent: 'Data has already been imported',
userEmailMissing: 'Some items in the CSV do not have an email',
}, },
}, },
errors: { errors: {
forbidden: { forbidden: {
message: 'Forbidden', message: 'ليس لديك صلاحية للوصول',
}, },
validation: { validation: {
message: 'An error occurred', message: 'حدث خطأ في التحقق من البيانات',
}, },
searchQueryRequired: { searchQueryRequired: {
message: 'Search query is required', message: 'يرجى إدخال عبارة البحث',
}, },
}, },
emails: { emails: {
invitation: { invitation: {
subject: `You've been invited to {0}`, subject: 'تمت دعوتك إلى {0}',
body: ` body: `
<p>Hello,</p> <p>مرحبًا،</p>
<p>You've been invited to {0} set password for your {1} account.</p> <p>تمت دعوتك إلى {0}. يرجى تعيين كلمة المرور لحسابك في {1}.</p>
<p><a href='{2}'>{2}</a></p> <p><a href='{2}'>{2}</a></p>
<p>Thanks,</p> <p>شكرًا لك،</p>
<p>Your {0} team</p> <p>فريق {0}</p>
`, `,
}, },
emailAddressVerification: { emailAddressVerification: {
subject: `Verify your email for {0}`, subject: 'تأكيد البريد الإلكتروني لـ {0}',
body: ` body: `
<p>Hello,</p> <p>مرحبًا،</p>
<p>Follow this link to verify your email address.</p> <p>استخدم هذا الرابط لتأكيد عنوان بريدك الإلكتروني.</p>
<p><a href='{0}'>{0}</a></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>إذا لم تطلب هذا الإجراء، يمكنك تجاهل هذه الرسالة.</p>
<p>Thanks,</p> <p>شكرًا لك،</p>
<p>Your {1} team</p> <p>فريق {1}</p>
`, `,
}, },
passwordReset: { passwordReset: {
subject: `Reset your password for {0}`, subject: 'إعادة تعيين كلمة المرور لـ {0}',
body: ` body: `
<p>Hello,</p> <p>مرحبًا،</p>
<p>Follow this link to reset your {0} password for your {1} account.</p> <p>استخدم هذا الرابط لإعادة تعيين كلمة المرور الخاصة بك في {0} لحساب {1}.</p>
<p><a href='{2}'>{2}</a></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>إذا لم تطلب إعادة التعيين، يمكنك تجاهل هذه الرسالة.</p>
<p>Thanks,</p> <p>شكرًا لك،</p>
<p>Your {0} team</p> <p>فريق {0}</p>
`, `,
}, },
}, },

View File

@ -6,8 +6,8 @@ const loadRoleService = () => {
try { try {
return require('./roles'); return require('./roles');
} catch (error) { } catch (error) {
console.error('Role service is missing. Advanced roles are required for this operation.', error); console.error('تعذر تحميل خدمة الأدوار المطلوبة لهذه العملية.', error);
const err = new Error('Role service is missing. Advanced roles are required for this operation.'); const err = new Error('تعذر تحميل خدمة الأدوار المطلوبة لهذه العملية.');
err.originalError = error; err.originalError = error;
throw err; throw err;
} }
@ -25,17 +25,17 @@ module.exports = class OpenAiService {
const { widget_id } = await response.data; const { widget_id } = await response.data;
await RoleService.addRoleInfo(roleId, userId, 'widgets', widget_id); await RoleService.addRoleInfo(roleId, userId, 'widgets', widget_id);
return 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) { static async askGpt(prompt) {
if (!prompt) { if (!prompt) {
return { return {
success: false, success: false,
error: 'Prompt is required' error: 'النص المطلوب للذكاء الاصطناعي فارغ',
}; };
} }
@ -59,7 +59,7 @@ module.exports = class OpenAiService {
console.error('AI JSON decode failed:', error); console.error('AI JSON decode failed:', error);
return { return {
success: false, success: false,
error: 'AI response parsing failed', error: 'تعذر قراءة رد الذكاء الاصطناعي',
details: error.message || String(error), details: error.message || String(error),
}; };
} }
@ -73,7 +73,7 @@ module.exports = class OpenAiService {
console.error('AI proxy error:', response); console.error('AI proxy error:', response);
return { return {
success: false, success: false,
error: response.error || response.message || 'AI proxy error', error: response.error || response.message || 'حدث خطأ أثناء التواصل مع خدمة الذكاء الاصطناعي',
response, response,
}; };
} }

View File

@ -1,6 +1,6 @@
/// <reference types="next" /> /// <reference types="next" />
/// <reference types="next/image-types/global" /> /// <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 // NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. // see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.

View File

@ -63,13 +63,13 @@ const AsideMenuItem = ({ item, isDropdownList = false }: Props) => {
) )
const componentClass = [ 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' : '', isDropdownList ? 'px-6 text-sm' : '',
item.color item.color
? getButtonColor(item.color, false, true) ? getButtonColor(item.color, false, true)
: `${asideMenuItemStyle}`, : `${asideMenuItemStyle}`,
isLinkActive isLinkActive
? `text-black ${activeLinkColor} dark:text-white dark:bg-dark-800` ? `text-black ${activeLinkColor} shadow-sm dark:text-white dark:bg-dark-800`
: '', : '',
].join(' '); ].join(' ');

View File

@ -56,17 +56,17 @@ export default function AsideMenuLayer({ menu, className = '', ...props }: Props
return ( return (
<aside <aside
id='asideMenu' 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 <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 <div
className={`flex flex-row h-14 items-center justify-between ${asideBrandStyle}`} 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"> <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>} {organizationName && <p>{organizationName}</p>}

View File

@ -48,10 +48,13 @@ export default function BaseButton({
'justify-center', 'justify-center',
'items-center', 'items-center',
'whitespace-nowrap', 'whitespace-nowrap',
'font-semibold',
'tracking-[0.01em]',
'focus:outline-none', 'focus:outline-none',
'transition-colors', 'transition-all',
'duration-200',
'ease-out',
'focus:ring', 'focus:ring',
'duration-150',
'border', 'border',
disabled ? 'cursor-not-allowed' : 'cursor-pointer', disabled ? 'cursor-not-allowed' : 'cursor-pointer',
roundedFull ? 'rounded-full' : `${corners}`, roundedFull ? 'rounded-full' : `${corners}`,
@ -60,7 +63,7 @@ export default function BaseButton({
] ]
if (!label && icon) { if (!label && icon) {
componentClass.push('p-1') componentClass.push('p-1.5')
} else if (small) { } else if (small) {
componentClass.push('text-sm', roundedFull ? 'px-3 py-1' : 'p-1') componentClass.push('text-sm', roundedFull ? 'px-3 py-1' : 'p-1')
} else { } else {
@ -69,6 +72,8 @@ export default function BaseButton({
if (disabled) { if (disabled) {
componentClass.push(outline ? 'opacity-50' : 'opacity-70') 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(' ') const componentClassString = componentClass.join(' ')

View File

@ -37,16 +37,16 @@ export default function CardBox({
const corners = useAppSelector((state) => state.style.corners); const corners = useAppSelector((state) => state.style.corners);
const cardsStyle = useAppSelector((state) => state.style.cardsStyle); const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
const componentClass = [ 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, className,
corners !== 'rounded-full'? corners : 'rounded-3xl', corners !== 'rounded-full'? corners : 'rounded-3xl',
flex, flex,
isList ? '' : `${cardsStyle}`, isList ? '' : `${cardsStyle}`,
hasTable ? '' : `border-dark-700 dark:border-dark-700`, hasTable ? '' : `border-dark-700 dark:border-dark-700`,
] ]
if (isHoverable) { if (isHoverable) {
componentClass.push('hover:shadow-lg transition-shadow duration-500') componentClass.push('hover:-translate-y-0.5 hover:shadow-lg')
} }
return React.createElement( return React.createElement(

View File

@ -35,9 +35,9 @@ export default function NavBar({ menu, className = '', children }: Props) {
return ( return (
<nav <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 flex-1 items-stretch h-14">{children}</div>
<div className="flex-none items-stretch flex h-14 lg:hidden"> <div className="flex-none items-stretch flex h-14 lg:hidden">
<NavBarItemPlain onClick={handleMenuNavBarToggleClick}> <NavBarItemPlain onClick={handleMenuNavBarToggleClick}>
@ -47,7 +47,7 @@ export default function NavBar({ menu, className = '', children }: Props) {
<div <div
className={`${ className={`${
isMenuNavBarActive ? 'block' : 'hidden' 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} /> <NavBarMenuList menu={menu} />
</div> </div>

View File

@ -17,7 +17,7 @@ export default function NavBarItemPlain({
const navBarItemLabelStyle = useAppSelector((state) => state.style.navBarItemLabelStyle) const navBarItemLabelStyle = useAppSelector((state) => state.style.navBarItemLabelStyle)
const navBarItemLabelHoverStyle = useAppSelector((state) => state.style.navBarItemLabelHoverStyle) 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} ${ const classAddon = `${display} ${navBarItemLabelStyle} ${navBarItemLabelHoverStyle} ${
useMargin ? 'my-2 mx-3' : 'py-2 px-3' useMargin ? 'my-2 mx-3' : 'py-2 px-3'
}` }`

View File

@ -93,7 +93,7 @@ const CardOrganizations = ({
))} ))}
{!loading && organizations.length === 0 && ( {!loading && organizations.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</ul> </ul>

View File

@ -70,7 +70,7 @@ const ListOrganizations = ({ organizations, loading, onDelete, currentPage, numP
))} ))}
{!loading && organizations.length === 0 && ( {!loading && organizations.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</div> </div>

View File

@ -395,12 +395,12 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">إجراء</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
color='danger' color='danger'
label='Delete' label='حذف'
onClick={() => { onClick={() => {
deleteFilter(filterItem.id) deleteFilter(filterItem.id)
}} }}
@ -413,13 +413,13 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
<BaseButton <BaseButton
className="my-2 mr-3" className="my-2 mr-3"
color="success" color="success"
label='Apply' label='تطبيق'
onClick={handleSubmit} onClick={handleSubmit}
/> />
<BaseButton <BaseButton
className="my-2" className="my-2"
color='info' color='info'
label='Cancel' label='إلغاء'
onClick={handleReset} onClick={handleReset}
/> />
</div> </div>
@ -429,14 +429,14 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
</CardBox> : null </CardBox> : null
} }
<CardBoxModal <CardBoxModal
title="Please confirm" title="تأكيد العملية"
buttonColor="info" buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'} buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive} isActive={isModalTrashActive}
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>هل أنت متأكد من حذف هذا العنصر؟</p>
</CardBoxModal> </CardBoxModal>
@ -450,7 +450,7 @@ const TableSampleOrganizations = ({ filterItems, setFilterItems, filters, showGr
<BaseButton <BaseButton
className='me-4' className='me-4'
color='danger' color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`} label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
onClick={() => onDeleteRows(selectedRows)} onClick={() => onDeleteRows(selectedRows)}
/>, />,
document.getElementById('delete-rows-button'), document.getElementById('delete-rows-button'),

View File

@ -93,7 +93,7 @@ const CardPermissions = ({
))} ))}
{!loading && permissions.length === 0 && ( {!loading && permissions.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</ul> </ul>

View File

@ -70,7 +70,7 @@ const ListPermissions = ({ permissions, loading, onDelete, currentPage, numPages
))} ))}
{!loading && permissions.length === 0 && ( {!loading && permissions.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</div> </div>

View File

@ -395,12 +395,12 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">إجراء</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
color='danger' color='danger'
label='Delete' label='حذف'
onClick={() => { onClick={() => {
deleteFilter(filterItem.id) deleteFilter(filterItem.id)
}} }}
@ -413,13 +413,13 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
<BaseButton <BaseButton
className="my-2 mr-3" className="my-2 mr-3"
color="success" color="success"
label='Apply' label='تطبيق'
onClick={handleSubmit} onClick={handleSubmit}
/> />
<BaseButton <BaseButton
className="my-2" className="my-2"
color='info' color='info'
label='Cancel' label='إلغاء'
onClick={handleReset} onClick={handleReset}
/> />
</div> </div>
@ -429,14 +429,14 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
</CardBox> : null </CardBox> : null
} }
<CardBoxModal <CardBoxModal
title="Please confirm" title="تأكيد العملية"
buttonColor="info" buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'} buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive} isActive={isModalTrashActive}
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>هل أنت متأكد من حذف هذا العنصر؟</p>
</CardBoxModal> </CardBoxModal>
@ -450,7 +450,7 @@ const TableSamplePermissions = ({ filterItems, setFilterItems, filters, showGrid
<BaseButton <BaseButton
className='me-4' className='me-4'
color='danger' color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`} label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
onClick={() => onDeleteRows(selectedRows)} onClick={() => onDeleteRows(selectedRows)}
/>, />,
document.getElementById('delete-rows-button'), document.getElementById('delete-rows-button'),

View File

@ -165,7 +165,7 @@ const CardPrice_change_logs = ({
))} ))}
{!loading && price_change_logs.length === 0 && ( {!loading && price_change_logs.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</ul> </ul>

View File

@ -118,7 +118,7 @@ const ListPrice_change_logs = ({ price_change_logs, loading, onDelete, currentPa
))} ))}
{!loading && price_change_logs.length === 0 && ( {!loading && price_change_logs.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</div> </div>

View File

@ -395,12 +395,12 @@ const TableSamplePrice_change_logs = ({ filterItems, setFilterItems, filters, sh
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">إجراء</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
color='danger' color='danger'
label='Delete' label='حذف'
onClick={() => { onClick={() => {
deleteFilter(filterItem.id) deleteFilter(filterItem.id)
}} }}
@ -413,13 +413,13 @@ const TableSamplePrice_change_logs = ({ filterItems, setFilterItems, filters, sh
<BaseButton <BaseButton
className="my-2 mr-3" className="my-2 mr-3"
color="success" color="success"
label='Apply' label='تطبيق'
onClick={handleSubmit} onClick={handleSubmit}
/> />
<BaseButton <BaseButton
className="my-2" className="my-2"
color='info' color='info'
label='Cancel' label='إلغاء'
onClick={handleReset} onClick={handleReset}
/> />
</div> </div>
@ -429,14 +429,14 @@ const TableSamplePrice_change_logs = ({ filterItems, setFilterItems, filters, sh
</CardBox> : null </CardBox> : null
} }
<CardBoxModal <CardBoxModal
title="Please confirm" title="تأكيد العملية"
buttonColor="info" buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'} buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive} isActive={isModalTrashActive}
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>هل أنت متأكد من حذف هذا العنصر؟</p>
</CardBoxModal> </CardBoxModal>
@ -450,7 +450,7 @@ const TableSamplePrice_change_logs = ({ filterItems, setFilterItems, filters, sh
<BaseButton <BaseButton
className='me-4' className='me-4'
color='danger' color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`} label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
onClick={() => onDeleteRows(selectedRows)} onClick={() => onDeleteRows(selectedRows)}
/>, />,
document.getElementById('delete-rows-button'), document.getElementById('delete-rows-button'),

View File

@ -117,7 +117,7 @@ const CardRoles = ({
))} ))}
{!loading && roles.length === 0 && ( {!loading && roles.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</ul> </ul>

View File

@ -86,7 +86,7 @@ const ListRoles = ({ roles, loading, onDelete, currentPage, numPages, onPageChan
))} ))}
{!loading && roles.length === 0 && ( {!loading && roles.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</div> </div>

View File

@ -395,12 +395,12 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">إجراء</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
color='danger' color='danger'
label='Delete' label='حذف'
onClick={() => { onClick={() => {
deleteFilter(filterItem.id) deleteFilter(filterItem.id)
}} }}
@ -413,13 +413,13 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
<BaseButton <BaseButton
className="my-2 mr-3" className="my-2 mr-3"
color="success" color="success"
label='Apply' label='تطبيق'
onClick={handleSubmit} onClick={handleSubmit}
/> />
<BaseButton <BaseButton
className="my-2" className="my-2"
color='info' color='info'
label='Cancel' label='إلغاء'
onClick={handleReset} onClick={handleReset}
/> />
</div> </div>
@ -429,14 +429,14 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
</CardBox> : null </CardBox> : null
} }
<CardBoxModal <CardBoxModal
title="Please confirm" title="تأكيد العملية"
buttonColor="info" buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'} buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive} isActive={isModalTrashActive}
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>هل أنت متأكد من حذف هذا العنصر؟</p>
</CardBoxModal> </CardBoxModal>
@ -450,7 +450,7 @@ const TableSampleRoles = ({ filterItems, setFilterItems, filters, showGrid }) =>
<BaseButton <BaseButton
className='me-4' className='me-4'
color='danger' color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`} label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
onClick={() => onDeleteRows(selectedRows)} onClick={() => onDeleteRows(selectedRows)}
/>, />,
document.getElementById('delete-rows-button'), document.getElementById('delete-rows-button'),

View File

@ -177,7 +177,7 @@ const CardSales_invoice_items = ({
))} ))}
{!loading && sales_invoice_items.length === 0 && ( {!loading && sales_invoice_items.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</ul> </ul>

View File

@ -126,7 +126,7 @@ const ListSales_invoice_items = ({ sales_invoice_items, loading, onDelete, curre
))} ))}
{!loading && sales_invoice_items.length === 0 && ( {!loading && sales_invoice_items.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</div> </div>

View File

@ -395,12 +395,12 @@ const TableSampleSales_invoice_items = ({ filterItems, setFilterItems, filters,
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">إجراء</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
color='danger' color='danger'
label='Delete' label='حذف'
onClick={() => { onClick={() => {
deleteFilter(filterItem.id) deleteFilter(filterItem.id)
}} }}
@ -413,13 +413,13 @@ const TableSampleSales_invoice_items = ({ filterItems, setFilterItems, filters,
<BaseButton <BaseButton
className="my-2 mr-3" className="my-2 mr-3"
color="success" color="success"
label='Apply' label='تطبيق'
onClick={handleSubmit} onClick={handleSubmit}
/> />
<BaseButton <BaseButton
className="my-2" className="my-2"
color='info' color='info'
label='Cancel' label='إلغاء'
onClick={handleReset} onClick={handleReset}
/> />
</div> </div>
@ -429,14 +429,14 @@ const TableSampleSales_invoice_items = ({ filterItems, setFilterItems, filters,
</CardBox> : null </CardBox> : null
} }
<CardBoxModal <CardBoxModal
title="Please confirm" title="تأكيد العملية"
buttonColor="info" buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'} buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive} isActive={isModalTrashActive}
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>هل أنت متأكد من حذف هذا العنصر؟</p>
</CardBoxModal> </CardBoxModal>
@ -450,7 +450,7 @@ const TableSampleSales_invoice_items = ({ filterItems, setFilterItems, filters,
<BaseButton <BaseButton
className='me-4' className='me-4'
color='danger' color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`} label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
onClick={() => onDeleteRows(selectedRows)} onClick={() => onDeleteRows(selectedRows)}
/>, />,
document.getElementById('delete-rows-button'), document.getElementById('delete-rows-button'),

View File

@ -37,7 +37,7 @@ const Search = () => {
name='search' name='search'
validate={validateSearch} validate={validateSearch}
placeholder='ابحث عن صفحة أو عنصر' dir='rtl' 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 ? ( {errors.search && touched.search && values.search.length < 2 ? (
<div className='text-red-500 text-sm ml-2 absolute'>{errors.search}</div> <div className='text-red-500 text-sm ml-2 absolute'>{errors.search}</div>

View File

@ -202,7 +202,7 @@ const CardUsers = ({
))} ))}
{!loading && users.length === 0 && ( {!loading && users.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</ul> </ul>

View File

@ -145,7 +145,7 @@ const ListUsers = ({ users, loading, onDelete, currentPage, numPages, onPageChan
))} ))}
{!loading && users.length === 0 && ( {!loading && users.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'> <div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p> <p className=''>لا توجد بيانات للعرض</p>
</div> </div>
)} )}
</div> </div>

View File

@ -395,12 +395,12 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div> </div>
)} )}
<div className="flex flex-col"> <div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div> <div className=" text-gray-500 font-bold">إجراء</div>
<BaseButton <BaseButton
className="my-2" className="my-2"
type='reset' type='reset'
color='danger' color='danger'
label='Delete' label='حذف'
onClick={() => { onClick={() => {
deleteFilter(filterItem.id) deleteFilter(filterItem.id)
}} }}
@ -413,13 +413,13 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
<BaseButton <BaseButton
className="my-2 mr-3" className="my-2 mr-3"
color="success" color="success"
label='Apply' label='تطبيق'
onClick={handleSubmit} onClick={handleSubmit}
/> />
<BaseButton <BaseButton
className="my-2" className="my-2"
color='info' color='info'
label='Cancel' label='إلغاء'
onClick={handleReset} onClick={handleReset}
/> />
</div> </div>
@ -429,14 +429,14 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
</CardBox> : null </CardBox> : null
} }
<CardBoxModal <CardBoxModal
title="Please confirm" title="تأكيد العملية"
buttonColor="info" buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'} buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive} isActive={isModalTrashActive}
onConfirm={handleDeleteAction} onConfirm={handleDeleteAction}
onCancel={handleModalAction} onCancel={handleModalAction}
> >
<p>Are you sure you want to delete this item?</p> <p>هل أنت متأكد من حذف هذا العنصر؟</p>
</CardBoxModal> </CardBoxModal>
@ -450,7 +450,7 @@ const TableSampleUsers = ({ filterItems, setFilterItems, filters, showGrid }) =>
<BaseButton <BaseButton
className='me-4' className='me-4'
color='danger' color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`} label={`حذف ${selectedRows.length === 1 ? 'السجل المحدد' : 'السجلات المحددة'}`}
onClick={() => onDeleteRows(selectedRows)} onClick={() => onDeleteRows(selectedRows)}
/>, />,
document.getElementById('delete-rows-button'), document.getElementById('delete-rows-button'),

View File

@ -35,14 +35,57 @@
@apply bg-transparent border border-blue-600 text-blue-600 !important; @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 { 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 { body {
text-rendering: optimizeLegibility; 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 { .app-rtl {
direction: rtl; direction: rtl;
text-align: right; text-align: right;

View File

@ -109,10 +109,10 @@ const EditOrganizations = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit organizations')}</title> <title>{getPageTitle('تعديل منظمة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit organizations'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل منظمة'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -164,9 +164,9 @@ const EditOrganizations = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/organizations/organizations-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/organizations/organizations-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -106,10 +106,10 @@ const EditOrganizationsPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit organizations')}</title> <title>{getPageTitle('تعديل منظمة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit organizations'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل منظمة'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -161,9 +161,9 @@ const EditOrganizationsPage = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/organizations/organizations-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/organizations/organizations-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -86,28 +86,28 @@ const OrganizationsTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Organizations')}</title> <title>{getPageTitle('المنظمات')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Organizations" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المنظمات" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} onClick={addFilter}
/> />
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getOrganizationsCSV} /> <BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getOrganizationsCSV} />
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -62,10 +62,10 @@ const OrganizationsNew = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('New Item')}</title> <title>{getPageTitle('إضافة منظمة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة منظمة" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -116,9 +116,9 @@ const OrganizationsNew = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/organizations/organizations-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/organizations/organizations-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -86,28 +86,28 @@ const OrganizationsTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Organizations')}</title> <title>{getPageTitle('المنظمات')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Organizations" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المنظمات" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} onClick={addFilter}
/> />
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getOrganizationsCSV} /> <BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getOrganizationsCSV} />
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -33,11 +33,6 @@ const OrganizationsView = () => {
const { id } = router.query; const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => { useEffect(() => {
dispatch(fetch({ id })); dispatch(fetch({ id }));
}, [dispatch, id]); }, [dispatch, id]);
@ -46,13 +41,13 @@ const OrganizationsView = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('View organizations')}</title> <title>{getPageTitle('عرض منظمة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View organizations')} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض منظمة" main>
<BaseButton <BaseButton
color='info' color='info'
label='Edit' label='تعديل'
href={`/organizations/organizations-edit/?id=${id}`} href={`/organizations/organizations-edit/?id=${id}`}
/> />
</SectionTitleLineWithButton> </SectionTitleLineWithButton>

View File

@ -109,10 +109,10 @@ const EditPermissions = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit permissions')}</title> <title>{getPageTitle('تعديل صلاحية')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit permissions'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل صلاحية'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -164,9 +164,9 @@ const EditPermissions = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/permissions/permissions-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/permissions/permissions-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -106,10 +106,10 @@ const EditPermissionsPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit permissions')}</title> <title>{getPageTitle('تعديل صلاحية')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit permissions'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل صلاحية'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -161,9 +161,9 @@ const EditPermissionsPage = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/permissions/permissions-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/permissions/permissions-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -86,28 +86,28 @@ const PermissionsTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Permissions')}</title> <title>{getPageTitle('الصلاحيات')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Permissions" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الصلاحيات" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} onClick={addFilter}
/> />
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getPermissionsCSV} /> <BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getPermissionsCSV} />
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -62,10 +62,10 @@ const PermissionsNew = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('New Item')}</title> <title>{getPageTitle('إضافة صلاحية')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة صلاحية" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -116,9 +116,9 @@ const PermissionsNew = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/permissions/permissions-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/permissions/permissions-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -86,28 +86,28 @@ const PermissionsTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Permissions')}</title> <title>{getPageTitle('الصلاحيات')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Permissions" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الصلاحيات" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} onClick={addFilter}
/> />
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getPermissionsCSV} /> <BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getPermissionsCSV} />
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -33,11 +33,6 @@ const PermissionsView = () => {
const { id } = router.query; const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => { useEffect(() => {
dispatch(fetch({ id })); dispatch(fetch({ id }));
}, [dispatch, id]); }, [dispatch, id]);
@ -46,13 +41,13 @@ const PermissionsView = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('View permissions')}</title> <title>{getPageTitle('عرض صلاحية')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View permissions')} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض صلاحية" main>
<BaseButton <BaseButton
color='info' color='info'
label='Edit' label='تعديل'
href={`/permissions/permissions-edit/?id=${id}`} href={`/permissions/permissions-edit/?id=${id}`}
/> />
</SectionTitleLineWithButton> </SectionTitleLineWithButton>

View File

@ -305,10 +305,10 @@ const EditPrice_change_logs = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit price_change_logs')}</title> <title>{getPageTitle('تعديل سجل تغيير السعر')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit price_change_logs'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل سجل تغيير السعر'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -706,9 +706,9 @@ const EditPrice_change_logs = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -302,10 +302,10 @@ const EditPrice_change_logsPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit price_change_logs')}</title> <title>{getPageTitle('تعديل سجل تغيير السعر')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit price_change_logs'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل سجل تغيير السعر'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -703,9 +703,9 @@ const EditPrice_change_logsPage = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -94,28 +94,28 @@ const Price_change_logsTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Price_change_logs')}</title> <title>{getPageTitle('سجلات تغيير السعر')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Price_change_logs" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="سجلات تغيير السعر" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} 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 && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -175,10 +175,10 @@ const Price_change_logsNew = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('New Item')}</title> <title>{getPageTitle('إضافة سجل تغيير السعر')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة سجل تغيير السعر" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -460,9 +460,9 @@ const Price_change_logsNew = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/price_change_logs/price_change_logs-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -94,28 +94,28 @@ const Price_change_logsTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Price_change_logs')}</title> <title>{getPageTitle('سجلات تغيير السعر')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Price_change_logs" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="سجلات تغيير السعر" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} 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 && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -33,11 +33,6 @@ const Price_change_logsView = () => {
const { id } = router.query; const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => { useEffect(() => {
dispatch(fetch({ id })); dispatch(fetch({ id }));
}, [dispatch, id]); }, [dispatch, id]);
@ -46,13 +41,13 @@ const Price_change_logsView = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('View price_change_logs')}</title> <title>{getPageTitle('عرض سجل تغيير السعر')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View price_change_logs')} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض سجل تغيير السعر" main>
<BaseButton <BaseButton
color='info' color='info'
label='Edit' label='تعديل'
href={`/price_change_logs/price_change_logs-edit/?id=${id}`} href={`/price_change_logs/price_change_logs-edit/?id=${id}`}
/> />
</SectionTitleLineWithButton> </SectionTitleLineWithButton>

View File

@ -165,10 +165,10 @@ const EditRoles = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit roles')}</title> <title>{getPageTitle('تعديل دور')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit roles'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل دور'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -317,9 +317,9 @@ const EditRoles = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/roles/roles-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/roles/roles-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -162,10 +162,10 @@ const EditRolesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit roles')}</title> <title>{getPageTitle('تعديل دور')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit roles'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل دور'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -314,9 +314,9 @@ const EditRolesPage = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/roles/roles-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/roles/roles-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -86,28 +86,28 @@ const RolesTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Roles')}</title> <title>{getPageTitle('الأدوار')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Roles" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الأدوار" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} onClick={addFilter}
/> />
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getRolesCSV} /> <BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getRolesCSV} />
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -94,10 +94,10 @@ const RolesNew = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('New Item')}</title> <title>{getPageTitle('إضافة دور')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة دور" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -218,9 +218,9 @@ const RolesNew = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/roles/roles-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/roles/roles-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -86,28 +86,28 @@ const RolesTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Roles')}</title> <title>{getPageTitle('الأدوار')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Roles" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الأدوار" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} onClick={addFilter}
/> />
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getRolesCSV} /> <BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getRolesCSV} />
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -33,11 +33,6 @@ const RolesView = () => {
const { id } = router.query; const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => { useEffect(() => {
dispatch(fetch({ id })); dispatch(fetch({ id }));
}, [dispatch, id]); }, [dispatch, id]);
@ -46,13 +41,13 @@ const RolesView = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('View roles')}</title> <title>{getPageTitle('عرض دور')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View roles')} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض دور" main>
<BaseButton <BaseButton
color='info' color='info'
label='Edit' label='تعديل'
href={`/roles/roles-edit/?id=${id}`} href={`/roles/roles-edit/?id=${id}`}
/> />
</SectionTitleLineWithButton> </SectionTitleLineWithButton>

View File

@ -333,10 +333,10 @@ const EditSales_invoice_items = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit sales_invoice_items')}</title> <title>{getPageTitle('تعديل بند الفاتورة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit sales_invoice_items'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل بند الفاتورة'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -770,9 +770,9 @@ const EditSales_invoice_items = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -330,10 +330,10 @@ const EditSales_invoice_itemsPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit sales_invoice_items')}</title> <title>{getPageTitle('تعديل بند الفاتورة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit sales_invoice_items'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل بند الفاتورة'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -767,9 +767,9 @@ const EditSales_invoice_itemsPage = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -94,28 +94,28 @@ const Sales_invoice_itemsTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Sales_invoice_items')}</title> <title>{getPageTitle('بنود الفاتورة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Sales_invoice_items" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="بنود الفاتورة" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} 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 && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -190,10 +190,10 @@ const Sales_invoice_itemsNew = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('New Item')}</title> <title>{getPageTitle('إضافة بند الفاتورة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة بند الفاتورة" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -514,9 +514,9 @@ const Sales_invoice_itemsNew = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -94,28 +94,28 @@ const Sales_invoice_itemsTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Sales_invoice_items')}</title> <title>{getPageTitle('بنود الفاتورة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Sales_invoice_items" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="بنود الفاتورة" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} 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 && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -33,11 +33,6 @@ const Sales_invoice_itemsView = () => {
const { id } = router.query; const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => { useEffect(() => {
dispatch(fetch({ id })); dispatch(fetch({ id }));
}, [dispatch, id]); }, [dispatch, id]);
@ -46,13 +41,13 @@ const Sales_invoice_itemsView = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('View sales_invoice_items')}</title> <title>{getPageTitle('عرض بند الفاتورة')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View sales_invoice_items')} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض بند الفاتورة" main>
<BaseButton <BaseButton
color='info' color='info'
label='Edit' label='تعديل'
href={`/sales_invoice_items/sales_invoice_items-edit/?id=${id}`} href={`/sales_invoice_items/sales_invoice_items-edit/?id=${id}`}
/> />
</SectionTitleLineWithButton> </SectionTitleLineWithButton>

View File

@ -335,10 +335,10 @@ const EditUsers = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit users')}</title> <title>{getPageTitle('تعديل مستخدم')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit users'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل مستخدم'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -779,9 +779,9 @@ const EditUsers = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/users/users-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/users/users-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -332,10 +332,10 @@ const EditUsersPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Edit users')}</title> <title>{getPageTitle('تعديل مستخدم')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit users'} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل مستخدم'} main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -776,9 +776,9 @@ const EditUsersPage = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/users/users-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/users/users-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -92,28 +92,28 @@ const UsersTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Users')}</title> <title>{getPageTitle('المستخدمون')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Users" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المستخدمون" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox id="usersList" className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} onClick={addFilter}
/> />
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getUsersCSV} /> <BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getUsersCSV} />
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -190,10 +190,10 @@ const UsersNew = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('New Item')}</title> <title>{getPageTitle('إضافة مستخدم')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة مستخدم" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox> <CardBox>
@ -521,9 +521,9 @@ const UsersNew = () => {
<BaseDivider /> <BaseDivider />
<BaseButtons> <BaseButtons>
<BaseButton type="submit" color="info" label="Submit" /> <BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="Reset" /> <BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/users/users-list')}/> <BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/users/users-list')}/>
</BaseButtons> </BaseButtons>
</Form> </Form>
</Formik> </Formik>

View File

@ -92,28 +92,28 @@ const UsersTablesPage = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('Users')}</title> <title>{getPageTitle('المستخدمون')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Users" main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المستخدمون" main>
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'> <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 <BaseButton
className={'mr-3'} className={'mr-3'}
color='info' color='info'
label='Filter' label='تصفية'
onClick={addFilter} onClick={addFilter}
/> />
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getUsersCSV} /> <BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getUsersCSV} />
{hasCreatePermission && ( {hasCreatePermission && (
<BaseButton <BaseButton
color='info' color='info'
label='Upload CSV' label='رفع CSV'
onClick={() => setIsModalActive(true)} onClick={() => setIsModalActive(true)}
/> />
)} )}

View File

@ -33,11 +33,6 @@ const UsersView = () => {
const { id } = router.query; const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => { useEffect(() => {
dispatch(fetch({ id })); dispatch(fetch({ id }));
}, [dispatch, id]); }, [dispatch, id]);
@ -46,13 +41,13 @@ const UsersView = () => {
return ( return (
<> <>
<Head> <Head>
<title>{getPageTitle('View users')}</title> <title>{getPageTitle('عرض مستخدم')}</title>
</Head> </Head>
<SectionMain> <SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View users')} main> <SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="عرض مستخدم" main>
<BaseButton <BaseButton
color='info' color='info'
label='Edit' label='تعديل'
href={`/users/users-edit/?id=${id}`} href={`/users/users-edit/?id=${id}`}
/> />
</SectionTitleLineWithButton> </SectionTitleLineWithButton>