Autosave: 20260401-194421

This commit is contained in:
Flatlogic Bot 2026-04-01 19:44:21 +00:00
parent 6958be49cc
commit 0704729e11
70 changed files with 1537 additions and 1565 deletions

10
frontend/lint-final.log Normal file
View File

@ -0,0 +1,10 @@
> lint
> eslint . --ext .ts,.tsx
/home/ubuntu/executor/workspace/frontend/src/components/Logo/index.tsx
9:5 warning Do not use `<img>` element. Use `<Image />` from `next/image` instead. See: https://nextjs.org/docs/messages/no-img-element @next/next/no-img-element
✖ 1 problem (0 errors, 1 warning)

View File

@ -33,7 +33,7 @@ const CardBoxModal = ({
const footer = (
<BaseButtons>
<BaseButton label={buttonLabel} color={buttonColor} onClick={onConfirm} />
{!!onCancel && <BaseButton label="Cancel" color={buttonColor} outline onClick={onCancel} />}
{!!onCancel && <BaseButton label="إلغاء" color={buttonColor} outline onClick={onCancel} />}
</BaseButtons>
)

View File

@ -90,7 +90,7 @@ const CardCategories = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>اسمالقسم</dt>
<dt className=' text-gray-500 dark:text-dark-600'>اسم القسم</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.category_name }
@ -114,7 +114,7 @@ const CardCategories = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>ترتيبالعرض</dt>
<dt className=' text-gray-500 dark:text-dark-600'>ترتيب العرض</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.sort_order }
@ -141,7 +141,7 @@ const CardCategories = ({
))}
{!loading && categories.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
<p className=''>لا توجد بيانات للعرض</p>
</div>
)}
</ul>

View File

@ -56,7 +56,7 @@ const ListCategories = ({ categories, loading, onDelete, currentPage, numPages,
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>اسمالقسم</p>
<p className={'text-xs text-gray-500 '}>اسم القسم</p>
<p className={'line-clamp-2'}>{ item.category_name }</p>
</div>
@ -72,7 +72,7 @@ const ListCategories = ({ categories, loading, onDelete, currentPage, numPages,
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>ترتيبالعرض</p>
<p className={'text-xs text-gray-500 '}>ترتيب العرض</p>
<p className={'line-clamp-2'}>{ item.sort_order }</p>
</div>
@ -102,7 +102,7 @@ const ListCategories = ({ categories, loading, onDelete, currentPage, numPages,
))}
{!loading && categories.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
<p className=''>لا توجد بيانات للعرض</p>
</div>
)}
</div>

View File

@ -277,7 +277,7 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
return (
<div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div>
<div className=" text-gray-500 font-bold">التصفية</div>
<Field
className={controlClasses}
name='selectedField'
@ -311,7 +311,7 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)}
>
<option value="">Select Value</option>
<option value="">اختر قيمة</option>
{filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => (
@ -326,22 +326,22 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
)?.number ? (
<div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div>
<div className=" text-gray-500 font-bold">من</div>
<Field
className={controlClasses}
name='filterValueFrom'
placeholder='From'
placeholder='من'
id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)}
/>
</div>
<div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div>
<div className=" text-gray-500 font-bold">إلى</div>
<Field
className={controlClasses}
name='filterValueTo'
placeholder='to'
placeholder='إلى'
id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)}
@ -356,12 +356,12 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
<div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'>
From
من
</div>
<Field
className={controlClasses}
name='filterValueFrom'
placeholder='From'
placeholder='من'
id='filterValueFrom'
type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +369,11 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
/>
</div>
<div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div>
<div className=' text-gray-500 font-bold'>إلى</div>
<Field
className={controlClasses}
name='filterValueTo'
placeholder='to'
placeholder='إلى'
id='filterValueTo'
type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +383,11 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
</div>
) : (
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div>
<div className=" text-gray-500 font-bold">يحتوي على</div>
<Field
className={controlClasses}
name='filterValue'
placeholder='Contained'
placeholder='أدخل قيمة'
id='filterValue'
value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)}
@ -395,12 +395,12 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
</div>
)}
<div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div>
<div className=" text-gray-500 font-bold">الإجراء</div>
<BaseButton
className="my-2"
type='reset'
color='danger'
label='Delete'
label='حذف'
onClick={() => {
deleteFilter(filterItem.id)
}}
@ -413,13 +413,13 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
<BaseButton
className="my-2 mr-3"
color="success"
label='Apply'
label='تطبيق'
onClick={handleSubmit}
/>
<BaseButton
className="my-2"
color='info'
label='Cancel'
label='إلغاء'
onClick={handleReset}
/>
</div>
@ -429,14 +429,14 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
</CardBox> : null
}
<CardBoxModal
title="Please confirm"
title="تأكيد العملية"
buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive}
onConfirm={handleDeleteAction}
onCancel={handleModalAction}
>
<p>Are you sure you want to delete this item?</p>
<p>هل أنت متأكد أنك تريد حذف هذا العنصر؟</p>
</CardBoxModal>
@ -450,7 +450,7 @@ const TableSampleCategories = ({ filterItems, setFilterItems, filters, showGrid
<BaseButton
className='me-4'
color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
label={`حذف ${selectedRows.length === 1 ? 'صف واحد' : 'عدة صفوف'}`}
onClick={() => onDeleteRows(selectedRows)}
/>,
document.getElementById('delete-rows-button'),

View File

@ -65,7 +65,7 @@ export const loadColumns = async (
{
field: 'category_name',
headerName: 'اسمالقسم',
headerName: 'اسم القسم',
flex: 1,
minWidth: 120,
filterable: false,
@ -95,7 +95,7 @@ export const loadColumns = async (
{
field: 'sort_order',
headerName: 'ترتيبالعرض',
headerName: 'ترتيب العرض',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -42,7 +42,7 @@ const KanbanCard = ({
href={`/${entityName}/${entityName}-view/?id=${item.id}`}
className={'text-base font-semibold'}
>
{item[showFieldName] ?? 'No data'}
{item[showFieldName] ?? 'لا توجد بيانات'}
</Link>
</div>
<div className={'flex items-center justify-between'}>

View File

@ -1,5 +1,4 @@
import React from 'react';
import Link from 'next/link';
import Button from '@mui/material/Button';
import BaseIcon from './BaseIcon';
import {
@ -81,7 +80,7 @@ const ListActionsPopover = ({
href={linkView}
sx={{ justifyContent: "start" }}
>
View
عرض
</Button>
{hasUpdatePermission && (
<Button
@ -90,7 +89,7 @@ const ListActionsPopover = ({
href={linkEdit}
sx={{ justifyContent: "start" }}
>
Edit
تعديل
</Button>
)}
{hasUpdatePermission && (
@ -103,7 +102,7 @@ const ListActionsPopover = ({
}}
sx={{ justifyContent: "start" }}
>
Delete
حذف
</Button>
)}
</div>

View File

@ -49,16 +49,16 @@ export default function PasswordSetOrReset() {
return (
<>
<Head>
{isInvitation && <title>{getPageTitle('Set Password')}</title>}
{!isInvitation && <title>{getPageTitle('Reset Password')}</title>}
{isInvitation && <title>{getPageTitle('تعيين كلمة المرور')}</title>}
{!isInvitation && <title>{getPageTitle('إعادة تعيين كلمة المرور')}</title>}
</Head>
<SectionFullScreen bg='violet'>
<div className='w-full flex flex-col items-center justify-center'>
<CardBox className='w-11/12 md:w-7/12 lg:w-6/12 xl:w-4/12'>
{isInvitation && <p className='text-xl mb-2'>Set Password</p>}
{!isInvitation && <p className='text-xl mb-2'>Reset Password</p>}
<p className='text-base mb-4'>Enter your new password</p>
{isInvitation && <p className='text-xl mb-2'>تعيين كلمة المرور</p>}
{!isInvitation && <p className='text-xl mb-2'>إعادة تعيين كلمة المرور</p>}
<p className='text-base mb-4'>أدخل كلمة المرور الجديدة</p>
<Formik
initialValues={{
@ -74,7 +74,7 @@ export default function PasswordSetOrReset() {
<Field
type='password'
name='password'
placeholder='Password'
placeholder='كلمة المرور الجديدة'
/>
</FormField>
<FormField
@ -82,7 +82,7 @@ export default function PasswordSetOrReset() {
<Field
type='password'
name='confirm'
placeholder='Confirm Password'
placeholder='تأكيد كلمة المرور'
/>
</FormField>
@ -93,10 +93,10 @@ export default function PasswordSetOrReset() {
disabled={loading}
label={
loading
? 'Loading...'
? 'جارٍ الحفظ...'
: isInvitation
? 'Set Password'
: 'Reset Password'
? 'تعيين كلمة المرور'
: 'إعادة تعيين كلمة المرور'
}
color='info'
/>

View File

@ -111,7 +111,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>اسمالمنتج</dt>
<dt className=' text-gray-500 dark:text-dark-600'>اسم المنتج</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.product_name }
@ -123,7 +123,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>رمزالمنتج</dt>
<dt className=' text-gray-500 dark:text-dark-600'>رمز المنتج</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.sku }
@ -147,7 +147,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>سعرالتكلفةالحقيقي</dt>
<dt className=' text-gray-500 dark:text-dark-600'>سعر التكلفة</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.cost_price }
@ -159,7 +159,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>سعرالبيع</dt>
<dt className=' text-gray-500 dark:text-dark-600'>سعر البيع</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.sale_price }
@ -171,7 +171,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>سعرالبيعالسابق</dt>
<dt className=' text-gray-500 dark:text-dark-600'>سعر البيع السابق</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.sale_price_backup }
@ -183,7 +183,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>سعرالتكلفةالسابق</dt>
<dt className=' text-gray-500 dark:text-dark-600'>سعر التكلفة السابق</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.cost_price_backup }
@ -195,7 +195,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>السعربالدولار</dt>
<dt className=' text-gray-500 dark:text-dark-600'>السعر بالدولار</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.usd_price }
@ -207,7 +207,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>الكميةبالمخزون</dt>
<dt className=' text-gray-500 dark:text-dark-600'>الكمية بالمخزون</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.stock_quantity }
@ -219,7 +219,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>حدالتنبيهلنقصالمخزون</dt>
<dt className=' text-gray-500 dark:text-dark-600'>حد التنبيه لنقص المخزون</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.low_stock_threshold }
@ -247,7 +247,7 @@ const CardProducts = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>متاحللبيع</dt>
<dt className=' text-gray-500 dark:text-dark-600'>متاح للبيع</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ dataFormatter.booleanFormatter(item.is_active) }
@ -262,7 +262,7 @@ const CardProducts = ({
))}
{!loading && products.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
<p className=''>لا توجد بيانات للعرض</p>
</div>
)}
</ul>

View File

@ -71,7 +71,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>اسمالمنتج</p>
<p className={'text-xs text-gray-500 '}>اسم المنتج</p>
<p className={'line-clamp-2'}>{ item.product_name }</p>
</div>
@ -79,7 +79,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>رمزالمنتج</p>
<p className={'text-xs text-gray-500 '}>رمز المنتج</p>
<p className={'line-clamp-2'}>{ item.sku }</p>
</div>
@ -95,7 +95,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>سعرالتكلفةالحقيقي</p>
<p className={'text-xs text-gray-500 '}>سعر التكلفة</p>
<p className={'line-clamp-2'}>{ item.cost_price }</p>
</div>
@ -103,7 +103,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>سعرالبيع</p>
<p className={'text-xs text-gray-500 '}>سعر البيع</p>
<p className={'line-clamp-2'}>{ item.sale_price }</p>
</div>
@ -111,7 +111,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>سعرالبيعالسابق</p>
<p className={'text-xs text-gray-500 '}>سعر البيع السابق</p>
<p className={'line-clamp-2'}>{ item.sale_price_backup }</p>
</div>
@ -119,7 +119,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>سعرالتكلفةالسابق</p>
<p className={'text-xs text-gray-500 '}>سعر التكلفة السابق</p>
<p className={'line-clamp-2'}>{ item.cost_price_backup }</p>
</div>
@ -127,7 +127,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>السعربالدولار</p>
<p className={'text-xs text-gray-500 '}>السعر بالدولار</p>
<p className={'line-clamp-2'}>{ item.usd_price }</p>
</div>
@ -135,7 +135,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>الكميةبالمخزون</p>
<p className={'text-xs text-gray-500 '}>الكمية بالمخزون</p>
<p className={'line-clamp-2'}>{ item.stock_quantity }</p>
</div>
@ -143,7 +143,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>حدالتنبيهلنقصالمخزون</p>
<p className={'text-xs text-gray-500 '}>حد التنبيه لنقص المخزون</p>
<p className={'line-clamp-2'}>{ item.low_stock_threshold }</p>
</div>
@ -163,7 +163,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>متاحللبيع</p>
<p className={'text-xs text-gray-500 '}>متاح للبيع</p>
<p className={'line-clamp-2'}>{ dataFormatter.booleanFormatter(item.is_active) }</p>
</div>
@ -185,7 +185,7 @@ const ListProducts = ({ products, loading, onDelete, currentPage, numPages, onPa
))}
{!loading && products.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
<p className=''>لا توجد بيانات للعرض</p>
</div>
)}
</div>

View File

@ -277,7 +277,7 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
return (
<div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div>
<div className=" text-gray-500 font-bold">التصفية</div>
<Field
className={controlClasses}
name='selectedField'
@ -301,7 +301,7 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
)?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold">
Value
القيمة
</div>
<Field
className={controlClasses}
@ -311,7 +311,7 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)}
>
<option value="">Select Value</option>
<option value="">Select القيمة</option>
{filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => (
@ -326,22 +326,22 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
)?.number ? (
<div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div>
<div className=" text-gray-500 font-bold">من</div>
<Field
className={controlClasses}
name='filterValueFrom'
placeholder='From'
placeholder='من'
id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)}
/>
</div>
<div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div>
<div className=" text-gray-500 font-bold">إلى</div>
<Field
className={controlClasses}
name='filterValueTo'
placeholder='to'
placeholder='إلى'
id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)}
@ -356,12 +356,12 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
<div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'>
From
من
</div>
<Field
className={controlClasses}
name='filterValueFrom'
placeholder='From'
placeholder='من'
id='filterValueFrom'
type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''}
@ -369,11 +369,11 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
/>
</div>
<div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div>
<div className=' text-gray-500 font-bold'>إلى</div>
<Field
className={controlClasses}
name='filterValueTo'
placeholder='to'
placeholder='إلى'
id='filterValueTo'
type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''}
@ -383,11 +383,11 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
</div>
) : (
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div>
<div className=" text-gray-500 font-bold">يحتوي على</div>
<Field
className={controlClasses}
name='filterValue'
placeholder='Contained'
placeholder='اكتب قيمة البحث'
id='filterValue'
value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)}
@ -395,12 +395,12 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
</div>
)}
<div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div>
<div className=" text-gray-500 font-bold">الإجراء</div>
<BaseButton
className="my-2"
type='reset'
color='danger'
label='Delete'
label='حذف'
onClick={() => {
deleteFilter(filterItem.id)
}}
@ -413,13 +413,13 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
<BaseButton
className="my-2 mr-3"
color="success"
label='Apply'
label='تطبيق'
onClick={handleSubmit}
/>
<BaseButton
className="my-2"
color='info'
label='Cancel'
label='إلغاء'
onClick={handleReset}
/>
</div>
@ -429,14 +429,14 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
</CardBox> : null
}
<CardBoxModal
title="Please confirm"
title="تأكيد العملية"
buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive}
onConfirm={handleDeleteAction}
onCancel={handleModalAction}
>
<p>Are you sure you want to delete this item?</p>
<p>هل أنت متأكد أنك تريد حذف هذا العنصر؟</p>
</CardBoxModal>
@ -450,7 +450,7 @@ const TableSampleProducts = ({ filterItems, setFilterItems, filters, showGrid })
<BaseButton
className='me-4'
color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
label={`حذف ${selectedRows.length === 1 ? 'سطر' : 'سطور'}`}
onClick={() => onDeleteRows(selectedRows)}
/>,
document.getElementById('delete-rows-button'),

View File

@ -87,7 +87,7 @@ export const loadColumns = async (
{
field: 'product_name',
headerName: 'اسمالمنتج',
headerName: 'اسم المنتج',
flex: 1,
minWidth: 120,
filterable: false,
@ -102,7 +102,7 @@ export const loadColumns = async (
{
field: 'sku',
headerName: 'رمزالمنتج',
headerName: 'رمز المنتج',
flex: 1,
minWidth: 120,
filterable: false,
@ -132,7 +132,7 @@ export const loadColumns = async (
{
field: 'cost_price',
headerName: 'سعرالتكلفةالحقيقي',
headerName: 'سعر التكلفة',
flex: 1,
minWidth: 120,
filterable: false,
@ -148,7 +148,7 @@ export const loadColumns = async (
{
field: 'sale_price',
headerName: 'سعرالبيع',
headerName: 'سعر البيع',
flex: 1,
minWidth: 120,
filterable: false,
@ -164,7 +164,7 @@ export const loadColumns = async (
{
field: 'sale_price_backup',
headerName: 'سعرالبيعالسابق',
headerName: 'سعر البيع السابق',
flex: 1,
minWidth: 120,
filterable: false,
@ -180,7 +180,7 @@ export const loadColumns = async (
{
field: 'cost_price_backup',
headerName: 'سعرالتكلفةالسابق',
headerName: 'سعر التكلفة السابق',
flex: 1,
minWidth: 120,
filterable: false,
@ -196,7 +196,7 @@ export const loadColumns = async (
{
field: 'usd_price',
headerName: 'السعربالدولار',
headerName: 'السعر بالدولار',
flex: 1,
minWidth: 120,
filterable: false,
@ -212,7 +212,7 @@ export const loadColumns = async (
{
field: 'stock_quantity',
headerName: 'الكميةبالمخزون',
headerName: 'الكمية بالمخزون',
flex: 1,
minWidth: 120,
filterable: false,
@ -228,7 +228,7 @@ export const loadColumns = async (
{
field: 'low_stock_threshold',
headerName: 'حدالتنبيهلنقصالمخزون',
headerName: 'حد التنبيه لنقص المخزون',
flex: 1,
minWidth: 120,
filterable: false,
@ -244,7 +244,7 @@ export const loadColumns = async (
{
field: 'product_images',
headerName: 'صورالمنتج',
headerName: 'صور المنتج',
flex: 1,
minWidth: 120,
filterable: false,
@ -265,7 +265,7 @@ export const loadColumns = async (
{
field: 'is_active',
headerName: 'متاحللبيع',
headerName: 'متاح للبيع',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -126,7 +126,7 @@ const CardSales_invoice_items = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>سعرالبيعوقتالبيع</dt>
<dt className=' text-gray-500 dark:text-dark-600'>سعر البيعوقتالبيع</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.sale_price_snapshot }

View File

@ -80,7 +80,7 @@ const ListSales_invoice_items = ({ sales_invoice_items, loading, onDelete, curre
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>سعرالبيعوقتالبيع</p>
<p className={'text-xs text-gray-500 '}>سعر البيعوقتالبيع</p>
<p className={'line-clamp-2'}>{ item.sale_price_snapshot }</p>
</div>

View File

@ -118,7 +118,7 @@ export const loadColumns = async (
{
field: 'sale_price_snapshot',
headerName: 'سعرالبيعوقتالبيع',
headerName: 'سعر البيعوقتالبيع',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -7,6 +7,10 @@ import { Pagination } from '../Pagination';
import {saveFile} from "../../helpers/fileSaver";
import LoadingSpinner from "../LoadingSpinner";
import Link from 'next/link';
import {
formatSalesInvoicePaymentMethod,
formatSalesInvoiceStatus,
} from '../../helpers/salesInvoiceLabels';
import {hasPermission} from "../../helpers/userPermissions";
@ -102,7 +106,7 @@ const CardSales_invoices = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>رقمالفاتورة</dt>
<dt className=' text-gray-500 dark:text-dark-600'>رقم الفاتورة</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.invoice_number }
@ -114,7 +118,7 @@ const CardSales_invoices = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>تاريخووقتالبيع</dt>
<dt className=' text-gray-500 dark:text-dark-600'>تاريخ ووقت البيع</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ dataFormatter.dateTimeFormatter(item.sold_at) }
@ -129,7 +133,7 @@ const CardSales_invoices = ({
<dt className=' text-gray-500 dark:text-dark-600'>الحالة</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.status }
{ formatSalesInvoiceStatus(item.status) }
</div>
</dd>
</div>
@ -138,7 +142,7 @@ const CardSales_invoices = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>الإجماليقبلالخصم</dt>
<dt className=' text-gray-500 dark:text-dark-600'>الإجمالي قبل الخصم</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.subtotal_amount }
@ -162,7 +166,7 @@ const CardSales_invoices = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>الإجماليالنهائي</dt>
<dt className=' text-gray-500 dark:text-dark-600'>الإجمالي النهائي</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.total_amount }
@ -174,7 +178,7 @@ const CardSales_invoices = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>إجماليالتكلفة</dt>
<dt className=' text-gray-500 dark:text-dark-600'>إجمالي التكلفة</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.total_cost_amount }
@ -186,7 +190,7 @@ const CardSales_invoices = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>إجماليالربح</dt>
<dt className=' text-gray-500 dark:text-dark-600'>إجمالي الربح</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.total_profit_amount }
@ -198,10 +202,10 @@ const CardSales_invoices = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>طريقةالدفع</dt>
<dt className=' text-gray-500 dark:text-dark-600'>طريقة الدفع</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.payment_method }
{ formatSalesInvoicePaymentMethod(item.payment_method) }
</div>
</dd>
</div>
@ -222,7 +226,7 @@ const CardSales_invoices = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>بنودالفاتورة</dt>
<dt className=' text-gray-500 dark:text-dark-600'>بنود الفاتورة</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ dataFormatter.sales_invoice_itemsManyListFormatter(item.items).join(', ')}
@ -237,7 +241,7 @@ const CardSales_invoices = ({
))}
{!loading && sales_invoices.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
<p className=''>لا توجد بيانات للعرض</p>
</div>
)}
</ul>

View File

@ -8,6 +8,10 @@ import {useAppSelector} from "../../stores/hooks";
import {Pagination} from "../Pagination";
import LoadingSpinner from "../LoadingSpinner";
import Link from 'next/link';
import {
formatSalesInvoicePaymentMethod,
formatSalesInvoiceStatus,
} from '../../helpers/salesInvoiceLabels';
import {hasPermission} from "../../helpers/userPermissions";
@ -64,7 +68,7 @@ const ListSales_invoices = ({ sales_invoices, loading, onDelete, currentPage, nu
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>رقمالفاتورة</p>
<p className={'text-xs text-gray-500 '}>رقم الفاتورة</p>
<p className={'line-clamp-2'}>{ item.invoice_number }</p>
</div>
@ -72,7 +76,7 @@ const ListSales_invoices = ({ sales_invoices, loading, onDelete, currentPage, nu
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>تاريخووقتالبيع</p>
<p className={'text-xs text-gray-500 '}>تاريخ ووقت البيع</p>
<p className={'line-clamp-2'}>{ dataFormatter.dateTimeFormatter(item.sold_at) }</p>
</div>
@ -81,14 +85,14 @@ const ListSales_invoices = ({ sales_invoices, loading, onDelete, currentPage, nu
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>الحالة</p>
<p className={'line-clamp-2'}>{ item.status }</p>
<p className={'line-clamp-2'}>{ formatSalesInvoiceStatus(item.status) }</p>
</div>
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>الإجماليقبلالخصم</p>
<p className={'text-xs text-gray-500 '}>الإجمالي قبل الخصم</p>
<p className={'line-clamp-2'}>{ item.subtotal_amount }</p>
</div>
@ -104,7 +108,7 @@ const ListSales_invoices = ({ sales_invoices, loading, onDelete, currentPage, nu
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>الإجماليالنهائي</p>
<p className={'text-xs text-gray-500 '}>الإجمالي النهائي</p>
<p className={'line-clamp-2'}>{ item.total_amount }</p>
</div>
@ -112,7 +116,7 @@ const ListSales_invoices = ({ sales_invoices, loading, onDelete, currentPage, nu
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>إجماليالتكلفة</p>
<p className={'text-xs text-gray-500 '}>إجمالي التكلفة</p>
<p className={'line-clamp-2'}>{ item.total_cost_amount }</p>
</div>
@ -120,7 +124,7 @@ const ListSales_invoices = ({ sales_invoices, loading, onDelete, currentPage, nu
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>إجماليالربح</p>
<p className={'text-xs text-gray-500 '}>إجمالي الربح</p>
<p className={'line-clamp-2'}>{ item.total_profit_amount }</p>
</div>
@ -128,8 +132,8 @@ const ListSales_invoices = ({ sales_invoices, loading, onDelete, currentPage, nu
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>طريقةالدفع</p>
<p className={'line-clamp-2'}>{ item.payment_method }</p>
<p className={'text-xs text-gray-500 '}>طريقة الدفع</p>
<p className={'line-clamp-2'}>{ formatSalesInvoicePaymentMethod(item.payment_method) }</p>
</div>
@ -144,7 +148,7 @@ const ListSales_invoices = ({ sales_invoices, loading, onDelete, currentPage, nu
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>بنودالفاتورة</p>
<p className={'text-xs text-gray-500 '}>بنود الفاتورة</p>
<p className={'line-clamp-2'}>{ dataFormatter.sales_invoice_itemsManyListFormatter(item.items).join(', ')}</p>
</div>
@ -166,7 +170,7 @@ const ListSales_invoices = ({ sales_invoices, loading, onDelete, currentPage, nu
))}
{!loading && sales_invoices.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
<p className=''>لا توجد بيانات للعرض</p>
</div>
)}
</div>

View File

@ -20,10 +20,20 @@ import {dataGridStyles} from "../../styles";
import KanbanBoard from '../KanbanBoard/KanbanBoard';
import axios from 'axios';
import {
formatSalesInvoicePaymentMethod,
formatSalesInvoiceStatus,
} from '../../helpers/salesInvoiceLabels';
const perPage = 10
const getEnumOptionLabel = (fieldName: string, value: string) => {
if (fieldName === 'status') return formatSalesInvoiceStatus(value);
if (fieldName === 'payment_method') return formatSalesInvoicePaymentMethod(value);
return value;
}
const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showGrid }) => {
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
@ -98,13 +108,13 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
setKanbanColumns([
{ id: "draft", label: "draft" },
{ id: "draft", label: "مسودة" },
{ id: "paid", label: "paid" },
{ id: "paid", label: "مدفوعة" },
{ id: "voided", label: "voided" },
{ id: "voided", label: "ملغاة" },
{ id: "refunded", label: "refunded" },
{ id: "refunded", label: "مسترجعة" },
]);
@ -295,7 +305,7 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
{filterItems && Array.isArray( filterItems ) && filterItems.length ?
<CardBox>
<Formik
initialValues={{
initialالقيمةs={{
checkboxes: ['lorem'],
switches: ['lorem'],
radio: 'lorem',
@ -308,7 +318,7 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
return (
<div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div>
<div className=" text-gray-500 font-bold">التصفية</div>
<Field
className={controlClasses}
name='selectedField'
@ -332,7 +342,7 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
)?.type === 'enum' ? (
<div className="flex flex-col w-full mr-3">
<div className="text-gray-500 font-bold">
Value
القيمة
</div>
<Field
className={controlClasses}
@ -342,12 +352,12 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)}
>
<option value="">Select Value</option>
<option value="">اختر القيمة</option>
{filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => (
<option key={option} value={option}>
{option}
{getEnumOptionLabel(filterItem?.fields?.selectedField, option)}
</option>
))}
</Field>
@ -357,22 +367,22 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
)?.number ? (
<div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div>
<div className=" text-gray-500 font-bold">من</div>
<Field
className={controlClasses}
name='filterValueFrom'
placeholder='From'
placeholder='من'
id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)}
/>
</div>
<div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div>
<div className=" text-gray-500 font-bold">إلى</div>
<Field
className={controlClasses}
name='filterValueTo'
placeholder='to'
placeholder='إلى'
id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)}
@ -387,12 +397,12 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
<div className='flex flex-row w-full mr-3'>
<div className='flex flex-col w-full mr-3'>
<div className=' text-gray-500 font-bold'>
From
من
</div>
<Field
className={controlClasses}
name='filterValueFrom'
placeholder='From'
placeholder='من'
id='filterValueFrom'
type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''}
@ -400,11 +410,11 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
/>
</div>
<div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div>
<div className=' text-gray-500 font-bold'>إلى</div>
<Field
className={controlClasses}
name='filterValueTo'
placeholder='to'
placeholder='إلى'
id='filterValueTo'
type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''}
@ -414,11 +424,11 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
</div>
) : (
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div>
<div className=" text-gray-500 font-bold">يحتوي على</div>
<Field
className={controlClasses}
name='filterValue'
placeholder='Contained'
placeholder='أدخل القيمة'
id='filterValue'
value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)}
@ -426,12 +436,12 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
</div>
)}
<div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div>
<div className=" text-gray-500 font-bold">الإجراء</div>
<BaseButton
className="my-2"
type='reset'
color='danger'
label='Delete'
label='حذف'
onClick={() => {
deleteFilter(filterItem.id)
}}
@ -444,13 +454,13 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
<BaseButton
className="my-2 mr-3"
color="success"
label='Apply'
label='تطبيق'
onClick={handleSubmit}
/>
<BaseButton
className="my-2"
color='info'
label='Cancel'
label='إلغاء'
onClick={handleReset}
/>
</div>
@ -460,14 +470,14 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
</CardBox> : null
}
<CardBoxModal
title="Please confirm"
title="تأكيد العملية"
buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive}
onConfirm={handleDeleteAction}
onCancel={handleModalAction}
>
<p>Are you sure you want to delete this item?</p>
<p>هل أنت متأكد أنك تريد حذف هذا العنصر؟</p>
</CardBoxModal>
@ -494,7 +504,7 @@ const TableSampleSales_invoices = ({ filterItems, setFilterItems, filters, showG
<BaseButton
className='me-4'
color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
label={`حذف ${selectedRows.length === 1 ? 'صف واحد' : 'عدة صفوف'}`}
onClick={() => onDeleteRows(selectedRows)}
/>,
document.getElementById('delete-rows-button'),

View File

@ -12,6 +12,10 @@ import {saveFile} from "../../helpers/fileSaver";
import dataFormatter from '../../helpers/dataFormatter'
import DataGridMultiSelect from "../DataGridMultiSelect";
import ListActionsPopover from '../ListActionsPopover';
import {
formatSalesInvoicePaymentMethod,
formatSalesInvoiceStatus,
} from '../../helpers/salesInvoiceLabels';
import {hasPermission} from "../../helpers/userPermissions";
@ -87,7 +91,7 @@ export const loadColumns = async (
{
field: 'invoice_number',
headerName: 'رقمالفاتورة',
headerName: 'رقم الفاتورة',
flex: 1,
minWidth: 120,
filterable: false,
@ -102,7 +106,7 @@ export const loadColumns = async (
{
field: 'sold_at',
headerName: 'تاريخووقتالبيع',
headerName: 'تاريخ ووقت البيع',
flex: 1,
minWidth: 120,
filterable: false,
@ -129,13 +133,13 @@ export const loadColumns = async (
editable: hasUpdatePermission,
valueFormatter: ({ value }) => formatSalesInvoiceStatus(value),
},
{
field: 'subtotal_amount',
headerName: 'الإجماليقبلالخصم',
headerName: 'الإجمالي قبل الخصم',
flex: 1,
minWidth: 120,
filterable: false,
@ -167,7 +171,7 @@ export const loadColumns = async (
{
field: 'total_amount',
headerName: 'الإجماليالنهائي',
headerName: 'الإجمالي النهائي',
flex: 1,
minWidth: 120,
filterable: false,
@ -183,7 +187,7 @@ export const loadColumns = async (
{
field: 'total_cost_amount',
headerName: 'إجماليالتكلفة',
headerName: 'إجمالي التكلفة',
flex: 1,
minWidth: 120,
filterable: false,
@ -199,7 +203,7 @@ export const loadColumns = async (
{
field: 'total_profit_amount',
headerName: 'إجماليالربح',
headerName: 'إجمالي الربح',
flex: 1,
minWidth: 120,
filterable: false,
@ -215,7 +219,7 @@ export const loadColumns = async (
{
field: 'payment_method',
headerName: 'طريقةالدفع',
headerName: 'طريقة الدفع',
flex: 1,
minWidth: 120,
filterable: false,
@ -224,7 +228,7 @@ export const loadColumns = async (
editable: hasUpdatePermission,
valueFormatter: ({ value }) => formatSalesInvoicePaymentMethod(value),
},
@ -245,7 +249,7 @@ export const loadColumns = async (
{
field: 'items',
headerName: 'بنودالفاتورة',
headerName: 'بنود الفاتورة',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -11,9 +11,9 @@ const Search = () => {
const validateSearch = (value) => {
let error;
if (!value) {
error = 'Required';
error = 'الرجاء كتابة كلمة للبحث';
} else if (value.length < 2) {
error = 'Minimum length: 2 characters';
error = 'الحد الأدنى حرفان';
}
return error;
};
@ -31,12 +31,12 @@ const Search = () => {
validateOnChange={false}
>
{({ errors, touched, values }) => (
<Form style={{width: '300px'}} >
<Form className='w-[220px] sm:w-[300px]'>
<Field
id='search'
name='search'
validate={validateSearch}
placeholder='Search'
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`}
/>
{errors.search && touched.search && values.search.length < 2 ? (

View File

@ -78,7 +78,7 @@ const CardShops = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>اسمالمتجر</dt>
<dt className=' text-gray-500 dark:text-dark-600'>اسم المحل</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.shop_name }
@ -90,7 +90,7 @@ const CardShops = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>اسمالمالك</dt>
<dt className=' text-gray-500 dark:text-dark-600'>اسم المالك</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.owner_name }
@ -102,7 +102,7 @@ const CardShops = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>هاتفالمتجر</dt>
<dt className=' text-gray-500 dark:text-dark-600'>هاتف المحل</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.phone }
@ -126,7 +126,7 @@ const CardShops = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>اسمالعملةالمحلية</dt>
<dt className=' text-gray-500 dark:text-dark-600'>اسم العملة المحلية</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.currency_name }
@ -138,7 +138,7 @@ const CardShops = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>سعرالدولاراليومي</dt>
<dt className=' text-gray-500 dark:text-dark-600'>سعر الدولار اليومي</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ item.usd_rate }
@ -150,7 +150,7 @@ const CardShops = ({
<div className='flex justify-between gap-x-4 py-3'>
<dt className=' text-gray-500 dark:text-dark-600'>السماحبمخزونسالب</dt>
<dt className=' text-gray-500 dark:text-dark-600'>السماح بمخزون سالب</dt>
<dd className='flex items-start gap-x-2'>
<div className='font-medium line-clamp-4'>
{ dataFormatter.booleanFormatter(item.allow_negative_stock) }
@ -177,7 +177,7 @@ const CardShops = ({
))}
{!loading && shops.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
<p className=''>لا توجد بيانات للعرض</p>
</div>
)}
</ul>

View File

@ -48,7 +48,7 @@ const ListShops = ({ shops, loading, onDelete, currentPage, numPages, onPageChan
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>اسمالمتجر</p>
<p className={'text-xs text-gray-500 '}>اسم المحل</p>
<p className={'line-clamp-2'}>{ item.shop_name }</p>
</div>
@ -56,7 +56,7 @@ const ListShops = ({ shops, loading, onDelete, currentPage, numPages, onPageChan
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>اسمالمالك</p>
<p className={'text-xs text-gray-500 '}>اسم المالك</p>
<p className={'line-clamp-2'}>{ item.owner_name }</p>
</div>
@ -64,7 +64,7 @@ const ListShops = ({ shops, loading, onDelete, currentPage, numPages, onPageChan
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>هاتفالمتجر</p>
<p className={'text-xs text-gray-500 '}>هاتف المحل</p>
<p className={'line-clamp-2'}>{ item.phone }</p>
</div>
@ -80,7 +80,7 @@ const ListShops = ({ shops, loading, onDelete, currentPage, numPages, onPageChan
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>اسمالعملةالمحلية</p>
<p className={'text-xs text-gray-500 '}>اسم العملة المحلية</p>
<p className={'line-clamp-2'}>{ item.currency_name }</p>
</div>
@ -88,7 +88,7 @@ const ListShops = ({ shops, loading, onDelete, currentPage, numPages, onPageChan
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>سعرالدولاراليومي</p>
<p className={'text-xs text-gray-500 '}>سعر الدولار اليومي</p>
<p className={'line-clamp-2'}>{ item.usd_rate }</p>
</div>
@ -96,7 +96,7 @@ const ListShops = ({ shops, loading, onDelete, currentPage, numPages, onPageChan
<div className={'flex-1 px-3'}>
<p className={'text-xs text-gray-500 '}>السماحبمخزونسالب</p>
<p className={'text-xs text-gray-500 '}>السماح بمخزون سالب</p>
<p className={'line-clamp-2'}>{ dataFormatter.booleanFormatter(item.allow_negative_stock) }</p>
</div>
@ -126,7 +126,7 @@ const ListShops = ({ shops, loading, onDelete, currentPage, numPages, onPageChan
))}
{!loading && shops.length === 0 && (
<div className='col-span-full flex items-center justify-center h-40'>
<p className=''>No data to display</p>
<p className=''>لا توجد بيانات للعرض</p>
</div>
)}
</div>

View File

@ -279,7 +279,7 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
return (
<div key={filterItem.id} className="flex mb-4">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Filter</div>
<div className=" text-gray-500 font-bold">التصفية</div>
<Field
className={controlClasses}
name='selectedField'
@ -313,7 +313,7 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)}
>
<option value="">Select Value</option>
<option value="">اختر قيمة</option>
{filters.find((filter) =>
filter.title === filterItem?.fields?.selectedField
)?.options?.map((option) => (
@ -328,22 +328,22 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
)?.number ? (
<div className="flex flex-row w-full mr-3">
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">From</div>
<div className=" text-gray-500 font-bold">من</div>
<Field
className={controlClasses}
name='filterValueFrom'
placeholder='From'
placeholder='من'
id='filterValueFrom'
value={filterItem?.fields?.filterValueFrom || ''}
onChange={handleChange(filterItem.id)}
/>
</div>
<div className="flex flex-col w-full">
<div className=" text-gray-500 font-bold">To</div>
<div className=" text-gray-500 font-bold">إلى</div>
<Field
className={controlClasses}
name='filterValueTo'
placeholder='to'
placeholder='إلى'
id='filterValueTo'
value={filterItem?.fields?.filterValueTo || ''}
onChange={handleChange(filterItem.id)}
@ -363,7 +363,7 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
<Field
className={controlClasses}
name='filterValueFrom'
placeholder='From'
placeholder='من'
id='filterValueFrom'
type='datetime-local'
value={filterItem?.fields?.filterValueFrom || ''}
@ -371,11 +371,11 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
/>
</div>
<div className='flex flex-col w-full'>
<div className=' text-gray-500 font-bold'>To</div>
<div className=' text-gray-500 font-bold'>إلى</div>
<Field
className={controlClasses}
name='filterValueTo'
placeholder='to'
placeholder='إلى'
id='filterValueTo'
type='datetime-local'
value={filterItem?.fields?.filterValueTo || ''}
@ -385,11 +385,11 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div>
) : (
<div className="flex flex-col w-full mr-3">
<div className=" text-gray-500 font-bold">Contains</div>
<div className=" text-gray-500 font-bold">يحتوي على</div>
<Field
className={controlClasses}
name='filterValue'
placeholder='Contained'
placeholder='يحتوي على'
id='filterValue'
value={filterItem?.fields?.filterValue || ''}
onChange={handleChange(filterItem.id)}
@ -397,12 +397,12 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
</div>
)}
<div className="flex flex-col">
<div className=" text-gray-500 font-bold">Action</div>
<div className=" text-gray-500 font-bold">الإجراء</div>
<BaseButton
className="my-2"
type='reset'
color='danger'
label='Delete'
label='حذف'
onClick={() => {
deleteFilter(filterItem.id)
}}
@ -415,13 +415,13 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
<BaseButton
className="my-2 mr-3"
color="success"
label='Apply'
label='تطبيق'
onClick={handleSubmit}
/>
<BaseButton
className="my-2"
color='info'
label='Cancel'
label='إلغاء'
onClick={handleReset}
/>
</div>
@ -431,14 +431,14 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
</CardBox> : null
}
<CardBoxModal
title="Please confirm"
title="تأكيد العملية"
buttonColor="info"
buttonLabel={loading ? 'Deleting...' : 'Confirm'}
buttonLabel={loading ? 'جارٍ الحذف...' : 'تأكيد'}
isActive={isModalTrashActive}
onConfirm={handleDeleteAction}
onCancel={handleModalAction}
>
<p>Are you sure you want to delete this item?</p>
<p>هل أنت متأكد أنك تريد حذف هذا العنصر؟</p>
</CardBoxModal>
@ -463,7 +463,7 @@ const TableSampleShops = ({ filterItems, setFilterItems, filters, showGrid }) =>
<BaseButton
className='me-4'
color='danger'
label={`Delete ${selectedRows.length === 1 ? 'Row' : 'Rows'}`}
label={`حذف ${selectedRows.length === 1 ? 'صف واحد' : 'عدة صفوف'}`}
onClick={() => onDeleteRows(selectedRows)}
/>,
document.getElementById('delete-rows-button'),

View File

@ -43,7 +43,7 @@ export const loadColumns = async (
{
field: 'shop_name',
headerName: 'اسمالمتجر',
headerName: 'اسم المحل',
flex: 1,
minWidth: 120,
filterable: false,
@ -58,7 +58,7 @@ export const loadColumns = async (
{
field: 'owner_name',
headerName: 'اسمالمالك',
headerName: 'اسم المالك',
flex: 1,
minWidth: 120,
filterable: false,
@ -73,7 +73,7 @@ export const loadColumns = async (
{
field: 'phone',
headerName: 'هاتفالمتجر',
headerName: 'هاتف المحل',
flex: 1,
minWidth: 120,
filterable: false,
@ -103,7 +103,7 @@ export const loadColumns = async (
{
field: 'currency_name',
headerName: 'اسمالعملةالمحلية',
headerName: 'اسم العملة المحلية',
flex: 1,
minWidth: 120,
filterable: false,
@ -118,7 +118,7 @@ export const loadColumns = async (
{
field: 'usd_rate',
headerName: 'سعرالدولاراليومي',
headerName: 'سعر الدولار اليومي',
flex: 1,
minWidth: 120,
filterable: false,
@ -134,7 +134,7 @@ export const loadColumns = async (
{
field: 'allow_negative_stock',
headerName: 'السماحبمخزونسالب',
headerName: 'السماح بمخزون سالب',
flex: 1,
minWidth: 120,
filterable: false,

View File

@ -0,0 +1,23 @@
export const SALES_INVOICE_STATUS_LABELS: Record<string, string> = {
draft: 'مسودة',
paid: 'مدفوعة',
voided: 'ملغاة',
refunded: 'مسترجعة',
};
export const SALES_INVOICE_PAYMENT_METHOD_LABELS: Record<string, string> = {
cash: 'نقداً',
card: 'بطاقة',
transfer: 'تحويل',
mixed: 'مختلط',
};
export const formatSalesInvoiceStatus = (value?: string | null) => {
if (!value) return 'لا توجد بيانات';
return SALES_INVOICE_STATUS_LABELS[value] ?? value;
};
export const formatSalesInvoicePaymentMethod = (value?: string | null) => {
if (!value) return 'لا توجد بيانات';
return SALES_INVOICE_PAYMENT_METHOD_LABELS[value] ?? value;
};

View File

@ -121,7 +121,7 @@ export default function LayoutAuthenticated({
onAsideLgClose={() => setIsAsideLgActive(false)}
/>
{children}
<FooterBar>Hand-crafted & Made with </FooterBar>
<FooterBar>واجهة مبسطة لإدارة المحل</FooterBar>
</div>
</div>
)

View File

@ -5,110 +5,53 @@ const menuAside: MenuAsideItem[] = [
{
href: '/dashboard',
icon: icon.mdiViewDashboardOutline,
label: 'لوحة التحكم',
},
{
href: '/users/users-list',
label: 'المستخدمون',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiAccountGroup ?? icon.mdiTable,
permissions: 'READ_USERS'
},
{
href: '/roles/roles-list',
label: 'الأدوار',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiShieldAccountVariantOutline ?? icon.mdiTable,
permissions: 'READ_ROLES'
},
{
href: '/permissions/permissions-list',
label: 'الصلاحيات',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiShieldAccountOutline ?? icon.mdiTable,
permissions: 'READ_PERMISSIONS'
},
{
href: '/organizations/organizations-list',
label: 'المنظمات',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_ORGANIZATIONS'
},
{
href: '/shops/shops-list',
label: 'المحلات',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiStorefront' in icon ? icon['mdiStorefront' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_SHOPS'
},
{
href: '/categories/categories-list',
label: 'الأقسام',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiShape' in icon ? icon['mdiShape' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_CATEGORIES'
label: 'الصفحة الرئيسية',
},
{
href: '/cashier',
label: 'الكاشير',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiCashRegister' in icon ? icon['mdiCashRegister' as keyof typeof icon] : ('mdiReceipt' in icon ? icon['mdiReceipt' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable),
permissions: 'READ_PRODUCTS'
icon: 'mdiCashRegister' in icon ? icon['mdiCashRegister' as keyof typeof icon] : ('mdiReceipt' in icon ? icon['mdiReceipt' as keyof typeof icon] : icon.mdiTable),
permissions: 'READ_PRODUCTS',
},
{
href: '/products/products-list',
label: 'المنتجات',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiSprayBottle' in icon ? icon['mdiSprayBottle' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_PRODUCTS'
icon: 'mdiSprayBottle' in icon ? icon['mdiSprayBottle' as keyof typeof icon] : icon.mdiTable,
permissions: 'READ_PRODUCTS',
},
{
href: '/categories/categories-list',
label: 'الأقسام',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiShape' in icon ? icon['mdiShape' as keyof typeof icon] : icon.mdiTable,
permissions: 'READ_CATEGORIES',
},
{
href: '/sales_invoices/sales_invoices-list',
label: 'الفواتير',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiReceipt' in icon ? icon['mdiReceipt' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_SALES_INVOICES'
icon: 'mdiReceipt' in icon ? icon['mdiReceipt' as keyof typeof icon] : icon.mdiTable,
permissions: 'READ_SALES_INVOICES',
},
{
href: '/sales_invoice_items/sales_invoice_items-list',
label: 'عناصر الفواتير',
href: '/shops/shops-list',
label: 'المحل',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiFormatListBulleted' in icon ? icon['mdiFormatListBulleted' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_SALES_INVOICE_ITEMS'
},
{
href: '/price_change_logs/price_change_logs-list',
label: 'سجل الأسعار',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
icon: 'mdiCurrencyUsd' in icon ? icon['mdiCurrencyUsd' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_PRICE_CHANGE_LOGS'
icon: 'mdiStorefront' in icon ? icon['mdiStorefront' as keyof typeof icon] : icon.mdiTable,
permissions: 'READ_SHOPS',
},
{
href: '/profile',
label: 'الملف الشخصي',
icon: icon.mdiAccountCircle,
},
{
href: '/api-docs',
target: '_blank',
label: 'توثيق API',
icon: icon.mdiFileCode,
permissions: 'READ_API_DOCS'
withDevider: true,
},
]

View File

@ -10,6 +10,7 @@ import LoadingSpinner from '../components/LoadingSpinner';
import SectionMain from '../components/SectionMain';
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
import { getPageTitle } from '../config';
import { formatSalesInvoicePaymentMethod } from '../helpers/salesInvoiceLabels';
import { hasPermission } from '../helpers/userPermissions';
import LayoutAuthenticated from '../layouts/Authenticated';
import { useAppSelector } from '../stores/hooks';
@ -410,7 +411,7 @@ const CashierPage = () => {
<div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
<div>
<h2 className="text-xl font-bold text-slate-900">بحث سريع عن المنتجات</h2>
<p className="text-sm text-slate-500">اكتب أول حرف من اسم المنتج أو الباركود أو SKU وستظهر النتائج فوراً بدون إعادة تحميل.</p>
<p className="text-sm text-slate-500">اكتب اسم المنتج أو الباركود أو رمز المنتج، وستظهر النتائج فوراً بدون إعادة تحميل.</p>
</div>
<div className="flex flex-wrap gap-2">
<BaseButton href="/products/products-list" color="info" label="إدارة المنتجات" />
@ -704,7 +705,7 @@ const CashierPage = () => {
<div className="mt-1 text-sm text-slate-500">{formatDateTime(invoice.sold_at)}</div>
</div>
<span className="rounded-full bg-white px-3 py-1 text-xs font-bold text-slate-600 shadow-sm">
{invoice.payment_method}
{formatSalesInvoicePaymentMethod(invoice.payment_method)}
</span>
</div>
<div className="mt-4 grid gap-2 sm:grid-cols-3">

View File

@ -249,10 +249,10 @@ const EditCategories = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit categories')}</title>
<title>{getPageTitle('تعديل القسم')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit categories'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل القسم'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -330,11 +330,11 @@ const EditCategories = () => {
<FormField
label="اسمالقسم"
label="اسم القسم"
>
<Field
name="category_name"
placeholder="اسمالقسم"
placeholder="اسم القسم"
/>
</FormField>
@ -405,12 +405,12 @@ const EditCategories = () => {
<FormField
label="ترتيبالعرض"
label="ترتيب العرض"
>
<Field
type="number"
name="sort_order"
placeholder="ترتيبالعرض"
placeholder="ترتيب العرض"
/>
</FormField>
@ -491,7 +491,7 @@ const EditCategories = () => {
<FormField label='organizations' labelFor='organizations'>
<FormField label='المنظمة' labelFor='organizations'>
<Field
name='organizations'
id='organizations'
@ -538,9 +538,9 @@ const EditCategories = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/categories/categories-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/categories/categories-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -246,10 +246,10 @@ const EditCategoriesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit categories')}</title>
<title>{getPageTitle('تعديل القسم')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit categories'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل القسم'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -327,11 +327,11 @@ const EditCategoriesPage = () => {
<FormField
label="اسمالقسم"
label="اسم القسم"
>
<Field
name="category_name"
placeholder="اسمالقسم"
placeholder="اسم القسم"
/>
</FormField>
@ -402,12 +402,12 @@ const EditCategoriesPage = () => {
<FormField
label="ترتيبالعرض"
label="ترتيب العرض"
>
<Field
type="number"
name="sort_order"
placeholder="ترتيبالعرض"
placeholder="ترتيب العرض"
/>
</FormField>
@ -488,7 +488,7 @@ const EditCategoriesPage = () => {
<FormField label='organizations' labelFor='organizations'>
<FormField label='المنظمة' labelFor='organizations'>
<Field
name='organizations'
id='organizations'
@ -535,9 +535,9 @@ const EditCategoriesPage = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/categories/categories-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/categories/categories-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -34,8 +34,8 @@ const CategoriesTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'اسمالقسم', title: 'category_name'},{label: 'الوصف', title: 'description'},
{label: 'ترتيبالعرض', title: 'sort_order', number: 'true'},
const [filters] = useState([{label: 'اسم القسم', title: 'category_name'},{label: 'الوصف', title: 'description'},
{label: 'ترتيب العرض', title: 'sort_order', number: 'true'},
@ -90,28 +90,28 @@ const CategoriesTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Categories')}</title>
<title>{getPageTitle('الأقسام')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Categories" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الأقسام" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/categories/categories-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/categories/categories-new'} color='info' label='إضافة قسم'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='إضافة تصفية'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getCategoriesCSV} />
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getCategoriesCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
label='Upload CSV'
label='رفع CSV'
onClick={() => setIsModalActive(true)}
/>
)}
@ -133,9 +133,9 @@ const CategoriesTablesPage = () => {
</SectionMain>
<CardBoxModal
title='Upload CSV'
title='رفع CSV'
buttonColor='info'
buttonLabel={'Confirm'}
buttonLabel={'تأكيد'}
// buttonLabel={false ? 'Deleting...' : 'Confirm'}
isActive={isModalActive}
onConfirm={onModalConfirm}

View File

@ -142,10 +142,10 @@ const CategoriesNew = () => {
return (
<>
<Head>
<title>{getPageTitle('New Item')}</title>
<title>{getPageTitle('إضافة قسم')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة قسم" main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -192,11 +192,11 @@ const CategoriesNew = () => {
<FormField
label="اسمالقسم"
label="اسم القسم"
>
<Field
name="category_name"
placeholder="اسمالقسم"
placeholder="اسم القسم"
/>
</FormField>
@ -263,12 +263,12 @@ const CategoriesNew = () => {
<FormField
label="ترتيبالعرض"
label="ترتيب العرض"
>
<Field
type="number"
name="sort_order"
placeholder="ترتيبالعرض"
placeholder="ترتيب العرض"
/>
</FormField>
@ -344,7 +344,7 @@ const CategoriesNew = () => {
<FormField label="organizations" labelFor="organizations">
<FormField label="المنظمة" labelFor="organizations">
<Field name="organizations" id="organizations" component={SelectField} options={[]} itemRef={'organizations'}></Field>
</FormField>
@ -356,9 +356,9 @@ const CategoriesNew = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/categories/categories-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/categories/categories-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -34,8 +34,8 @@ const CategoriesTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'اسمالقسم', title: 'category_name'},{label: 'الوصف', title: 'description'},
{label: 'ترتيبالعرض', title: 'sort_order', number: 'true'},
const [filters] = useState([{label: 'اسم القسم', title: 'category_name'},{label: 'الوصف', title: 'description'},
{label: 'ترتيب العرض', title: 'sort_order', number: 'true'},
@ -90,28 +90,28 @@ const CategoriesTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Categories')}</title>
<title>{getPageTitle('الأقسام')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Categories" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الأقسام" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/categories/categories-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/categories/categories-new'} color='info' label='إضافة قسم'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='إضافة تصفية'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getCategoriesCSV} />
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getCategoriesCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
label='Upload CSV'
label='رفع CSV'
onClick={() => setIsModalActive(true)}
/>
)}
@ -120,7 +120,7 @@ const CategoriesTablesPage = () => {
<div id='delete-rows-button'></div>
<Link href={'/categories/categories-list'}>
Back to <span className='capitalize'>table</span>
العودة إلى <span className='capitalize'>الجدول</span>
</Link>
</div>
@ -135,9 +135,9 @@ const CategoriesTablesPage = () => {
</CardBox>
</SectionMain>
<CardBoxModal
title='Upload CSV'
title='رفع CSV'
buttonColor='info'
buttonLabel={'Confirm'}
buttonLabel={'تأكيد'}
// buttonLabel={false ? 'Deleting...' : 'Confirm'}
isActive={isModalActive}
onConfirm={onModalConfirm}

View File

@ -33,10 +33,6 @@ const CategoriesView = () => {
const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => {
dispatch(fetch({ id }));
@ -46,13 +42,13 @@ const CategoriesView = () => {
return (
<>
<Head>
<title>{getPageTitle('View categories')}</title>
<title>{getPageTitle('تفاصيل القسم')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View categories')} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تفاصيل القسم'} main>
<BaseButton
color='info'
label='Edit'
label='تعديل'
href={`/categories/categories-edit/?id=${id}`}
/>
</SectionTitleLineWithButton>
@ -91,7 +87,7 @@ const CategoriesView = () => {
<p>{categories?.shop?.shop_name ?? 'No data'}</p>
<p>{categories?.shop?.shop_name ?? 'لا توجد بيانات'}</p>
@ -117,7 +113,7 @@ const CategoriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>اسمالقسم</p>
<p className={'block font-bold mb-2'}>اسم القسم</p>
<p>{categories?.category_name}</p>
</div>
@ -150,7 +146,7 @@ const CategoriesView = () => {
<FormField label='Multi Text' hasTextareaHeight>
<FormField label='الوصف' hasTextareaHeight>
<textarea className={'w-full'} disabled value={categories?.description} />
</FormField>
@ -186,8 +182,8 @@ const CategoriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>ترتيبالعرض</p>
<p>{categories?.sort_order || 'No data'}</p>
<p className={'block font-bold mb-2'}>ترتيب العرض</p>
<p>{categories?.sort_order || 'لا توجد بيانات'}</p>
</div>
@ -266,7 +262,7 @@ const CategoriesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>organizations</p>
<p className={'block font-bold mb-2'}>المنظمة</p>
@ -275,7 +271,7 @@ const CategoriesView = () => {
<p>{categories?.organizations?.name ?? 'No data'}</p>
<p>{categories?.organizations?.name ?? 'لا توجد بيانات'}</p>
@ -309,7 +305,7 @@ const CategoriesView = () => {
<>
<p className={'block font-bold mb-2'}>Products القسم</p>
<p className={'block font-bold mb-2'}>منتجات القسم</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -324,11 +320,11 @@ const CategoriesView = () => {
<th>اسمالمنتج</th>
<th>اسم المنتج</th>
<th>رمزالمنتج</th>
<th>رمز المنتج</th>
@ -336,37 +332,37 @@ const CategoriesView = () => {
<th>سعرالتكلفةالحقيقي</th>
<th>سعر التكلفة</th>
<th>سعرالبيع</th>
<th>سعر البيع</th>
<th>سعرالبيعالسابق</th>
<th>سعر البيع السابق</th>
<th>سعرالتكلفةالسابق</th>
<th>سعر التكلفة السابق</th>
<th>السعربالدولار</th>
<th>السعر بالدولار</th>
<th>الكميةبالمخزون</th>
<th>الكمية بالمخزون</th>
<th>حدالتنبيهلنقصالمخزون</th>
<th>حد التنبيه لنقص المخزون</th>
<th>متاحللبيع</th>
<th>متاح للبيع</th>
</tr>
@ -381,61 +377,61 @@ const CategoriesView = () => {
<td data-label="product_name">
<td data-label="اسم المنتج">
{ item.product_name }
</td>
<td data-label="sku">
<td data-label="رمز المنتج">
{ item.sku }
</td>
<td data-label="barcode">
<td data-label="الباركود">
{ item.barcode }
</td>
<td data-label="cost_price">
<td data-label="سعر التكلفة">
{ item.cost_price }
</td>
<td data-label="sale_price">
<td data-label="سعر البيع">
{ item.sale_price }
</td>
<td data-label="sale_price_backup">
<td data-label="سعر البيع السابق">
{ item.sale_price_backup }
</td>
<td data-label="cost_price_backup">
<td data-label="سعر التكلفة السابق">
{ item.cost_price_backup }
</td>
<td data-label="usd_price">
<td data-label="السعر بالدولار">
{ item.usd_price }
</td>
<td data-label="stock_quantity">
<td data-label="الكمية بالمخزون">
{ item.stock_quantity }
</td>
<td data-label="low_stock_threshold">
<td data-label="حد التنبيه لنقص المخزون">
{ item.low_stock_threshold }
</td>
@ -443,7 +439,7 @@ const CategoriesView = () => {
<td data-label="is_active">
<td data-label="الحالة">
{ dataFormatter.booleanFormatter(item.is_active) }
</td>
@ -453,7 +449,7 @@ const CategoriesView = () => {
</tbody>
</table>
</div>
{!categories?.products_category?.length && <div className={'text-center py-4'}>No data</div>}
{!categories?.products_category?.length && <div className={'text-center py-4'}>لا توجد بيانات</div>}
</CardBox>
</>
@ -466,7 +462,7 @@ const CategoriesView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/categories/categories-list')}
/>
</CardBox>

View File

@ -1,441 +1,388 @@
import * as icon from '@mdi/js';
import Head from 'next/head'
import React from 'react'
import { mdiChartTimelineVariant } from '@mdi/js';
import Head from 'next/head';
import Link from 'next/link';
import React, { ReactElement, useEffect, useMemo, useState } from 'react';
import axios from 'axios';
import type { ReactElement } from 'react'
import LayoutAuthenticated from '../layouts/Authenticated'
import SectionMain from '../components/SectionMain'
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton'
import BaseIcon from "../components/BaseIcon";
import { getPageTitle } from '../config'
import Link from "next/link";
import { hasPermission } from "../helpers/userPermissions";
import { fetchWidgets } from '../stores/roles/rolesSlice';
import { WidgetCreator } from '../components/WidgetCreator/WidgetCreator';
import { SmartWidget } from '../components/SmartWidget/SmartWidget';
import BaseButton from '../components/BaseButton';
import CardBox from '../components/CardBox';
import LoadingSpinner from '../components/LoadingSpinner';
import SectionMain from '../components/SectionMain';
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
import { getPageTitle } from '../config';
import { formatSalesInvoicePaymentMethod } from '../helpers/salesInvoiceLabels';
import { hasPermission } from '../helpers/userPermissions';
import LayoutAuthenticated from '../layouts/Authenticated';
import { useAppSelector } from '../stores/hooks';
type PosSummary = {
totalSales: number;
totalProfit: number;
invoiceCount: number;
};
type PosInvoice = {
id: string;
invoice_number: string;
sold_at: string;
total_amount: number;
total_profit_amount: number;
payment_method: string;
item_count: number;
cashier_name: string;
};
type PosWorkspace = {
selectedShop: {
id: string;
shop_name: string;
currency_name: string;
usd_rate: number;
} | null;
summary: PosSummary;
recentInvoices: PosInvoice[];
};
const emptyWorkspace: PosWorkspace = {
selectedShop: null,
summary: {
totalSales: 0,
totalProfit: 0,
invoiceCount: 0,
},
recentInvoices: [],
};
const formatMoney = (value: number) => `${new Intl.NumberFormat('ar-IQ').format(value || 0)} د.ع`;
const formatNumber = (value: number) => new Intl.NumberFormat('ar-IQ').format(value || 0);
const formatDateTime = (value?: string) => {
if (!value) {
return '--';
}
return new Date(value).toLocaleString('ar-IQ', {
hour: '2-digit',
minute: '2-digit',
year: 'numeric',
month: 'short',
day: 'numeric',
});
};
import { useAppDispatch, useAppSelector } from '../stores/hooks';
const Dashboard = () => {
const dispatch = useAppDispatch();
const iconsColor = useAppSelector((state) => state.style.iconsColor);
const corners = useAppSelector((state) => state.style.corners);
const cardsStyle = useAppSelector((state) => state.style.cardsStyle);
const { currentUser } = useAppSelector((state) => state.auth);
const corners = useAppSelector((state) => state.style.corners);
const loadingMessage = 'Loading...';
const [workspace, setWorkspace] = useState<PosWorkspace>(emptyWorkspace);
const [loading, setLoading] = useState(true);
const [errorMessage, setErrorMessage] = useState('');
const [users, setUsers] = React.useState(loadingMessage);
const [roles, setRoles] = React.useState(loadingMessage);
const [permissions, setPermissions] = React.useState(loadingMessage);
const [organizations, setOrganizations] = React.useState(loadingMessage);
const [shops, setShops] = React.useState(loadingMessage);
const [categories, setCategories] = React.useState(loadingMessage);
const [products, setProducts] = React.useState(loadingMessage);
const [sales_invoices, setSales_invoices] = React.useState(loadingMessage);
const [sales_invoice_items, setSales_invoice_items] = React.useState(loadingMessage);
const [price_change_logs, setPrice_change_logs] = React.useState(loadingMessage);
const canReadProducts = hasPermission(currentUser, 'READ_PRODUCTS');
const canReadInvoices = hasPermission(currentUser, 'READ_SALES_INVOICES');
const canReadShops = hasPermission(currentUser, 'READ_SHOPS');
const [widgetsRole, setWidgetsRole] = React.useState({
role: { value: '', label: '' },
});
const { currentUser } = useAppSelector((state) => state.auth);
const { isFetchingQuery } = useAppSelector((state) => state.openAi);
const { rolesWidgets, loading } = useAppSelector((state) => state.roles);
const organizationId = currentUser?.organizations?.id;
async function loadData() {
const entities = ['users','roles','permissions','organizations','shops','categories','products','sales_invoices','sales_invoice_items','price_change_logs',];
const fns = [setUsers,setRoles,setPermissions,setOrganizations,setShops,setCategories,setProducts,setSales_invoices,setSales_invoice_items,setPrice_change_logs,];
const requests = entities.map((entity, index) => {
if(hasPermission(currentUser, `READ_${entity.toUpperCase()}`)) {
return axios.get(`/${entity.toLowerCase()}/count`);
} else {
fns[index](null);
return Promise.resolve({data: {count: null}});
}
});
Promise.allSettled(requests).then((results) => {
results.forEach((result, i) => {
if (result.status === 'fulfilled') {
fns[i](result.value.data.count);
} else {
fns[i](result.reason.message);
}
});
});
useEffect(() => {
if (!currentUser) {
return;
}
async function getWidgets(roleId) {
await dispatch(fetchWidgets(roleId));
}
React.useEffect(() => {
if (!currentUser) return;
loadData().then();
setWidgetsRole({ role: { value: currentUser?.app_role?.id, label: currentUser?.app_role?.name } });
}, [currentUser]);
React.useEffect(() => {
if (!currentUser || !widgetsRole?.role?.value) return;
getWidgets(widgetsRole?.role?.value || '').then();
}, [widgetsRole?.role?.value]);
if (!canReadProducts) {
setLoading(false);
return;
}
const loadWorkspace = async () => {
setLoading(true);
setErrorMessage('');
try {
const { data } = await axios.get('/pos/workspace');
setWorkspace({
selectedShop: data.selectedShop || null,
summary: data.summary || emptyWorkspace.summary,
recentInvoices: Array.isArray(data.recentInvoices) ? data.recentInvoices : [],
});
} catch (error: any) {
console.error('Dashboard workspace load failed:', error);
setErrorMessage(error?.response?.data || 'تعذر تحميل ملخص اليوم الآن.');
} finally {
setLoading(false);
}
};
loadWorkspace();
}, [canReadProducts, currentUser]);
const quickActions = useMemo(
() => [
{
href: '/cashier',
label: 'فتح الكاشير',
description: 'ابدأ عملية بيع جديدة بسرعة وابحث عن المنتج مباشرة.',
visible: canReadProducts,
},
{
href: '/products/products-list',
label: 'إدارة المنتجات',
description: 'أضف المنتجات وعدّل الأسعار والكميات من مكان واحد.',
visible: canReadProducts,
},
{
href: '/sales_invoices/sales_invoices-list',
label: 'مراجعة الفواتير',
description: 'تابع المبيعات اليومية وشاهد الأرباح وتفاصيل كل فاتورة.',
visible: canReadInvoices,
},
{
href: '/shops/shops-list',
label: 'إعدادات المحل',
description: 'حدّث بيانات المحل والعملة وسعر الدولار اليومي.',
visible: canReadShops,
},
].filter((item) => item.visible),
[canReadInvoices, canReadProducts, canReadShops],
);
const startSteps = useMemo(
() => [
'أضف المنتجات مع سعر التكلفة وسعر البيع والكمية.',
'افتح شاشة الكاشير واختر المنتجات المطلوبة بسرعة.',
'احفظ الفاتورة ثم راقب ملخص اليوم من هذه الصفحة.',
],
[],
);
const stats = useMemo(
() => [
{
label: 'المحل الحالي',
value: workspace.selectedShop?.shop_name || 'غير محدد بعد',
hint: workspace.selectedShop?.currency_name || 'أضف محلًا واحدًا للبدء',
cardClassName: 'border border-emerald-100 bg-white shadow-sm shadow-emerald-100/70',
},
{
label: 'مبيعات اليوم',
value: formatMoney(workspace.summary.totalSales),
hint: 'إجمالي قيمة الفواتير المدفوعة اليوم',
cardClassName: 'border border-sky-100 bg-white shadow-sm shadow-sky-100/70',
},
{
label: 'ربح اليوم',
value: formatMoney(workspace.summary.totalProfit),
hint: 'صافي الفرق بين سعر البيع وسعر التكلفة',
cardClassName: 'border border-violet-100 bg-white shadow-sm shadow-violet-100/70',
},
{
label: 'عدد الفواتير اليوم',
value: formatNumber(workspace.summary.invoiceCount),
hint: 'عدد عمليات البيع المسجلة اليوم',
cardClassName: 'border border-amber-100 bg-white shadow-sm shadow-amber-100/70',
},
],
[workspace],
);
const welcomeName = currentUser?.firstName || 'بك';
const primaryAction = quickActions[0];
const usdRate = workspace.selectedShop?.usd_rate ? formatNumber(workspace.selectedShop.usd_rate) : '--';
return (
<>
<Head>
<title>
{getPageTitle('Overview')}
</title>
<title>{getPageTitle('الواجهة الرئيسية')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton
icon={icon.mdiChartTimelineVariant}
title='Overview'
main>
icon={mdiChartTimelineVariant}
title="الواجهة الرئيسية"
main
>
{''}
</SectionTitleLineWithButton>
{hasPermission(currentUser, 'CREATE_ROLES') && <WidgetCreator
currentUser={currentUser}
isFetchingQuery={isFetchingQuery}
setWidgetsRole={setWidgetsRole}
widgetsRole={widgetsRole}
/>}
{!!rolesWidgets.length &&
hasPermission(currentUser, 'CREATE_ROLES') && (
<p className=' text-gray-500 dark:text-gray-400 mb-4'>
{`${widgetsRole?.role?.label || 'Users'}'s widgets`}
</p>
)}
<div className='grid grid-cols-1 gap-6 lg:grid-cols-4 mb-6 grid-flow-dense'>
{(isFetchingQuery || loading) && (
<div className={` ${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 text-lg leading-tight text-gray-500 flex items-center ${cardsStyle} dark:border-dark-700 p-6`}>
<BaseIcon
className={`${iconsColor} animate-spin mr-5`}
w='w-16'
h='h-16'
size={48}
path={icon.mdiLoading}
/>{' '}
Loading widgets...
<div className="mb-6 grid gap-6 xl:grid-cols-[1.2fr,0.8fr]">
<CardBox className="border border-emerald-100 bg-gradient-to-l from-white via-emerald-50 to-sky-50 shadow-lg shadow-emerald-100/60">
<div className="space-y-5">
<div className="flex flex-wrap items-start justify-between gap-3">
<div>
<span className="inline-flex rounded-full border border-emerald-200 bg-white px-3 py-1 text-xs font-bold text-emerald-700">
ملخص سريع وواضح لعمل اليوم
</span>
<h2 className="mt-3 text-3xl font-extrabold text-slate-950">أهلاً {welcomeName}</h2>
<p className="mt-2 max-w-2xl text-sm leading-7 text-slate-600">
هذه الصفحة تجمع لك أهم ما تحتاجه: حالة المحل الحالية، أرقام اليوم، وروابط سريعة للمنتجات والكاشير والفواتير.
</p>
</div>
)}
{ rolesWidgets &&
rolesWidgets.map((widget) => (
<SmartWidget
key={widget.id}
userId={currentUser?.id}
widget={widget}
roleId={widgetsRole?.role?.value || ''}
admin={hasPermission(currentUser, 'CREATE_ROLES')}
/>
))}
{primaryAction ? (
<BaseButton
href={primaryAction.href}
color="success"
label={primaryAction.label}
className="!px-5 !py-3 font-bold"
/>
) : null}
</div>
<div className="grid gap-3 md:grid-cols-3">
<div className={`${corners !== 'rounded-full' ? corners : 'rounded-3xl'} border border-white bg-white/90 px-4 py-4`}>
<div className="text-xs font-bold text-slate-500">المحل</div>
<div className="mt-2 text-lg font-extrabold text-slate-900">{workspace.selectedShop?.shop_name || 'غير محدد بعد'}</div>
</div>
<div className={`${corners !== 'rounded-full' ? corners : 'rounded-3xl'} border border-white bg-white/90 px-4 py-4`}>
<div className="text-xs font-bold text-slate-500">سعر الدولار اليومي</div>
<div className="mt-2 text-lg font-extrabold text-slate-900">{usdRate}</div>
</div>
<div className={`${corners !== 'rounded-full' ? corners : 'rounded-3xl'} border border-white bg-white/90 px-4 py-4`}>
<div className="text-xs font-bold text-slate-500">الروابط السريعة</div>
<div className="mt-2 text-lg font-extrabold text-slate-900">{formatNumber(quickActions.length)}</div>
</div>
</div>
</div>
</CardBox>
<CardBox className="border border-slate-100 bg-white shadow-lg shadow-slate-100/70">
<div className="space-y-4">
<div>
<h3 className="text-xl font-bold text-slate-900">ابدأ من هنا</h3>
<p className="mt-1 text-sm leading-6 text-slate-500">
رتّبت الواجهة لتكون بسيطة: أضف البيانات مرة واحدة، ثم استخدم الكاشير، وبعدها راقب النتائج يوميًا.
</p>
</div>
<div className="space-y-3">
{startSteps.map((step, index) => (
<div
key={step}
className={`${corners !== 'rounded-full' ? corners : 'rounded-3xl'} flex items-start gap-3 border border-slate-100 bg-slate-50 px-4 py-3`}
>
<span className="mt-0.5 inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-full bg-emerald-100 text-sm font-extrabold text-emerald-700">
{index + 1}
</span>
<p className="text-sm font-medium leading-6 text-slate-700">{step}</p>
</div>
))}
</div>
{primaryAction ? (
<BaseButton href={primaryAction.href} color="info" label={`الانتقال إلى ${primaryAction.label}`} />
) : null}
</div>
</CardBox>
</div>
{!!rolesWidgets.length && <hr className='my-6 ' />}
<div id="dashboard" className='grid grid-cols-1 gap-6 lg:grid-cols-3 mb-6'>
{hasPermission(currentUser, 'READ_USERS') && <Link href={'/users/users-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Users
</div>
<div className="text-3xl leading-tight font-semibold">
{users}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={icon.mdiAccountGroup || icon.mdiTable}
/>
</div>
</div>
{errorMessage ? (
<div className="mb-6 rounded-2xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
{errorMessage}
</div>
) : null}
<div className="mb-6 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
{stats.map((item) => (
<CardBox key={item.label} className={item.cardClassName}>
<div className="text-sm font-bold text-slate-500">{item.label}</div>
<div className="mt-2 text-2xl font-extrabold text-slate-900">{item.value}</div>
<div className="mt-1 text-xs text-slate-500">{item.hint}</div>
</CardBox>
))}
</div>
<div className="grid gap-6 xl:grid-cols-[0.92fr,1.08fr]">
<CardBox className="border border-slate-100 bg-white shadow-lg shadow-slate-100/70">
<div className="space-y-4">
<div className="flex items-start justify-between gap-3">
<div>
<h3 className="text-xl font-bold text-slate-900">الصفحات المهمة</h3>
<p className="mt-1 text-sm text-slate-500">
هذه أهم الروابط اليومية بعد تنظيف القائمة الجانبية وتبسيط الواجهة.
</p>
</div>
</Link>}
{hasPermission(currentUser, 'READ_ROLES') && <Link href={'/roles/roles-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Roles
</div>
<div className="text-3xl leading-tight font-semibold">
{roles}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={icon.mdiShieldAccountVariantOutline || icon.mdiTable}
/>
</div>
</div>
<span className="rounded-full bg-slate-100 px-3 py-1 text-xs font-bold text-slate-600">
{formatNumber(quickActions.length)} روابط
</span>
</div>
{!quickActions.length ? (
<div className="rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500">
لا توجد صفحات متاحة لك حاليًا حسب الصلاحيات.
</div>
</Link>}
{hasPermission(currentUser, 'READ_PERMISSIONS') && <Link href={'/permissions/permissions-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Permissions
</div>
<div className="text-3xl leading-tight font-semibold">
{permissions}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={icon.mdiShieldAccountOutline || icon.mdiTable}
/>
</div>
</div>
) : (
<div className="grid gap-3">
{quickActions.map((item) => (
<Link
key={item.href}
href={item.href}
className={`${corners !== 'rounded-full' ? corners : 'rounded-3xl'} block border border-slate-100 bg-slate-50 px-4 py-4 transition hover:border-emerald-200 hover:bg-emerald-50/60`}
>
<div className="text-base font-bold text-slate-900">{item.label}</div>
<div className="mt-1 text-sm leading-6 text-slate-600">{item.description}</div>
</Link>
))}
</div>
</Link>}
{hasPermission(currentUser, 'READ_ORGANIZATIONS') && <Link href={'/organizations/organizations-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Organizations
</div>
<div className="text-3xl leading-tight font-semibold">
{organizations}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={icon.mdiTable || icon.mdiTable}
/>
</div>
</div>
)}
</div>
</CardBox>
<CardBox className="border border-slate-100 bg-white shadow-lg shadow-slate-100/70">
<div className="space-y-4">
<div className="flex items-center justify-between gap-3">
<div>
<h3 className="text-xl font-bold text-slate-900">آخر فواتير اليوم</h3>
<p className="mt-1 text-sm text-slate-500">لمتابعة حركة البيع بسرعة من نفس الواجهة.</p>
</div>
</Link>}
{hasPermission(currentUser, 'READ_SHOPS') && <Link href={'/shops/shops-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Shops
</div>
<div className="text-3xl leading-tight font-semibold">
{shops}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={'mdiStorefront' in icon ? icon['mdiStorefront' as keyof typeof icon] : icon.mdiTable || icon.mdiTable}
/>
</div>
</div>
{canReadInvoices && (
<BaseButton href="/sales_invoices/sales_invoices-list" color="info" label="كل الفواتير" small />
)}
</div>
{loading ? (
<LoadingSpinner />
) : !workspace.recentInvoices.length ? (
<div className="rounded-2xl border border-dashed border-slate-200 bg-slate-50 px-4 py-8 text-center text-sm text-slate-500">
لا توجد فواتير مدفوعة اليوم حتى الآن.
</div>
</Link>}
{hasPermission(currentUser, 'READ_CATEGORIES') && <Link href={'/categories/categories-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
) : (
<div className="space-y-3">
{workspace.recentInvoices.slice(0, 6).map((invoice) => (
<div
key={invoice.id}
className={`${corners !== 'rounded-full' ? corners : 'rounded-3xl'} border border-slate-100 bg-slate-50 px-4 py-4`}
>
<div className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Categories
</div>
<div className="text-3xl leading-tight font-semibold">
{categories}
</div>
<div className="text-sm font-bold text-slate-900">{invoice.invoice_number}</div>
<div className="mt-1 text-xs text-slate-500">
{formatDateTime(invoice.sold_at)}
{invoice.cashier_name ? `${invoice.cashier_name}` : ''}
</div>
<div className="mt-2 inline-flex rounded-full bg-white px-3 py-1 text-xs font-bold text-slate-600">
{formatSalesInvoicePaymentMethod(invoice.payment_method)}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={'mdiShape' in icon ? icon['mdiShape' as keyof typeof icon] : icon.mdiTable || icon.mdiTable}
/>
<div className="grid gap-1 text-sm lg:text-left">
<div className="font-bold text-slate-900">الإجمالي: {formatMoney(invoice.total_amount)}</div>
<div className="text-slate-600">الربح: {formatMoney(invoice.total_profit_amount)}</div>
<div className="text-slate-500">عدد القطع: {formatNumber(invoice.item_count || 0)}</div>
</div>
</div>
</div>
))}
</div>
</Link>}
{hasPermission(currentUser, 'READ_PRODUCTS') && <Link href={'/products/products-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Products
</div>
<div className="text-3xl leading-tight font-semibold">
{products}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={'mdiSprayBottle' in icon ? icon['mdiSprayBottle' as keyof typeof icon] : icon.mdiTable || icon.mdiTable}
/>
</div>
</div>
</div>
</Link>}
{hasPermission(currentUser, 'READ_SALES_INVOICES') && <Link href={'/sales_invoices/sales_invoices-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Sales invoices
</div>
<div className="text-3xl leading-tight font-semibold">
{sales_invoices}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={'mdiReceipt' in icon ? icon['mdiReceipt' as keyof typeof icon] : icon.mdiTable || icon.mdiTable}
/>
</div>
</div>
</div>
</Link>}
{hasPermission(currentUser, 'READ_SALES_INVOICE_ITEMS') && <Link href={'/sales_invoice_items/sales_invoice_items-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Sales invoice items
</div>
<div className="text-3xl leading-tight font-semibold">
{sales_invoice_items}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={'mdiFormatListBulleted' in icon ? icon['mdiFormatListBulleted' as keyof typeof icon] : icon.mdiTable || icon.mdiTable}
/>
</div>
</div>
</div>
</Link>}
{hasPermission(currentUser, 'READ_PRICE_CHANGE_LOGS') && <Link href={'/price_change_logs/price_change_logs-list'}>
<div
className={`${corners !== 'rounded-full'? corners : 'rounded-3xl'} dark:bg-dark-900 ${cardsStyle} dark:border-dark-700 p-6`}
>
<div className="flex justify-between align-center">
<div>
<div className="text-lg leading-tight text-gray-500 dark:text-gray-400">
Price change logs
</div>
<div className="text-3xl leading-tight font-semibold">
{price_change_logs}
</div>
</div>
<div>
<BaseIcon
className={`${iconsColor}`}
w="w-16"
h="h-16"
size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
path={'mdiCurrencyUsd' in icon ? icon['mdiCurrencyUsd' as keyof typeof icon] : icon.mdiTable || icon.mdiTable}
/>
</div>
</div>
</div>
</Link>}
)}
</div>
</CardBox>
</div>
</SectionMain>
</>
)
}
);
};
Dashboard.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated>{page}</LayoutAuthenticated>
}
return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
};
export default Dashboard
export default Dashboard;

View File

@ -22,23 +22,23 @@ export default function Forgot() {
const handleSubmit = async (value) => {
setLoading(true)
try {
const { data: response } = await axios.post('/auth/send-password-reset-email', value);
await axios.post('/auth/send-password-reset-email', value);
setLoading(false)
notify('success', 'Please check your email for verification link');
notify('success', 'تم إرسال رابط إعادة التعيين إلى بريدك الإلكتروني.');
setTimeout(async () => {
await router.push('/login')
}, 3000)
} catch (error) {
setLoading(false)
console.log('error: ', error)
notify('error', 'Something was wrong. Try again')
console.error('Password reset request failed:', error)
notify('error', 'حدث خطأ. حاول مرة أخرى.')
}
};
return (
<>
<Head>
<title>{getPageTitle('Login')}</title>
<title>{getPageTitle('استعادة كلمة المرور')}</title>
</Head>
<SectionFullScreen bg='violet'>
@ -50,7 +50,7 @@ export default function Forgot() {
onSubmit={(values) => handleSubmit(values)}
>
<Form>
<FormField label='Email' help='Please enter your email'>
<FormField label='البريد الإلكتروني' help='أدخل بريدك الإلكتروني لإرسال رابط إعادة التعيين'>
<Field name='email' />
</FormField>
@ -59,12 +59,12 @@ export default function Forgot() {
<BaseButtons>
<BaseButton
type='submit'
label={loading ? 'Loading...' : 'Submit' }
label={loading ? 'جارٍ الإرسال...' : 'إرسال الرابط' }
color='info'
/>
<BaseButton
href={'/login'}
label={'Login'}
label={'العودة لتسجيل الدخول'}
color='info'
/>
</BaseButtons>

View File

@ -44,7 +44,7 @@ export default function Login() {
password: '0897e59a',
remember: true })
const title = 'Multi-Client Detergents POS'
const title = 'نظام مبيعات محل المنظفات'
// Fetch Pexels image/video
useEffect( () => {
@ -109,8 +109,7 @@ export default function Login() {
backgroundRepeat: 'no-repeat',
}}>
<div className="flex justify-center w-full bg-blue-300/20">
<a className="text-[8px]" href={image?.photographer_url} target="_blank" rel="noreferrer">Photo
by {image?.photographer} on Pexels</a>
<a className="text-[8px]" href={image?.photographer_url} target="_blank" rel="noreferrer">الصورة بعدسة {image?.photographer} عبر Pexels</a>
</div>
</div>
)
@ -126,7 +125,7 @@ export default function Login() {
muted
>
<source src={video.video_files[0]?.link} type='video/mp4'/>
Your browser does not support the video tag.
متصفحك لا يدعم تشغيل الفيديو.
</video>
<div className='flex justify-center w-full bg-blue-300/20 z-10'>
<a
@ -135,7 +134,7 @@ export default function Login() {
target='_blank'
rel='noreferrer'
>
Video by {video.user.name} on Pexels
الفيديو بواسطة {video.user.name} عبر Pexels
</a>
</div>
</div>)
@ -154,7 +153,7 @@ export default function Login() {
backgroundRepeat: 'no-repeat',
} : {}}>
<Head>
<title>{getPageTitle('Login')}</title>
<title>{getPageTitle('تسجيل الدخول')}</title>
</Head>
<SectionFullScreen bg='violet'>
@ -170,25 +169,25 @@ export default function Login() {
<div className='flex flex-row text-gray-500 justify-between'>
<div>
<p className='mb-2'>Use{' '}
<p className='mb-2'>استخدم{' '}
<code className={`cursor-pointer ${textColor} `}
data-password="0897e59a"
onClick={(e) => setLogin(e.target)}>super_admin@flatlogic.com</code>{' / '}
<code className={`${textColor}`}>0897e59a</code>{' / '}
to login as Super Admin</p>
للدخول كمدير عام</p>
<p className='mb-2'>Use{' '}
<p className='mb-2'>استخدم{' '}
<code className={`cursor-pointer ${textColor} `}
data-password="0897e59a"
onClick={(e) => setLogin(e.target)}>admin@flatlogic.com</code>{' / '}
<code className={`${textColor}`}>0897e59a</code>{' / '}
to login as Admin</p>
<p>Use <code
للدخول كمدير</p>
<p>استخدم <code
className={`cursor-pointer ${textColor} `}
data-password="c72eaa09f2c5"
onClick={(e) => setLogin(e.target)}>client@hello.com</code>{' / '}
<code className={`${textColor}`}>c72eaa09f2c5</code>{' / '}
to login as User</p>
للدخول كمستخدم</p>
</div>
<div>
<BaseIcon
@ -210,15 +209,15 @@ export default function Login() {
>
<Form>
<FormField
label='Login'
help='Please enter your login'>
label='البريد الإلكتروني'
help='أدخل بريدك الإلكتروني'>
<Field name='email' />
</FormField>
<div className='relative'>
<FormField
label='Password'
help='Please enter your password'>
label='كلمة المرور'
help='أدخل كلمة المرور'>
<Field name='password' type={showPassword ? 'text' : 'password'} />
</FormField>
<div
@ -234,12 +233,12 @@ export default function Login() {
</div>
<div className={'flex justify-between'}>
<FormCheckRadio type='checkbox' label='Remember'>
<FormCheckRadio type='checkbox' label='تذكرني'>
<Field type='checkbox' name='remember' />
</FormCheckRadio>
<Link className={`${textColor} text-blue-600`} href={'/forgot'}>
Forgot password?
نسيت كلمة المرور؟
</Link>
</div>
@ -249,16 +248,16 @@ export default function Login() {
<BaseButton
className={'w-full'}
type='submit'
label={isFetching ? 'Loading...' : 'Login'}
label={isFetching ? 'جارٍ تسجيل الدخول...' : 'تسجيل الدخول'}
color='info'
disabled={isFetching}
/>
</BaseButtons>
<br />
<p className={'text-center'}>
Dont have an account yet?{' '}
ليس لديك حساب بعد؟{' '}
<Link className={`${textColor}`} href={'/register'}>
New Account
إنشاء حساب جديد
</Link>
</p>
</Form>
@ -268,9 +267,9 @@ export default function Login() {
</div>
</SectionFullScreen>
<div className='bg-black text-white flex flex-col text-center justify-center md:flex-row'>
<p className='py-6 text-sm'>© 2026 <span>{title}</span>. © All rights reserved</p>
<p className='py-6 text-sm'>© 2026 <span>{title}</span>. جميع الحقوق محفوظة</p>
<Link className='py-6 ml-4 text-sm' href='/privacy-policy/'>
Privacy Policy
سياسة الخصوصية
</Link>
</div>
<ToastContainer />

View File

@ -389,7 +389,7 @@ const OrganizationsView = () => {
<th>رمزالمنتج</th>
<th>رمز المنتج</th>
@ -401,11 +401,11 @@ const OrganizationsView = () => {
<th>سعرالبيع</th>
<th>سعر البيع</th>
<th>سعرالبيعالسابق</th>
<th>سعر البيعالسابق</th>
@ -427,7 +427,7 @@ const OrganizationsView = () => {
<th>متاحللبيع</th>
<th>متاح للبيع</th>
</tr>
@ -535,11 +535,11 @@ const OrganizationsView = () => {
<th>رقمالفاتورة</th>
<th>رقم الفاتورة</th>
<th>تاريخووقتالبيع</th>
<th>تاريخ ووقت البيع</th>
@ -547,7 +547,7 @@ const OrganizationsView = () => {
<th>الإجماليقبلالخصم</th>
<th>الإجمالي قبل الخصم</th>
@ -555,19 +555,19 @@ const OrganizationsView = () => {
<th>الإجماليالنهائي</th>
<th>الإجمالي النهائي</th>
<th>إجماليالتكلفة</th>
<th>إجمالي التكلفة</th>
<th>إجماليالربح</th>
<th>إجمالي الربح</th>
<th>طريقةالدفع</th>
<th>طريقة الدفع</th>
@ -683,7 +683,7 @@ const OrganizationsView = () => {
<th>سعرالبيعوقتالبيع</th>
<th>سعر البيعوقتالبيع</th>
@ -846,7 +846,7 @@ const OrganizationsView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/organizations/organizations-list')}
/>
</CardBox>

View File

@ -107,7 +107,7 @@ const PermissionsView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/permissions/permissions-list')}
/>
</CardBox>

View File

@ -91,7 +91,7 @@ const Price_change_logsView = () => {
<p>{price_change_logs?.shop?.shop_name ?? 'No data'}</p>
<p>{price_change_logs?.shop?.shop_name ?? 'لا توجد بيانات'}</p>
@ -139,7 +139,7 @@ const Price_change_logsView = () => {
<p className={'block font-bold mb-2'}>تمالتغييربواسطة</p>
<p>{price_change_logs?.changed_by?.firstName ?? 'No data'}</p>
<p>{price_change_logs?.changed_by?.firstName ?? 'لا توجد بيانات'}</p>
@ -228,7 +228,7 @@ const Price_change_logsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>نوعالتغيير</p>
<p>{price_change_logs?.change_type ?? 'No data'}</p>
<p>{price_change_logs?.change_type ?? 'لا توجد بيانات'}</p>
</div>
@ -252,7 +252,7 @@ const Price_change_logsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>سعرالدولارقبل</p>
<p>{price_change_logs?.usd_rate_before || 'No data'}</p>
<p>{price_change_logs?.usd_rate_before || 'لا توجد بيانات'}</p>
</div>
@ -284,7 +284,7 @@ const Price_change_logsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>سعرالدولاربعد</p>
<p>{price_change_logs?.usd_rate_after || 'No data'}</p>
<p>{price_change_logs?.usd_rate_after || 'لا توجد بيانات'}</p>
</div>
@ -368,7 +368,7 @@ const Price_change_logsView = () => {
<p>{price_change_logs?.organizations?.name ?? 'No data'}</p>
<p>{price_change_logs?.organizations?.name ?? 'لا توجد بيانات'}</p>
@ -410,7 +410,7 @@ const Price_change_logsView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/price_change_logs/price_change_logs-list')}
/>
</CardBox>

View File

@ -501,10 +501,10 @@ const EditProducts = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit products')}</title>
<title>{getPageTitle('تعديل المنتج')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit products'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل المنتج'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -646,11 +646,11 @@ const EditProducts = () => {
<FormField
label="اسمالمنتج"
label="اسم المنتج"
>
<Field
name="product_name"
placeholder="اسمالمنتج"
placeholder="اسم المنتج"
/>
</FormField>
@ -683,11 +683,11 @@ const EditProducts = () => {
<FormField
label="رمزالمنتج"
label="رمز المنتج"
>
<Field
name="sku"
placeholder="رمزالمنتج"
placeholder="رمز المنتج"
/>
</FormField>
@ -763,12 +763,12 @@ const EditProducts = () => {
<FormField
label="سعرالتكلفةالحقيقي"
label="سعر التكلفة"
>
<Field
type="number"
name="cost_price"
placeholder="سعرالتكلفةالحقيقي"
placeholder="سعر التكلفة"
/>
</FormField>
@ -801,12 +801,12 @@ const EditProducts = () => {
<FormField
label="سعرالبيع"
label="سعر البيع"
>
<Field
type="number"
name="sale_price"
placeholder="سعرالبيع"
placeholder="سعر البيع"
/>
</FormField>
@ -839,12 +839,12 @@ const EditProducts = () => {
<FormField
label="سعرالبيعالسابق"
label="سعر البيع السابق"
>
<Field
type="number"
name="sale_price_backup"
placeholder="سعرالبيعالسابق"
placeholder="سعر البيع السابق"
/>
</FormField>
@ -877,12 +877,12 @@ const EditProducts = () => {
<FormField
label="سعرالتكلفةالسابق"
label="سعر التكلفة السابق"
>
<Field
type="number"
name="cost_price_backup"
placeholder="سعرالتكلفةالسابق"
placeholder="سعر التكلفة السابق"
/>
</FormField>
@ -915,12 +915,12 @@ const EditProducts = () => {
<FormField
label="السعربالدولار"
label="السعر بالدولار"
>
<Field
type="number"
name="usd_price"
placeholder="السعربالدولار"
placeholder="السعر بالدولار"
/>
</FormField>
@ -953,12 +953,12 @@ const EditProducts = () => {
<FormField
label="الكميةبالمخزون"
label="الكمية بالمخزون"
>
<Field
type="number"
name="stock_quantity"
placeholder="الكميةبالمخزون"
placeholder="الكمية بالمخزون"
/>
</FormField>
@ -991,12 +991,12 @@ const EditProducts = () => {
<FormField
label="حدالتنبيهلنقصالمخزون"
label="حد التنبيه لنقص المخزون"
>
<Field
type="number"
name="low_stock_threshold"
placeholder="حدالتنبيهلنقصالمخزون"
placeholder="حد التنبيه لنقص المخزون"
/>
</FormField>
@ -1046,7 +1046,7 @@ const EditProducts = () => {
<FormField>
<Field
label='صورالمنتج'
label='صور المنتج'
color='info'
icon={mdiUpload}
path={'products/product_images'}
@ -1082,7 +1082,7 @@ const EditProducts = () => {
<FormField label='متاحللبيع' labelFor='is_active'>
<FormField label='متاح للبيع' labelFor='is_active'>
<Field
name='is_active'
id='is_active'
@ -1121,7 +1121,7 @@ const EditProducts = () => {
<FormField label='organizations' labelFor='organizations'>
<FormField label='المنظمة' labelFor='organizations'>
<Field
name='organizations'
id='organizations'
@ -1168,9 +1168,9 @@ const EditProducts = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/products/products-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/products/products-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -498,10 +498,10 @@ const EditProductsPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit products')}</title>
<title>{getPageTitle('تعديل المنتج')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit products'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل المنتج'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -643,11 +643,11 @@ const EditProductsPage = () => {
<FormField
label="اسمالمنتج"
label="اسم المنتج"
>
<Field
name="product_name"
placeholder="اسمالمنتج"
placeholder="اسم المنتج"
/>
</FormField>
@ -680,11 +680,11 @@ const EditProductsPage = () => {
<FormField
label="رمزالمنتج"
label="رمز المنتج"
>
<Field
name="sku"
placeholder="رمزالمنتج"
placeholder="رمز المنتج"
/>
</FormField>
@ -760,12 +760,12 @@ const EditProductsPage = () => {
<FormField
label="سعرالتكلفةالحقيقي"
label="سعر التكلفة"
>
<Field
type="number"
name="cost_price"
placeholder="سعرالتكلفةالحقيقي"
placeholder="سعر التكلفة"
/>
</FormField>
@ -798,12 +798,12 @@ const EditProductsPage = () => {
<FormField
label="سعرالبيع"
label="سعر البيع"
>
<Field
type="number"
name="sale_price"
placeholder="سعرالبيع"
placeholder="سعر البيع"
/>
</FormField>
@ -836,12 +836,12 @@ const EditProductsPage = () => {
<FormField
label="سعرالبيعالسابق"
label="سعر البيع السابق"
>
<Field
type="number"
name="sale_price_backup"
placeholder="سعرالبيعالسابق"
placeholder="سعر البيع السابق"
/>
</FormField>
@ -874,12 +874,12 @@ const EditProductsPage = () => {
<FormField
label="سعرالتكلفةالسابق"
label="سعر التكلفة السابق"
>
<Field
type="number"
name="cost_price_backup"
placeholder="سعرالتكلفةالسابق"
placeholder="سعر التكلفة السابق"
/>
</FormField>
@ -912,12 +912,12 @@ const EditProductsPage = () => {
<FormField
label="السعربالدولار"
label="السعر بالدولار"
>
<Field
type="number"
name="usd_price"
placeholder="السعربالدولار"
placeholder="السعر بالدولار"
/>
</FormField>
@ -950,12 +950,12 @@ const EditProductsPage = () => {
<FormField
label="الكميةبالمخزون"
label="الكمية بالمخزون"
>
<Field
type="number"
name="stock_quantity"
placeholder="الكميةبالمخزون"
placeholder="الكمية بالمخزون"
/>
</FormField>
@ -988,12 +988,12 @@ const EditProductsPage = () => {
<FormField
label="حدالتنبيهلنقصالمخزون"
label="حد التنبيه لنقص المخزون"
>
<Field
type="number"
name="low_stock_threshold"
placeholder="حدالتنبيهلنقصالمخزون"
placeholder="حد التنبيه لنقص المخزون"
/>
</FormField>
@ -1043,7 +1043,7 @@ const EditProductsPage = () => {
<FormField>
<Field
label='صورالمنتج'
label='صور المنتج'
color='info'
icon={mdiUpload}
path={'products/product_images'}
@ -1079,7 +1079,7 @@ const EditProductsPage = () => {
<FormField label='متاحللبيع' labelFor='is_active'>
<FormField label='متاح للبيع' labelFor='is_active'>
<Field
name='is_active'
id='is_active'
@ -1118,7 +1118,7 @@ const EditProductsPage = () => {
<FormField label='organizations' labelFor='organizations'>
<FormField label='المنظمة' labelFor='organizations'>
<Field
name='organizations'
id='organizations'
@ -1165,9 +1165,9 @@ const EditProductsPage = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/products/products-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/products/products-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -34,9 +34,9 @@ const ProductsTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'اسمالمنتج', title: 'product_name'},{label: 'رمزالمنتج', title: 'sku'},{label: 'الباركود', title: 'barcode'},
{label: 'الكميةبالمخزون', title: 'stock_quantity', number: 'true'},{label: 'حدالتنبيهلنقصالمخزون', title: 'low_stock_threshold', number: 'true'},
{label: 'سعرالتكلفةالحقيقي', title: 'cost_price', number: 'true'},{label: 'سعرالبيع', title: 'sale_price', number: 'true'},{label: 'سعرالبيعالسابق', title: 'sale_price_backup', number: 'true'},{label: 'سعرالتكلفةالسابق', title: 'cost_price_backup', number: 'true'},{label: 'السعربالدولار', title: 'usd_price', number: 'true'},
const [filters] = useState([{label: 'اسم المنتج', title: 'product_name'},{label: 'رمز المنتج', title: 'sku'},{label: 'الباركود', title: 'barcode'},
{label: 'الكمية بالمخزون', title: 'stock_quantity', number: 'true'},{label: 'حد التنبيه لنقص المخزون', title: 'low_stock_threshold', number: 'true'},
{label: 'سعر التكلفة', title: 'cost_price', number: 'true'},{label: 'سعر البيع', title: 'sale_price', number: 'true'},{label: 'سعر البيع السابق', title: 'sale_price_backup', number: 'true'},{label: 'سعر التكلفة السابق', title: 'cost_price_backup', number: 'true'},{label: 'السعر بالدولار', title: 'usd_price', number: 'true'},
@ -94,28 +94,28 @@ const ProductsTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Products')}</title>
<title>{getPageTitle('المنتجات')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Products" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المنتجات" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/products/products-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/products/products-new'} color='info' label='إضافة منتج'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='إضافة تصفية'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getProductsCSV} />
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getProductsCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
label='Upload CSV'
label='رفع CSV'
onClick={() => setIsModalActive(true)}
/>
)}
@ -137,9 +137,9 @@ const ProductsTablesPage = () => {
</SectionMain>
<CardBoxModal
title='Upload CSV'
title='رفع ملف CSV'
buttonColor='info'
buttonLabel={'Confirm'}
buttonLabel={'تأكيد'}
// buttonLabel={false ? 'Deleting...' : 'Confirm'}
isActive={isModalActive}
onConfirm={onModalConfirm}

View File

@ -286,10 +286,10 @@ const ProductsNew = () => {
return (
<>
<Head>
<title>{getPageTitle('New Item')}</title>
<title>{getPageTitle('إضافة منتج')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة منتج" main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -366,11 +366,11 @@ const ProductsNew = () => {
<FormField
label="اسمالمنتج"
label="اسم المنتج"
>
<Field
name="product_name"
placeholder="اسمالمنتج"
placeholder="اسم المنتج"
/>
</FormField>
@ -401,11 +401,11 @@ const ProductsNew = () => {
<FormField
label="رمزالمنتج"
label="رمز المنتج"
>
<Field
name="sku"
placeholder="رمزالمنتج"
placeholder="رمز المنتج"
/>
</FormField>
@ -477,12 +477,12 @@ const ProductsNew = () => {
<FormField
label="سعرالتكلفةالحقيقي"
label="سعر التكلفة"
>
<Field
type="number"
name="cost_price"
placeholder="سعرالتكلفةالحقيقي"
placeholder="سعر التكلفة"
/>
</FormField>
@ -513,12 +513,12 @@ const ProductsNew = () => {
<FormField
label="سعرالبيع"
label="سعر البيع"
>
<Field
type="number"
name="sale_price"
placeholder="سعرالبيع"
placeholder="سعر البيع"
/>
</FormField>
@ -549,12 +549,12 @@ const ProductsNew = () => {
<FormField
label="سعرالبيعالسابق"
label="سعر البيع السابق"
>
<Field
type="number"
name="sale_price_backup"
placeholder="سعرالبيعالسابق"
placeholder="سعر البيع السابق"
/>
</FormField>
@ -585,12 +585,12 @@ const ProductsNew = () => {
<FormField
label="سعرالتكلفةالسابق"
label="سعر التكلفة السابق"
>
<Field
type="number"
name="cost_price_backup"
placeholder="سعرالتكلفةالسابق"
placeholder="سعر التكلفة السابق"
/>
</FormField>
@ -621,12 +621,12 @@ const ProductsNew = () => {
<FormField
label="السعربالدولار"
label="السعر بالدولار"
>
<Field
type="number"
name="usd_price"
placeholder="السعربالدولار"
placeholder="السعر بالدولار"
/>
</FormField>
@ -657,12 +657,12 @@ const ProductsNew = () => {
<FormField
label="الكميةبالمخزون"
label="الكمية بالمخزون"
>
<Field
type="number"
name="stock_quantity"
placeholder="الكميةبالمخزون"
placeholder="الكمية بالمخزون"
/>
</FormField>
@ -693,12 +693,12 @@ const ProductsNew = () => {
<FormField
label="حدالتنبيهلنقصالمخزون"
label="حد التنبيه لنقص المخزون"
>
<Field
type="number"
name="low_stock_threshold"
placeholder="حدالتنبيهلنقصالمخزون"
placeholder="حد التنبيه لنقص المخزون"
/>
</FormField>
@ -746,7 +746,7 @@ const ProductsNew = () => {
<FormField>
<Field
label='صورالمنتج'
label='صور المنتج'
color='info'
icon={mdiUpload}
path={'products/product_images'}
@ -780,7 +780,7 @@ const ProductsNew = () => {
<FormField label='متاحللبيع' labelFor='is_active'>
<FormField label='متاح للبيع' labelFor='is_active'>
<Field
name='is_active'
id='is_active'
@ -816,7 +816,7 @@ const ProductsNew = () => {
<FormField label="organizations" labelFor="organizations">
<FormField label="المنظمة" labelFor="organizations">
<Field name="organizations" id="organizations" component={SelectField} options={[]} itemRef={'organizations'}></Field>
</FormField>
@ -828,9 +828,9 @@ const ProductsNew = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/products/products-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/products/products-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -34,9 +34,9 @@ const ProductsTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'اسمالمنتج', title: 'product_name'},{label: 'رمزالمنتج', title: 'sku'},{label: 'الباركود', title: 'barcode'},
{label: 'الكميةبالمخزون', title: 'stock_quantity', number: 'true'},{label: 'حدالتنبيهلنقصالمخزون', title: 'low_stock_threshold', number: 'true'},
{label: 'سعرالتكلفةالحقيقي', title: 'cost_price', number: 'true'},{label: 'سعرالبيع', title: 'sale_price', number: 'true'},{label: 'سعرالبيعالسابق', title: 'sale_price_backup', number: 'true'},{label: 'سعرالتكلفةالسابق', title: 'cost_price_backup', number: 'true'},{label: 'السعربالدولار', title: 'usd_price', number: 'true'},
const [filters] = useState([{label: 'اسم المنتج', title: 'product_name'},{label: 'رمز المنتج', title: 'sku'},{label: 'الباركود', title: 'barcode'},
{label: 'الكمية بالمخزون', title: 'stock_quantity', number: 'true'},{label: 'حد التنبيه لنقص المخزون', title: 'low_stock_threshold', number: 'true'},
{label: 'سعر التكلفة', title: 'cost_price', number: 'true'},{label: 'سعر البيع', title: 'sale_price', number: 'true'},{label: 'سعر البيع السابق', title: 'sale_price_backup', number: 'true'},{label: 'سعر التكلفة السابق', title: 'cost_price_backup', number: 'true'},{label: 'السعر بالدولار', title: 'usd_price', number: 'true'},
@ -94,28 +94,28 @@ const ProductsTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Products')}</title>
<title>{getPageTitle('المنتجات')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Products" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المنتجات" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/products/products-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/products/products-new'} color='info' label='إضافة منتج'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='إضافة تصفية'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getProductsCSV} />
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getProductsCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
label='Upload CSV'
label='رفع CSV'
onClick={() => setIsModalActive(true)}
/>
)}
@ -139,9 +139,9 @@ const ProductsTablesPage = () => {
</CardBox>
</SectionMain>
<CardBoxModal
title='Upload CSV'
title='رفع ملف CSV'
buttonColor='info'
buttonLabel={'Confirm'}
buttonLabel={'تأكيد'}
// buttonLabel={false ? 'Deleting...' : 'Confirm'}
isActive={isModalActive}
onConfirm={onModalConfirm}

View File

@ -33,10 +33,6 @@ const ProductsView = () => {
const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => {
dispatch(fetch({ id }));
@ -46,13 +42,13 @@ const ProductsView = () => {
return (
<>
<Head>
<title>{getPageTitle('View products')}</title>
<title>{getPageTitle('عرض المنتج')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View products')} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'عرض المنتج'} main>
<BaseButton
color='info'
label='Edit'
label='تعديل'
href={`/products/products-edit/?id=${id}`}
/>
</SectionTitleLineWithButton>
@ -91,7 +87,7 @@ const ProductsView = () => {
<p>{products?.shop?.shop_name ?? 'No data'}</p>
<p>{products?.shop?.shop_name ?? 'لا توجد بيانات'}</p>
@ -149,7 +145,7 @@ const ProductsView = () => {
<p>{products?.category?.category_name ?? 'No data'}</p>
<p>{products?.category?.category_name ?? 'لا توجد بيانات'}</p>
@ -173,7 +169,7 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>اسمالمنتج</p>
<p className={'block font-bold mb-2'}>اسم المنتج</p>
<p>{products?.product_name}</p>
</div>
@ -205,7 +201,7 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>رمزالمنتج</p>
<p className={'block font-bold mb-2'}>رمز المنتج</p>
<p>{products?.sku}</p>
</div>
@ -275,8 +271,8 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>سعرالتكلفةالحقيقي</p>
<p>{products?.cost_price || 'No data'}</p>
<p className={'block font-bold mb-2'}>سعر التكلفة</p>
<p>{products?.cost_price || 'لا توجد بيانات'}</p>
</div>
@ -307,8 +303,8 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>سعرالبيع</p>
<p>{products?.sale_price || 'No data'}</p>
<p className={'block font-bold mb-2'}>سعر البيع</p>
<p>{products?.sale_price || 'لا توجد بيانات'}</p>
</div>
@ -339,8 +335,8 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>سعرالبيعالسابق</p>
<p>{products?.sale_price_backup || 'No data'}</p>
<p className={'block font-bold mb-2'}>سعر البيع السابق</p>
<p>{products?.sale_price_backup || 'لا توجد بيانات'}</p>
</div>
@ -371,8 +367,8 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>سعرالتكلفةالسابق</p>
<p>{products?.cost_price_backup || 'No data'}</p>
<p className={'block font-bold mb-2'}>سعر التكلفة السابق</p>
<p>{products?.cost_price_backup || 'لا توجد بيانات'}</p>
</div>
@ -403,8 +399,8 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>السعربالدولار</p>
<p>{products?.usd_price || 'No data'}</p>
<p className={'block font-bold mb-2'}>السعر بالدولار</p>
<p>{products?.usd_price || 'لا توجد بيانات'}</p>
</div>
@ -435,8 +431,8 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>الكميةبالمخزون</p>
<p>{products?.stock_quantity || 'No data'}</p>
<p className={'block font-bold mb-2'}>الكمية بالمخزون</p>
<p>{products?.stock_quantity || 'لا توجد بيانات'}</p>
</div>
@ -467,8 +463,8 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>حدالتنبيهلنقصالمخزون</p>
<p>{products?.low_stock_threshold || 'No data'}</p>
<p className={'block font-bold mb-2'}>حد التنبيه لنقص المخزون</p>
<p>{products?.low_stock_threshold || 'لا توجد بيانات'}</p>
</div>
@ -548,7 +544,7 @@ const ProductsView = () => {
<FormField label='متاحللبيع'>
<FormField label='متاح للبيع'>
<SwitchField
field={{name: 'is_active', value: products?.is_active}}
form={{setFieldValue: () => null}}
@ -587,7 +583,7 @@ const ProductsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>organizations</p>
<p className={'block font-bold mb-2'}>المنظمة</p>
@ -596,7 +592,7 @@ const ProductsView = () => {
<p>{products?.organizations?.name ?? 'No data'}</p>
<p>{products?.organizations?.name ?? 'لا توجد بيانات'}</p>
@ -647,7 +643,7 @@ const ProductsView = () => {
<th>اسمالمنتجوقتالبيع</th>
<th>اسم المنتج وقت البيع</th>
@ -655,7 +651,7 @@ const ProductsView = () => {
<th>سعرالبيعوقتالبيع</th>
<th>سعر البيعوقتالبيع</th>
@ -682,37 +678,37 @@ const ProductsView = () => {
<td data-label="product_name_snapshot">
<td data-label="اسم المنتج وقت البيع">
{ item.product_name_snapshot }
</td>
<td data-label="cost_price_snapshot">
<td data-label="سعر التكلفة وقت البيع">
{ item.cost_price_snapshot }
</td>
<td data-label="sale_price_snapshot">
<td data-label="سعر البيع وقت البيع">
{ item.sale_price_snapshot }
</td>
<td data-label="quantity">
<td data-label="الكمية">
{ item.quantity }
</td>
<td data-label="line_subtotal">
<td data-label="إجمالي العنصر">
{ item.line_subtotal }
</td>
<td data-label="line_profit">
<td data-label="ربح العنصر">
{ item.line_profit }
</td>
@ -722,7 +718,7 @@ const ProductsView = () => {
</tbody>
</table>
</div>
{!products?.sales_invoice_items_product?.length && <div className={'text-center py-4'}>No data</div>}
{!products?.sales_invoice_items_product?.length && <div className={'text-center py-4'}>لا توجد بيانات</div>}
</CardBox>
</>
@ -733,7 +729,7 @@ const ProductsView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/products/products-list')}
/>
</CardBox>

View File

@ -1,180 +1,172 @@
import {
mdiChartTimelineVariant,
mdiUpload,
} from '@mdi/js';
import { mdiAccountCircle, mdiUpload } from '@mdi/js';
import Head from 'next/head';
import React, { ReactElement, useEffect, useState } from 'react';
import { ToastContainer, toast } from 'react-toastify';
import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
import { Field, Form, Formik } from 'formik';
import { useRouter } from 'next/router';
import BaseButton from '../components/BaseButton';
import BaseButtons from '../components/BaseButtons';
import BaseDivider from '../components/BaseDivider';
import CardBox from '../components/CardBox';
import LayoutAuthenticated from '../layouts/Authenticated';
import FormField from '../components/FormField';
import FormImagePicker from '../components/FormImagePicker';
import SectionMain from '../components/SectionMain';
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
import { getPageTitle } from '../config';
import { Field, Form, Formik } from 'formik';
import FormField from '../components/FormField';
import BaseDivider from '../components/BaseDivider';
import BaseButtons from '../components/BaseButtons';
import BaseButton from '../components/BaseButton';
import FormCheckRadio from '../components/FormCheckRadio';
import FormCheckRadioGroup from '../components/FormCheckRadioGroup';
import FormImagePicker from '../components/FormImagePicker';
import { SwitchField } from '../components/SwitchField';
import { SelectField } from '../components/SelectField';
import { update, fetch } from '../stores/users/usersSlice';
import LayoutAuthenticated from '../layouts/Authenticated';
import { findMe } from '../stores/authSlice';
import { useAppDispatch, useAppSelector } from '../stores/hooks';
import { useRouter } from 'next/router';
import {findMe} from "../stores/authSlice";
import { update } from '../stores/users/usersSlice';
const EditUsers = () => {
const { currentUser, isFetching, token } = useAppSelector(
(state) => state.auth,
);
const router = useRouter();
const dispatch = useAppDispatch();
const notify = (type, msg) => toast(msg, { type });
const initVals = {
firstName: '',
lastName: '',
phoneNumber: '',
email: '',
app_role: '',
disabled: false,
avatar: [],
password: ''
};
const [initialValues, setInitialValues] = useState(initVals);
const ProfilePage = () => {
const { currentUser } = useAppSelector((state) => state.auth);
const router = useRouter();
const dispatch = useAppDispatch();
useEffect(() => {
if (currentUser?.id && typeof currentUser === 'object') {
const newInitialVal = { ...initVals };
const notify = (type, msg) => toast(msg, { type });
Object.keys(initVals).forEach(
(el) => (newInitialVal[el] = currentUser[el]),
);
const initVals = {
firstName: '',
lastName: '',
phoneNumber: '',
email: '',
avatar: [],
password: '',
};
setInitialValues(newInitialVal);
}
}, [currentUser]);
const [initialValues, setInitialValues] = useState(initVals);
const handleSubmit = async (data) => {
await dispatch(update({ id: currentUser.id, data }));
await dispatch(findMe());
await router.push('/users/users-list');
notify('success', 'Profile was updated!');
useEffect(() => {
if (currentUser?.id && typeof currentUser === 'object') {
setInitialValues({
firstName: currentUser.firstName || '',
lastName: currentUser.lastName || '',
phoneNumber: currentUser.phoneNumber || '',
email: currentUser.email || '',
avatar: currentUser.avatar || [],
password: '',
});
}
}, [currentUser]);
const handleSubmit = async (values) => {
if (!currentUser?.id) {
notify('error', 'تعذر تحديد المستخدم الحالي.');
return;
}
const payload = {
firstName: values.firstName,
lastName: values.lastName,
phoneNumber: values.phoneNumber,
email: values.email,
avatar: values.avatar,
...(values.password?.trim() ? { password: values.password.trim() } : {}),
};
return (
<>
<Head>
<title>{getPageTitle('Edit profile')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton
icon={mdiChartTimelineVariant}
title='Edit profile'
main
>
{''}
</SectionTitleLineWithButton>
<CardBox>
{currentUser?.avatar[0]?.publicUrl && <div className={'grid grid-cols-6 gap-4 mb-4'}>
<div className="col-span-1 w-80 h-80 overflow-hidden border-2 rounded-full inline-flex items-center justify-center mb-8">
<img className="w-80 h-80 max-w-full max-h-full object-cover object-center" src={`${currentUser?.avatar[0]?.publicUrl}`} alt="Avatar" />
</div>
</div>}
<Formik
enableReinitialize
initialValues={initialValues}
onSubmit={(values) => handleSubmit(values)}
>
<Form>
<FormField>
<Field
label='Avatar'
color='info'
icon={mdiUpload}
path={'users/avatar'}
name='avatar'
id='avatar'
schema={{
size: undefined,
formats: undefined,
}}
component={FormImagePicker}
></Field>
</FormField>
<FormField label='First Name'>
<Field name='firstName' placeholder='First Name' />
</FormField>
await dispatch(update({ id: currentUser.id, data: payload }));
await dispatch(findMe());
notify('success', 'تم تحديث الملف الشخصي بنجاح.');
};
<FormField label='Last Name'>
<Field name='lastName' placeholder='Last Name' />
</FormField>
return (
<>
<Head>
<title>{getPageTitle('الملف الشخصي')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiAccountCircle} title='الملف الشخصي' main>
{''}
</SectionTitleLineWithButton>
<FormField label='Phone Number'>
<Field name='phoneNumber' placeholder='Phone Number' />
</FormField>
<CardBox>
<div className='mb-6 space-y-2'>
<h2 className='text-xl font-bold text-slate-900'>تعديل بيانات الحساب</h2>
<p className='text-sm text-slate-500'>
يمكنك تحديث الاسم ورقم الهاتف والصورة الشخصية من هنا. اترك كلمة المرور فارغة إذا كنت لا تريد تغييرها.
</p>
</div>
<FormField label='E-Mail'>
<Field name='email' placeholder='E-Mail' disabled />
</FormField>
{currentUser?.avatar?.[0]?.publicUrl ? (
<div className='mb-6 flex justify-center md:justify-start'>
<div className='inline-flex h-40 w-40 items-center justify-center overflow-hidden rounded-full border-2 border-slate-200 bg-slate-50'>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
className='h-full w-full object-cover object-center'
src={currentUser.avatar[0].publicUrl}
alt='الصورة الشخصية'
/>
</div>
</div>
) : null}
<FormField label='App Role' labelFor='app_role'>
<Field
name='app_role'
id='app_role'
component={SelectField}
options={initialValues.app_role}
itemRef={'roles'}
showField={'name'}
></Field>
</FormField>
<Formik enableReinitialize initialValues={initialValues} onSubmit={handleSubmit}>
<Form>
<FormField>
<Field
label='الصورة الشخصية'
color='info'
icon={mdiUpload}
path='users/avatar'
name='avatar'
id='avatar'
schema={{
size: undefined,
formats: undefined,
}}
component={FormImagePicker}
/>
</FormField>
<FormField label='Disabled' labelFor='disabled'>
<Field
name='disabled'
id='disabled'
component={SwitchField}
></Field>
</FormField>
<div className='grid gap-4 md:grid-cols-2'>
<FormField label='الاسم الأول'>
<Field name='firstName' placeholder='اكتب الاسم الأول' />
</FormField>
<FormField
label="Password"
>
<Field
name="password"
placeholder="password"
/>
</FormField>
<FormField label='الاسم الأخير'>
<Field name='lastName' placeholder='اكتب الاسم الأخير' />
</FormField>
</div>
<BaseDivider />
<div className='grid gap-4 md:grid-cols-2'>
<FormField label='رقم الهاتف'>
<Field name='phoneNumber' placeholder='اكتب رقم الهاتف' />
</FormField>
<BaseButtons>
<BaseButton type='submit' color='info' label='Submit' />
<BaseButton type='reset' color='info' outline label='Reset' />
<BaseButton
type='reset'
color='danger'
outline
label='Cancel'
onClick={() => router.push('/users/users-list')}
/>
</BaseButtons>
</Form>
</Formik>
</CardBox>
</SectionMain>
</>
);
<FormField label='البريد الإلكتروني'>
<Field name='email' placeholder='البريد الإلكتروني' disabled />
</FormField>
</div>
<FormField label='كلمة المرور الجديدة'>
<Field name='password' type='password' placeholder='اتركها فارغة إذا لا تريد التغيير' />
</FormField>
<BaseDivider />
<BaseButtons>
<BaseButton type='submit' color='info' label='حفظ التعديلات' />
<BaseButton type='reset' color='info' outline label='إعادة تعيين' />
<BaseButton
type='button'
color='danger'
outline
label='العودة للرئيسية'
onClick={() => router.push('/dashboard')}
/>
</BaseButtons>
</Form>
</Formik>
</CardBox>
</SectionMain>
<ToastContainer />
</>
);
};
EditUsers.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
ProfilePage.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
};
export default EditUsers;
export default ProfilePage;

View File

@ -12,123 +12,168 @@ import BaseDivider from '../components/BaseDivider';
import BaseButtons from '../components/BaseButtons';
import { useRouter } from 'next/router';
import { getPageTitle } from '../config';
import Select from 'react-select';
import axios from 'axios';
import Link from 'next/link';
import Select from 'react-select';
import { useAppDispatch } from '../stores/hooks';
import { createAsyncThunk } from '@reduxjs/toolkit';
type Organization = {
id: string;
name: string;
};
import axios from "axios";
type OrganizationOption = {
value: string;
label: string;
};
type RegisterFormValues = {
email: string;
password: string;
confirm: string;
};
export default function Register() {
const [loading, setLoading] = React.useState(false);
const router = useRouter();
const notify = (type, msg) => toast( msg, {type, position: "bottom-center"});
const [loading, setLoading] = React.useState(false);
const [organizations, setOrganizations] = React.useState<Organization[]>([]);
const [selectedOrganization, setSelectedOrganization] = React.useState<OrganizationOption | null>(null);
const router = useRouter();
const [organizations, setOrganizations] = React.useState(null);
const [selectedOrganization, setSelectedOrganization] = React.useState(null);
const dispatch = useAppDispatch();
const fetchOrganizations = createAsyncThunk(
'/org-for-auth',
async () => {
const notify = (type: 'success' | 'error', msg: string) =>
toast(msg, { type, position: 'bottom-center' });
React.useEffect(() => {
const fetchOrganizations = async () => {
try {
const response = await axios.get('/org-for-auth');
setOrganizations(response.data);
return response.data;
} catch (error) {
console.error(error.response);
throw error;
setOrganizations(Array.isArray(response.data) ? response.data : []);
} catch (error: any) {
console.error('Failed to load organizations for register:', error);
}
}
);
React.useEffect(() => {
dispatch(fetchOrganizations());
}, [dispatch]);
const options = organizations?.map(org => ({
value: org.id,
label: org.name
}));
const handleSubmit = async (value) => {
setLoading(true)
try {
const formData = { ...value, organizationId: selectedOrganization.value };
const { data: response } = await axios.post('/auth/signup',formData);
await router.push('/login')
setLoading(false)
notify('success', 'Please check your email for verification link')
} catch (error) {
setLoading(false)
console.log('error: ', error)
notify('error', 'Something was wrong. Try again')
}
};
return (
<>
<Head>
<title>{getPageTitle('Login')}</title>
</Head>
fetchOrganizations();
}, []);
<SectionFullScreen bg='violet'>
<CardBox className='w-11/12 md:w-7/12 lg:w-6/12 xl:w-4/12'>
<Formik
initialValues={{
email: '',
password: '',
confirm: ''
}}
onSubmit={(values) => handleSubmit(values)}
>
<Form>
<label className="block font-bold mb-2" >Organization</label>
<Select
classNames={{
control: () => 'px-1 mb-4 py-2',
}}
value={selectedOrganization}
onChange={setSelectedOrganization}
options={options}
placeholder="Select organization..."
/>
<FormField label='Email' help='Please enter your email'>
<Field type='email' name='email' />
</FormField>
<FormField label='Password' help='Please enter your password'>
<Field type='password' name='password' />
</FormField>
<FormField label='Confirm Password' help='Please confirm your password'>
<Field type='password' name='confirm' />
</FormField>
const options = organizations.map((org) => ({
value: org.id,
label: org.name,
}));
<BaseDivider />
const handleSubmit = async (values: RegisterFormValues) => {
if (!values.email || !values.password || !values.confirm) {
notify('error', 'يرجى تعبئة كل الحقول المطلوبة.');
return;
}
<BaseButtons>
<BaseButton
type='submit'
label={loading ? 'Loading...' : 'Register' }
color='info'
/>
<BaseButton
href={'/login'}
label={'Login'}
color='info'
/>
</BaseButtons>
</Form>
</Formik>
</CardBox>
</SectionFullScreen>
<ToastContainer />
</>
);
if (values.password !== values.confirm) {
notify('error', 'كلمتا المرور غير متطابقتين.');
return;
}
if (options.length > 0 && !selectedOrganization?.value) {
notify('error', 'يرجى اختيار المنظمة أولاً.');
return;
}
setLoading(true);
try {
const formData = {
email: values.email,
password: values.password,
organizationId: selectedOrganization?.value,
};
await axios.post('/auth/signup', formData);
notify('success', 'تم إنشاء الحساب. تحقق من بريدك الإلكتروني لتفعيل الحساب.');
await router.push('/login');
} catch (error: any) {
console.error('Register failed:', error);
notify('error', error?.response?.data || 'حدث خطأ أثناء إنشاء الحساب. حاول مرة أخرى.');
} finally {
setLoading(false);
}
};
return (
<>
<Head>
<title>{getPageTitle('إنشاء حساب جديد')}</title>
</Head>
<SectionFullScreen bg='violet'>
<CardBox className='w-11/12 md:w-7/12 lg:w-6/12 xl:w-4/12'>
<div className='mb-6 text-center'>
<h1 className='text-2xl font-bold mb-2'>إنشاء حساب جديد</h1>
<p className='text-sm text-gray-500'>
أدخل بياناتك الأساسية لبدء استخدام النظام.
</p>
</div>
<Formik<RegisterFormValues>
initialValues={{
email: '',
password: '',
confirm: '',
}}
onSubmit={handleSubmit}
>
<Form>
{options.length > 0 && (
<div className='mb-4'>
<label className='block font-bold mb-2'>المنظمة</label>
<Select
classNames={{
control: () => 'px-1 py-2',
}}
value={selectedOrganization}
onChange={(option) => setSelectedOrganization(option as OrganizationOption | null)}
options={options}
placeholder='اختر المنظمة...'
isClearable
/>
</div>
)}
<FormField label='البريد الإلكتروني' help='أدخل بريدك الإلكتروني'>
<Field type='email' name='email' />
</FormField>
<FormField label='كلمة المرور' help='أدخل كلمة المرور'>
<Field type='password' name='password' />
</FormField>
<FormField label='تأكيد كلمة المرور' help='أعد إدخال كلمة المرور للتأكيد'>
<Field type='password' name='confirm' />
</FormField>
<BaseDivider />
<BaseButtons>
<BaseButton
type='submit'
label={loading ? 'جارٍ إنشاء الحساب...' : 'إنشاء الحساب'}
color='info'
disabled={loading}
/>
<BaseButton href='/login' label='تسجيل الدخول' color='info' outline />
</BaseButtons>
<p className='mt-4 text-center text-sm'>
لديك حساب بالفعل؟{' '}
<Link href='/login' className='text-blue-600'>
ادخل إلى حسابك
</Link>
</p>
</Form>
</Formik>
</CardBox>
</SectionFullScreen>
<ToastContainer />
</>
);
}
Register.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
return <LayoutGuest>{page}</LayoutGuest>;
};

View File

@ -323,7 +323,7 @@ const RolesView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/roles/roles-list')}
/>
</CardBox>

View File

@ -559,12 +559,12 @@ const EditSales_invoice_items = () => {
<FormField
label="سعرالبيعوقتالبيع"
label="سعر البيعوقتالبيع"
>
<Field
type="number"
name="sale_price_snapshot"
placeholder="سعرالبيعوقتالبيع"
placeholder="سعر البيعوقتالبيع"
/>
</FormField>

View File

@ -556,12 +556,12 @@ const EditSales_invoice_itemsPage = () => {
<FormField
label="سعرالبيعوقتالبيع"
label="سعر البيعوقتالبيع"
>
<Field
type="number"
name="sale_price_snapshot"
placeholder="سعرالبيعوقتالبيع"
placeholder="سعر البيعوقتالبيع"
/>
</FormField>

View File

@ -36,7 +36,7 @@ const Sales_invoice_itemsTablesPage = () => {
const [filters] = useState([{label: 'اسمالمنتجوقتالبيع', title: 'product_name_snapshot'},
{label: 'الكمية', title: 'quantity', number: 'true'},
{label: 'سعرالتكلفةوقتالبيع', title: 'cost_price_snapshot', number: 'true'},{label: 'سعرالبيعوقتالبيع', title: 'sale_price_snapshot', number: 'true'},{label: 'الإجماليللعنصر', title: 'line_subtotal', number: 'true'},{label: 'الربحللعنصر', title: 'line_profit', number: 'true'},
{label: 'سعرالتكلفةوقتالبيع', title: 'cost_price_snapshot', number: 'true'},{label: 'سعر البيعوقتالبيع', title: 'sale_price_snapshot', number: 'true'},{label: 'الإجماليللعنصر', title: 'line_subtotal', number: 'true'},{label: 'الربحللعنصر', title: 'line_profit', number: 'true'},

View File

@ -347,12 +347,12 @@ const Sales_invoice_itemsNew = () => {
<FormField
label="سعرالبيعوقتالبيع"
label="سعر البيعوقتالبيع"
>
<Field
type="number"
name="sale_price_snapshot"
placeholder="سعرالبيعوقتالبيع"
placeholder="سعر البيعوقتالبيع"
/>
</FormField>

View File

@ -36,7 +36,7 @@ const Sales_invoice_itemsTablesPage = () => {
const [filters] = useState([{label: 'اسمالمنتجوقتالبيع', title: 'product_name_snapshot'},
{label: 'الكمية', title: 'quantity', number: 'true'},
{label: 'سعرالتكلفةوقتالبيع', title: 'cost_price_snapshot', number: 'true'},{label: 'سعرالبيعوقتالبيع', title: 'sale_price_snapshot', number: 'true'},{label: 'الإجماليللعنصر', title: 'line_subtotal', number: 'true'},{label: 'الربحللعنصر', title: 'line_profit', number: 'true'},
{label: 'سعرالتكلفةوقتالبيع', title: 'cost_price_snapshot', number: 'true'},{label: 'سعر البيعوقتالبيع', title: 'sale_price_snapshot', number: 'true'},{label: 'الإجماليللعنصر', title: 'line_subtotal', number: 'true'},{label: 'الربحللعنصر', title: 'line_profit', number: 'true'},

View File

@ -97,7 +97,7 @@ const Sales_invoice_itemsView = () => {
<p>{sales_invoice_items?.invoice?.invoice_number ?? 'No data'}</p>
<p>{sales_invoice_items?.invoice?.invoice_number ?? 'لا توجد بيانات'}</p>
@ -151,7 +151,7 @@ const Sales_invoice_itemsView = () => {
<p>{sales_invoice_items?.product?.product_name ?? 'No data'}</p>
<p>{sales_invoice_items?.product?.product_name ?? 'لا توجد بيانات'}</p>
@ -212,7 +212,7 @@ const Sales_invoice_itemsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>سعرالتكلفةوقتالبيع</p>
<p>{sales_invoice_items?.cost_price_snapshot || 'No data'}</p>
<p>{sales_invoice_items?.cost_price_snapshot || 'لا توجد بيانات'}</p>
</div>
@ -243,8 +243,8 @@ const Sales_invoice_itemsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>سعرالبيعوقتالبيع</p>
<p>{sales_invoice_items?.sale_price_snapshot || 'No data'}</p>
<p className={'block font-bold mb-2'}>سعر البيعوقتالبيع</p>
<p>{sales_invoice_items?.sale_price_snapshot || 'لا توجد بيانات'}</p>
</div>
@ -276,7 +276,7 @@ const Sales_invoice_itemsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>الكمية</p>
<p>{sales_invoice_items?.quantity || 'No data'}</p>
<p>{sales_invoice_items?.quantity || 'لا توجد بيانات'}</p>
</div>
@ -308,7 +308,7 @@ const Sales_invoice_itemsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>الإجماليللعنصر</p>
<p>{sales_invoice_items?.line_subtotal || 'No data'}</p>
<p>{sales_invoice_items?.line_subtotal || 'لا توجد بيانات'}</p>
</div>
@ -340,7 +340,7 @@ const Sales_invoice_itemsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>الربحللعنصر</p>
<p>{sales_invoice_items?.line_profit || 'No data'}</p>
<p>{sales_invoice_items?.line_profit || 'لا توجد بيانات'}</p>
</div>
@ -393,7 +393,7 @@ const Sales_invoice_itemsView = () => {
<p>{sales_invoice_items?.organizations?.name ?? 'No data'}</p>
<p>{sales_invoice_items?.organizations?.name ?? 'لا توجد بيانات'}</p>
@ -435,7 +435,7 @@ const Sales_invoice_itemsView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/sales_invoice_items/sales_invoice_items-list')}
/>
</CardBox>

View File

@ -473,10 +473,10 @@ const EditSales_invoices = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit sales_invoices')}</title>
<title>{getPageTitle('تعديل الفاتورة')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit sales_invoices'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل الفاتورة'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -618,11 +618,11 @@ const EditSales_invoices = () => {
<FormField
label="رقمالفاتورة"
label="رقم الفاتورة"
>
<Field
name="invoice_number"
placeholder="رقمالفاتورة"
placeholder="رقم الفاتورة"
/>
</FormField>
@ -665,7 +665,7 @@ const EditSales_invoices = () => {
<FormField
label="تاريخووقتالبيع"
label="تاريخ ووقت البيع"
>
<DatePicker
dateFormat="yyyy-MM-dd hh:mm"
@ -714,13 +714,13 @@ const EditSales_invoices = () => {
<FormField label="الحالة" labelFor="status">
<Field name="status" id="status" component="select">
<option value="draft">draft</option>
<option value="draft">مسودة</option>
<option value="paid">paid</option>
<option value="paid">مدفوعة</option>
<option value="voided">voided</option>
<option value="voided">ملغاة</option>
<option value="refunded">refunded</option>
<option value="refunded">مسترجعة</option>
</Field>
</FormField>
@ -746,12 +746,12 @@ const EditSales_invoices = () => {
<FormField
label="الإجماليقبلالخصم"
label="الإجمالي قبل الخصم"
>
<Field
type="number"
name="subtotal_amount"
placeholder="الإجماليقبلالخصم"
placeholder="الإجمالي قبل الخصم"
/>
</FormField>
@ -822,12 +822,12 @@ const EditSales_invoices = () => {
<FormField
label="الإجماليالنهائي"
label="الإجمالي النهائي"
>
<Field
type="number"
name="total_amount"
placeholder="الإجماليالنهائي"
placeholder="الإجمالي النهائي"
/>
</FormField>
@ -860,12 +860,12 @@ const EditSales_invoices = () => {
<FormField
label="إجماليالتكلفة"
label="إجمالي التكلفة"
>
<Field
type="number"
name="total_cost_amount"
placeholder="إجماليالتكلفة"
placeholder="إجمالي التكلفة"
/>
</FormField>
@ -898,12 +898,12 @@ const EditSales_invoices = () => {
<FormField
label="إجماليالربح"
label="إجمالي الربح"
>
<Field
type="number"
name="total_profit_amount"
placeholder="إجماليالربح"
placeholder="إجمالي الربح"
/>
</FormField>
@ -943,16 +943,16 @@ const EditSales_invoices = () => {
<FormField label="طريقةالدفع" labelFor="payment_method">
<FormField label="طريقة الدفع" labelFor="payment_method">
<Field name="payment_method" id="payment_method" component="select">
<option value="cash">cash</option>
<option value="cash">نقداً</option>
<option value="card">card</option>
<option value="card">بطاقة</option>
<option value="transfer">transfer</option>
<option value="transfer">تحويل</option>
<option value="mixed">mixed</option>
<option value="mixed">مختلط</option>
</Field>
</FormField>
@ -1023,7 +1023,7 @@ const EditSales_invoices = () => {
<FormField label='بنودالفاتورة' labelFor='items'>
<FormField label='بنود الفاتورة' labelFor='items'>
<Field
name='items'
id='items'
@ -1083,7 +1083,7 @@ const EditSales_invoices = () => {
<FormField label='organizations' labelFor='organizations'>
<FormField label='المنظمة' labelFor='organizations'>
<Field
name='organizations'
id='organizations'
@ -1130,9 +1130,9 @@ const EditSales_invoices = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/sales_invoices/sales_invoices-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/sales_invoices/sales_invoices-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -470,10 +470,10 @@ const EditSales_invoicesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit sales_invoices')}</title>
<title>{getPageTitle('تعديل الفاتورة')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit sales_invoices'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل الفاتورة'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -615,11 +615,11 @@ const EditSales_invoicesPage = () => {
<FormField
label="رقمالفاتورة"
label="رقم الفاتورة"
>
<Field
name="invoice_number"
placeholder="رقمالفاتورة"
placeholder="رقم الفاتورة"
/>
</FormField>
@ -662,7 +662,7 @@ const EditSales_invoicesPage = () => {
<FormField
label="تاريخووقتالبيع"
label="تاريخ ووقت البيع"
>
<DatePicker
dateFormat="yyyy-MM-dd hh:mm"
@ -711,13 +711,13 @@ const EditSales_invoicesPage = () => {
<FormField label="الحالة" labelFor="status">
<Field name="status" id="status" component="select">
<option value="draft">draft</option>
<option value="draft">مسودة</option>
<option value="paid">paid</option>
<option value="paid">مدفوعة</option>
<option value="voided">voided</option>
<option value="voided">ملغاة</option>
<option value="refunded">refunded</option>
<option value="refunded">مسترجعة</option>
</Field>
</FormField>
@ -743,12 +743,12 @@ const EditSales_invoicesPage = () => {
<FormField
label="الإجماليقبلالخصم"
label="الإجمالي قبل الخصم"
>
<Field
type="number"
name="subtotal_amount"
placeholder="الإجماليقبلالخصم"
placeholder="الإجمالي قبل الخصم"
/>
</FormField>
@ -819,12 +819,12 @@ const EditSales_invoicesPage = () => {
<FormField
label="الإجماليالنهائي"
label="الإجمالي النهائي"
>
<Field
type="number"
name="total_amount"
placeholder="الإجماليالنهائي"
placeholder="الإجمالي النهائي"
/>
</FormField>
@ -857,12 +857,12 @@ const EditSales_invoicesPage = () => {
<FormField
label="إجماليالتكلفة"
label="إجمالي التكلفة"
>
<Field
type="number"
name="total_cost_amount"
placeholder="إجماليالتكلفة"
placeholder="إجمالي التكلفة"
/>
</FormField>
@ -895,12 +895,12 @@ const EditSales_invoicesPage = () => {
<FormField
label="إجماليالربح"
label="إجمالي الربح"
>
<Field
type="number"
name="total_profit_amount"
placeholder="إجماليالربح"
placeholder="إجمالي الربح"
/>
</FormField>
@ -940,16 +940,16 @@ const EditSales_invoicesPage = () => {
<FormField label="طريقةالدفع" labelFor="payment_method">
<FormField label="طريقة الدفع" labelFor="payment_method">
<Field name="payment_method" id="payment_method" component="select">
<option value="cash">cash</option>
<option value="cash">نقداً</option>
<option value="card">card</option>
<option value="card">بطاقة</option>
<option value="transfer">transfer</option>
<option value="transfer">تحويل</option>
<option value="mixed">mixed</option>
<option value="mixed">مختلط</option>
</Field>
</FormField>
@ -1020,7 +1020,7 @@ const EditSales_invoicesPage = () => {
<FormField label='بنودالفاتورة' labelFor='items'>
<FormField label='بنود الفاتورة' labelFor='items'>
<Field
name='items'
id='items'
@ -1080,7 +1080,7 @@ const EditSales_invoicesPage = () => {
<FormField label='organizations' labelFor='organizations'>
<FormField label='المنظمة' labelFor='organizations'>
<Field
name='organizations'
id='organizations'
@ -1127,9 +1127,9 @@ const EditSales_invoicesPage = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/sales_invoices/sales_invoices-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/sales_invoices/sales_invoices-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -34,10 +34,10 @@ const Sales_invoicesTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'رقمالفاتورة', title: 'invoice_number'},{label: 'ملاحظات', title: 'notes'},
const [filters] = useState([{label: 'رقم الفاتورة', title: 'invoice_number'},{label: 'ملاحظات', title: 'notes'},
{label: 'الإجماليقبلالخصم', title: 'subtotal_amount', number: 'true'},{label: 'الخصم', title: 'discount_amount', number: 'true'},{label: 'الإجماليالنهائي', title: 'total_amount', number: 'true'},{label: 'إجماليالتكلفة', title: 'total_cost_amount', number: 'true'},{label: 'إجماليالربح', title: 'total_profit_amount', number: 'true'},
{label: 'تاريخووقتالبيع', title: 'sold_at', date: 'true'},
{label: 'الإجمالي قبل الخصم', title: 'subtotal_amount', number: 'true'},{label: 'الخصم', title: 'discount_amount', number: 'true'},{label: 'الإجمالي النهائي', title: 'total_amount', number: 'true'},{label: 'إجمالي التكلفة', title: 'total_cost_amount', number: 'true'},{label: 'إجمالي الربح', title: 'total_profit_amount', number: 'true'},
{label: 'تاريخ ووقت البيع', title: 'sold_at', date: 'true'},
{label: 'المتجر', title: 'shop'},
@ -47,8 +47,8 @@ const Sales_invoicesTablesPage = () => {
{label: 'الكاشير', title: 'cashier'},
{label: 'بنودالفاتورة', title: 'items'},
{label: 'الحالة', title: 'status', type: 'enum', options: ['draft','paid','voided','refunded']},{label: 'طريقةالدفع', title: 'payment_method', type: 'enum', options: ['cash','card','transfer','mixed']},
{label: 'بنود الفاتورة', title: 'items'},
{label: 'الحالة', title: 'status', type: 'enum', options: ['draft','paid','voided','refunded']},{label: 'طريقة الدفع', title: 'payment_method', type: 'enum', options: ['cash','card','transfer','mixed']},
]);
const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_SALES_INVOICES');
@ -94,28 +94,28 @@ const Sales_invoicesTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Sales_invoices')}</title>
<title>{getPageTitle('الفواتير')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Sales_invoices" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الفواتير" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/sales_invoices/sales_invoices-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/sales_invoices/sales_invoices-new'} color='info' label='إضافة فاتورة'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='إضافة تصفية'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getSales_invoicesCSV} />
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getSales_invoicesCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
label='Upload CSV'
label='رفع CSV'
onClick={() => setIsModalActive(true)}
/>
)}
@ -125,7 +125,7 @@ const Sales_invoicesTablesPage = () => {
</div>
<div className='md:inline-flex items-center ms-auto'>
<Link href={'/sales_invoices/sales_invoices-table'}>Switch to Table</Link>
<Link href={'/sales_invoices/sales_invoices-table'}>عرض الجدول</Link>
</div>
</CardBox>
@ -139,9 +139,9 @@ const Sales_invoicesTablesPage = () => {
</SectionMain>
<CardBoxModal
title='Upload CSV'
title='رفع CSV'
buttonColor='info'
buttonLabel={'Confirm'}
buttonLabel={'تأكيد'}
// buttonLabel={false ? 'Deleting...' : 'Confirm'}
isActive={isModalActive}
onConfirm={onModalConfirm}

View File

@ -272,10 +272,10 @@ const Sales_invoicesNew = () => {
return (
<>
<Head>
<title>{getPageTitle('New Item')}</title>
<title>{getPageTitle('إضافة فاتورة')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة فاتورة" main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -352,11 +352,11 @@ const Sales_invoicesNew = () => {
<FormField
label="رقمالفاتورة"
label="رقم الفاتورة"
>
<Field
name="invoice_number"
placeholder="رقمالفاتورة"
placeholder="رقم الفاتورة"
/>
</FormField>
@ -397,12 +397,12 @@ const Sales_invoicesNew = () => {
<FormField
label="تاريخووقتالبيع"
label="تاريخ ووقت البيع"
>
<Field
type="datetime-local"
name="sold_at"
placeholder="تاريخووقتالبيع"
placeholder="تاريخ ووقت البيع"
/>
</FormField>
@ -439,13 +439,13 @@ const Sales_invoicesNew = () => {
<FormField label="الحالة" labelFor="status">
<Field name="status" id="status" component="select">
<option value="draft">draft</option>
<option value="draft">مسودة</option>
<option value="paid">paid</option>
<option value="paid">مدفوعة</option>
<option value="voided">voided</option>
<option value="voided">ملغاة</option>
<option value="refunded">refunded</option>
<option value="refunded">مسترجعة</option>
</Field>
</FormField>
@ -469,12 +469,12 @@ const Sales_invoicesNew = () => {
<FormField
label="الإجماليقبلالخصم"
label="الإجمالي قبل الخصم"
>
<Field
type="number"
name="subtotal_amount"
placeholder="الإجماليقبلالخصم"
placeholder="الإجمالي قبل الخصم"
/>
</FormField>
@ -541,12 +541,12 @@ const Sales_invoicesNew = () => {
<FormField
label="الإجماليالنهائي"
label="الإجمالي النهائي"
>
<Field
type="number"
name="total_amount"
placeholder="الإجماليالنهائي"
placeholder="الإجمالي النهائي"
/>
</FormField>
@ -577,12 +577,12 @@ const Sales_invoicesNew = () => {
<FormField
label="إجماليالتكلفة"
label="إجمالي التكلفة"
>
<Field
type="number"
name="total_cost_amount"
placeholder="إجماليالتكلفة"
placeholder="إجمالي التكلفة"
/>
</FormField>
@ -613,12 +613,12 @@ const Sales_invoicesNew = () => {
<FormField
label="إجماليالربح"
label="إجمالي الربح"
>
<Field
type="number"
name="total_profit_amount"
placeholder="إجماليالربح"
placeholder="إجمالي الربح"
/>
</FormField>
@ -656,16 +656,16 @@ const Sales_invoicesNew = () => {
<FormField label="طريقةالدفع" labelFor="payment_method">
<FormField label="طريقة الدفع" labelFor="payment_method">
<Field name="payment_method" id="payment_method" component="select">
<option value="cash">cash</option>
<option value="cash">نقداً</option>
<option value="card">card</option>
<option value="card">بطاقة</option>
<option value="transfer">transfer</option>
<option value="transfer">تحويل</option>
<option value="mixed">mixed</option>
<option value="mixed">مختلط</option>
</Field>
</FormField>
@ -732,7 +732,7 @@ const Sales_invoicesNew = () => {
<FormField label='بنودالفاتورة' labelFor='items'>
<FormField label='بنود الفاتورة' labelFor='items'>
<Field
name='items'
id='items'
@ -766,7 +766,7 @@ const Sales_invoicesNew = () => {
<FormField label="organizations" labelFor="organizations">
<FormField label="المنظمة" labelFor="organizations">
<Field name="organizations" id="organizations" component={SelectField} options={[]} itemRef={'organizations'}></Field>
</FormField>
@ -778,9 +778,9 @@ const Sales_invoicesNew = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/sales_invoices/sales_invoices-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/sales_invoices/sales_invoices-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -34,10 +34,10 @@ const Sales_invoicesTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'رقمالفاتورة', title: 'invoice_number'},{label: 'ملاحظات', title: 'notes'},
const [filters] = useState([{label: 'رقم الفاتورة', title: 'invoice_number'},{label: 'ملاحظات', title: 'notes'},
{label: 'الإجماليقبلالخصم', title: 'subtotal_amount', number: 'true'},{label: 'الخصم', title: 'discount_amount', number: 'true'},{label: 'الإجماليالنهائي', title: 'total_amount', number: 'true'},{label: 'إجماليالتكلفة', title: 'total_cost_amount', number: 'true'},{label: 'إجماليالربح', title: 'total_profit_amount', number: 'true'},
{label: 'تاريخووقتالبيع', title: 'sold_at', date: 'true'},
{label: 'الإجمالي قبل الخصم', title: 'subtotal_amount', number: 'true'},{label: 'الخصم', title: 'discount_amount', number: 'true'},{label: 'الإجمالي النهائي', title: 'total_amount', number: 'true'},{label: 'إجمالي التكلفة', title: 'total_cost_amount', number: 'true'},{label: 'إجمالي الربح', title: 'total_profit_amount', number: 'true'},
{label: 'تاريخ ووقت البيع', title: 'sold_at', date: 'true'},
{label: 'المتجر', title: 'shop'},
@ -47,8 +47,8 @@ const Sales_invoicesTablesPage = () => {
{label: 'الكاشير', title: 'cashier'},
{label: 'بنودالفاتورة', title: 'items'},
{label: 'الحالة', title: 'status', type: 'enum', options: ['draft','paid','voided','refunded']},{label: 'طريقةالدفع', title: 'payment_method', type: 'enum', options: ['cash','card','transfer','mixed']},
{label: 'بنود الفاتورة', title: 'items'},
{label: 'الحالة', title: 'status', type: 'enum', options: ['draft','paid','voided','refunded']},{label: 'طريقة الدفع', title: 'payment_method', type: 'enum', options: ['cash','card','transfer','mixed']},
]);
const hasCreatePermission = currentUser && hasPermission(currentUser, 'CREATE_SALES_INVOICES');
@ -94,28 +94,28 @@ const Sales_invoicesTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Sales_invoices')}</title>
<title>{getPageTitle('الفواتير')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Sales_invoices" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="الفواتير" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/sales_invoices/sales_invoices-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/sales_invoices/sales_invoices-new'} color='info' label='إضافة فاتورة'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='إضافة تصفية'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getSales_invoicesCSV} />
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getSales_invoicesCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
label='Upload CSV'
label='رفع CSV'
onClick={() => setIsModalActive(true)}
/>
)}
@ -124,7 +124,7 @@ const Sales_invoicesTablesPage = () => {
<div id='delete-rows-button'></div>
<Link href={'/sales_invoices/sales_invoices-list'}>
Back to <span className='capitalize'>kanban</span>
العودة إلى عرض البطاقات
</Link>
</div>
@ -139,9 +139,9 @@ const Sales_invoicesTablesPage = () => {
</CardBox>
</SectionMain>
<CardBoxModal
title='Upload CSV'
title='رفع CSV'
buttonColor='info'
buttonLabel={'Confirm'}
buttonLabel={'تأكيد'}
// buttonLabel={false ? 'Deleting...' : 'Confirm'}
isActive={isModalActive}
onConfirm={onModalConfirm}

View File

@ -21,7 +21,10 @@ import {SwitchField} from "../../components/SwitchField";
import FormField from "../../components/FormField";
import {hasPermission} from "../../helpers/userPermissions";
import {
formatSalesInvoicePaymentMethod,
formatSalesInvoiceStatus,
} from '../../helpers/salesInvoiceLabels';
const Sales_invoicesView = () => {
const router = useRouter()
@ -33,11 +36,7 @@ const Sales_invoicesView = () => {
const { id } = router.query;
function removeLastCharacter(str) {
console.log(str,`str`)
return str.slice(0, -1);
}
useEffect(() => {
dispatch(fetch({ id }));
}, [dispatch, id]);
@ -46,13 +45,13 @@ const Sales_invoicesView = () => {
return (
<>
<Head>
<title>{getPageTitle('View sales_invoices')}</title>
<title>{getPageTitle('تفاصيل الفاتورة')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View sales_invoices')} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تفاصيل الفاتورة'} main>
<BaseButton
color='info'
label='Edit'
label='تعديل'
href={`/sales_invoices/sales_invoices-edit/?id=${id}`}
/>
</SectionTitleLineWithButton>
@ -91,7 +90,7 @@ const Sales_invoicesView = () => {
<p>{sales_invoices?.shop?.shop_name ?? 'No data'}</p>
<p>{sales_invoices?.shop?.shop_name ?? 'لا توجد بيانات'}</p>
@ -139,7 +138,7 @@ const Sales_invoicesView = () => {
<p className={'block font-bold mb-2'}>الكاشير</p>
<p>{sales_invoices?.cashier?.firstName ?? 'No data'}</p>
<p>{sales_invoices?.cashier?.firstName ?? 'لا توجد بيانات'}</p>
@ -173,7 +172,7 @@ const Sales_invoicesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>رقمالفاتورة</p>
<p className={'block font-bold mb-2'}>رقم الفاتورة</p>
<p>{sales_invoices?.invoice_number}</p>
</div>
@ -214,7 +213,7 @@ const Sales_invoicesView = () => {
<FormField label='تاريخووقتالبيع'>
<FormField label='تاريخ ووقت البيع'>
{sales_invoices.sold_at ? <DatePicker
dateFormat="yyyy-MM-dd hh:mm"
showTimeSelect
@ -224,7 +223,7 @@ const Sales_invoicesView = () => {
) : null
}
disabled
/> : <p>No تاريخووقتالبيع</p>}
/> : <p>لا يوجد تاريخ ووقت للبيع</p>}
</FormField>
@ -260,7 +259,7 @@ const Sales_invoicesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>الحالة</p>
<p>{sales_invoices?.status ?? 'No data'}</p>
<p>{formatSalesInvoiceStatus(sales_invoices?.status)}</p>
</div>
@ -283,8 +282,8 @@ const Sales_invoicesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>الإجماليقبلالخصم</p>
<p>{sales_invoices?.subtotal_amount || 'No data'}</p>
<p className={'block font-bold mb-2'}>الإجمالي قبل الخصم</p>
<p>{sales_invoices?.subtotal_amount || 'لا توجد بيانات'}</p>
</div>
@ -316,7 +315,7 @@ const Sales_invoicesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>الخصم</p>
<p>{sales_invoices?.discount_amount || 'No data'}</p>
<p>{sales_invoices?.discount_amount || 'لا توجد بيانات'}</p>
</div>
@ -347,8 +346,8 @@ const Sales_invoicesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>الإجماليالنهائي</p>
<p>{sales_invoices?.total_amount || 'No data'}</p>
<p className={'block font-bold mb-2'}>الإجمالي النهائي</p>
<p>{sales_invoices?.total_amount || 'لا توجد بيانات'}</p>
</div>
@ -379,8 +378,8 @@ const Sales_invoicesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>إجماليالتكلفة</p>
<p>{sales_invoices?.total_cost_amount || 'No data'}</p>
<p className={'block font-bold mb-2'}>إجمالي التكلفة</p>
<p>{sales_invoices?.total_cost_amount || 'لا توجد بيانات'}</p>
</div>
@ -411,8 +410,8 @@ const Sales_invoicesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>إجماليالربح</p>
<p>{sales_invoices?.total_profit_amount || 'No data'}</p>
<p className={'block font-bold mb-2'}>إجمالي الربح</p>
<p>{sales_invoices?.total_profit_amount || 'لا توجد بيانات'}</p>
</div>
@ -451,8 +450,8 @@ const Sales_invoicesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>طريقةالدفع</p>
<p>{sales_invoices?.payment_method ?? 'No data'}</p>
<p className={'block font-bold mb-2'}>طريقة الدفع</p>
<p>{formatSalesInvoicePaymentMethod(sales_invoices?.payment_method)}</p>
</div>
@ -470,7 +469,7 @@ const Sales_invoicesView = () => {
<FormField label='Multi Text' hasTextareaHeight>
<FormField label='ملاحظات' hasTextareaHeight>
<textarea className={'w-full'} disabled value={sales_invoices?.notes} />
</FormField>
@ -520,7 +519,7 @@ const Sales_invoicesView = () => {
<>
<p className={'block font-bold mb-2'}>بنودالفاتورة</p>
<p className={'block font-bold mb-2'}>بنود الفاتورة</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -544,15 +543,15 @@ const Sales_invoicesView = () => {
<th>اسمالمنتجوقتالبيع</th>
<th>اسم المنتج وقت البيع</th>
<th>سعرالتكلفةوقتالبيع</th>
<th>سعر التكلفة وقت البيع</th>
<th>سعرالبيعوقتالبيع</th>
<th>سعر البيع وقت البيع</th>
@ -560,11 +559,11 @@ const Sales_invoicesView = () => {
<th>الإجماليللعنصر</th>
<th>إجمالي العنصر</th>
<th>الربحللعنصر</th>
<th>ربح العنصر</th>
@ -591,37 +590,37 @@ const Sales_invoicesView = () => {
<td data-label="product_name_snapshot">
<td data-label="اسم المنتج وقت البيع">
{ item.product_name_snapshot }
</td>
<td data-label="cost_price_snapshot">
<td data-label="سعر التكلفة وقت البيع">
{ item.cost_price_snapshot }
</td>
<td data-label="sale_price_snapshot">
<td data-label="سعر البيع وقت البيع">
{ item.sale_price_snapshot }
</td>
<td data-label="quantity">
<td data-label="الكمية">
{ item.quantity }
</td>
<td data-label="line_subtotal">
<td data-label="إجمالي العنصر">
{ item.line_subtotal }
</td>
<td data-label="line_profit">
<td data-label="ربح العنصر">
{ item.line_profit }
</td>
@ -634,7 +633,7 @@ const Sales_invoicesView = () => {
</tbody>
</table>
</div>
{!sales_invoices?.items?.length && <div className={'text-center py-4'}>No data</div>}
{!sales_invoices?.items?.length && <div className={'text-center py-4'}>لا توجد بيانات</div>}
</CardBox>
</>
@ -665,7 +664,7 @@ const Sales_invoicesView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>organizations</p>
<p className={'block font-bold mb-2'}>المنظمة</p>
@ -674,7 +673,7 @@ const Sales_invoicesView = () => {
<p>{sales_invoices?.organizations?.name ?? 'No data'}</p>
<p>{sales_invoices?.organizations?.name ?? 'لا توجد بيانات'}</p>
@ -710,7 +709,7 @@ const Sales_invoicesView = () => {
<>
<p className={'block font-bold mb-2'}>Sales_invoice_items الفاتورة</p>
<p className={'block font-bold mb-2'}>بنود الفاتورة</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -725,15 +724,15 @@ const Sales_invoicesView = () => {
<th>اسمالمنتجوقتالبيع</th>
<th>اسم المنتج وقت البيع</th>
<th>سعرالتكلفةوقتالبيع</th>
<th>سعر التكلفة وقت البيع</th>
<th>سعرالبيعوقتالبيع</th>
<th>سعر البيع وقت البيع</th>
@ -741,11 +740,11 @@ const Sales_invoicesView = () => {
<th>الإجماليللعنصر</th>
<th>إجمالي العنصر</th>
<th>الربحللعنصر</th>
<th>ربح العنصر</th>
</tr>
@ -760,37 +759,37 @@ const Sales_invoicesView = () => {
<td data-label="product_name_snapshot">
<td data-label="اسم المنتج وقت البيع">
{ item.product_name_snapshot }
</td>
<td data-label="cost_price_snapshot">
<td data-label="سعر التكلفة وقت البيع">
{ item.cost_price_snapshot }
</td>
<td data-label="sale_price_snapshot">
<td data-label="سعر البيع وقت البيع">
{ item.sale_price_snapshot }
</td>
<td data-label="quantity">
<td data-label="الكمية">
{ item.quantity }
</td>
<td data-label="line_subtotal">
<td data-label="إجمالي العنصر">
{ item.line_subtotal }
</td>
<td data-label="line_profit">
<td data-label="ربح العنصر">
{ item.line_profit }
</td>
@ -800,7 +799,7 @@ const Sales_invoicesView = () => {
</tbody>
</table>
</div>
{!sales_invoices?.sales_invoice_items_invoice?.length && <div className={'text-center py-4'}>No data</div>}
{!sales_invoices?.sales_invoice_items_invoice?.length && <div className={'text-center py-4'}>لا توجد بيانات</div>}
</CardBox>
</>
@ -811,7 +810,7 @@ const Sales_invoicesView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/sales_invoices/sales_invoices-list')}
/>
</CardBox>

View File

@ -73,7 +73,7 @@ const SearchView = () => {
<BaseDivider />
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/dashboard')}
/>
</CardBox>

View File

@ -333,10 +333,10 @@ const EditShops = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit shops')}</title>
<title>{getPageTitle('تعديل المحل')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit shops'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل المحل'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -350,11 +350,11 @@ const EditShops = () => {
<FormField
label="اسمالمتجر"
label="اسم المحل"
>
<Field
name="shop_name"
placeholder="اسمالمتجر"
placeholder="اسم المحل"
/>
</FormField>
@ -387,11 +387,11 @@ const EditShops = () => {
<FormField
label="اسمالمالك"
label="اسم المالك"
>
<Field
name="owner_name"
placeholder="اسمالمالك"
placeholder="اسم المالك"
/>
</FormField>
@ -424,11 +424,11 @@ const EditShops = () => {
<FormField
label="هاتفالمتجر"
label="هاتف المحل"
>
<Field
name="phone"
placeholder="هاتفالمتجر"
placeholder="هاتف المحل"
/>
</FormField>
@ -493,11 +493,11 @@ const EditShops = () => {
<FormField
label="اسمالعملةالمحلية"
label="اسم العملة المحلية"
>
<Field
name="currency_name"
placeholder="اسمالعملةالمحلية"
placeholder="اسم العملة المحلية"
/>
</FormField>
@ -536,12 +536,12 @@ const EditShops = () => {
<FormField
label="سعرالدولاراليومي"
label="سعر الدولار اليومي"
>
<Field
type="number"
name="usd_rate"
placeholder="سعرالدولاراليومي"
placeholder="سعر الدولار اليومي"
/>
</FormField>
@ -583,7 +583,7 @@ const EditShops = () => {
<FormField label='السماحبمخزونسالب' labelFor='allow_negative_stock'>
<FormField label='السماح بمخزون سالب' labelFor='allow_negative_stock'>
<Field
name='allow_negative_stock'
id='allow_negative_stock'
@ -658,7 +658,7 @@ const EditShops = () => {
<FormField label='organizations' labelFor='organizations'>
<FormField label='المنظمة' labelFor='organizations'>
<Field
name='organizations'
id='organizations'
@ -705,9 +705,9 @@ const EditShops = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/shops/shops-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/shops/shops-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -330,10 +330,10 @@ const EditShopsPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Edit shops')}</title>
<title>{getPageTitle('تعديل المحل')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'Edit shops'} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تعديل المحل'} main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -347,11 +347,11 @@ const EditShopsPage = () => {
<FormField
label="اسمالمتجر"
label="اسم المحل"
>
<Field
name="shop_name"
placeholder="اسمالمتجر"
placeholder="اسم المحل"
/>
</FormField>
@ -384,11 +384,11 @@ const EditShopsPage = () => {
<FormField
label="اسمالمالك"
label="اسم المالك"
>
<Field
name="owner_name"
placeholder="اسمالمالك"
placeholder="اسم المالك"
/>
</FormField>
@ -421,11 +421,11 @@ const EditShopsPage = () => {
<FormField
label="هاتفالمتجر"
label="هاتف المحل"
>
<Field
name="phone"
placeholder="هاتفالمتجر"
placeholder="هاتف المحل"
/>
</FormField>
@ -490,11 +490,11 @@ const EditShopsPage = () => {
<FormField
label="اسمالعملةالمحلية"
label="اسم العملة المحلية"
>
<Field
name="currency_name"
placeholder="اسمالعملةالمحلية"
placeholder="اسم العملة المحلية"
/>
</FormField>
@ -533,12 +533,12 @@ const EditShopsPage = () => {
<FormField
label="سعرالدولاراليومي"
label="سعر الدولار اليومي"
>
<Field
type="number"
name="usd_rate"
placeholder="سعرالدولاراليومي"
placeholder="سعر الدولار اليومي"
/>
</FormField>
@ -580,7 +580,7 @@ const EditShopsPage = () => {
<FormField label='السماحبمخزونسالب' labelFor='allow_negative_stock'>
<FormField label='السماح بمخزون سالب' labelFor='allow_negative_stock'>
<Field
name='allow_negative_stock'
id='allow_negative_stock'
@ -655,7 +655,7 @@ const EditShopsPage = () => {
<FormField label='organizations' labelFor='organizations'>
<FormField label='المنظمة' labelFor='organizations'>
<Field
name='organizations'
id='organizations'
@ -702,9 +702,9 @@ const EditShopsPage = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/shops/shops-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/shops/shops-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -34,9 +34,9 @@ const ShopsTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'اسمالمتجر', title: 'shop_name'},{label: 'اسمالمالك', title: 'owner_name'},{label: 'هاتفالمتجر', title: 'phone'},{label: 'العنوان', title: 'address'},{label: 'اسمالعملةالمحلية', title: 'currency_name'},
const [filters] = useState([{label: 'اسم المحل', title: 'shop_name'},{label: 'اسم المالك', title: 'owner_name'},{label: 'هاتف المحل', title: 'phone'},{label: 'العنوان', title: 'address'},{label: 'اسم العملة المحلية', title: 'currency_name'},
{label: 'سعرالدولاراليومي', title: 'usd_rate', number: 'true'},
{label: 'سعر الدولار اليومي', title: 'usd_rate', number: 'true'},
@ -86,28 +86,28 @@ const ShopsTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Shops')}</title>
<title>{getPageTitle('المحلات')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Shops" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المحلات" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/shops/shops-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/shops/shops-new'} color='info' label='إضافة محل'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='إضافة تصفية'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getShopsCSV} />
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getShopsCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
label='Upload CSV'
label='رفع CSV'
onClick={() => setIsModalActive(true)}
/>
)}
@ -117,7 +117,7 @@ const ShopsTablesPage = () => {
</div>
<div className='md:inline-flex items-center ms-auto'>
<Link href={'/shops/shops-table'}>Switch to Table</Link>
<Link href={'/shops/shops-table'}>عرض الجدول</Link>
</div>
</CardBox>
@ -133,9 +133,9 @@ const ShopsTablesPage = () => {
</SectionMain>
<CardBoxModal
title='Upload CSV'
title='رفع ملف CSV'
buttonColor='info'
buttonLabel={'Confirm'}
buttonLabel={'تأكيد'}
// buttonLabel={false ? 'Deleting...' : 'Confirm'}
isActive={isModalActive}
onConfirm={onModalConfirm}

View File

@ -190,10 +190,10 @@ const ShopsNew = () => {
return (
<>
<Head>
<title>{getPageTitle('New Item')}</title>
<title>{getPageTitle('إضافة محل')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="New Item" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="إضافة محل" main>
{''}
</SectionTitleLineWithButton>
<CardBox>
@ -210,11 +210,11 @@ const ShopsNew = () => {
<FormField
label="اسمالمتجر"
label="اسم المحل"
>
<Field
name="shop_name"
placeholder="اسمالمتجر"
placeholder="اسم المحل"
/>
</FormField>
@ -245,11 +245,11 @@ const ShopsNew = () => {
<FormField
label="اسمالمالك"
label="اسم المالك"
>
<Field
name="owner_name"
placeholder="اسمالمالك"
placeholder="اسم المالك"
/>
</FormField>
@ -280,11 +280,11 @@ const ShopsNew = () => {
<FormField
label="هاتفالمتجر"
label="هاتف المحل"
>
<Field
name="phone"
placeholder="هاتفالمتجر"
placeholder="هاتف المحل"
/>
</FormField>
@ -345,11 +345,11 @@ const ShopsNew = () => {
<FormField
label="اسمالعملةالمحلية"
label="اسم العملة المحلية"
>
<Field
name="currency_name"
placeholder="اسمالعملةالمحلية"
placeholder="اسم العملة المحلية"
/>
</FormField>
@ -386,12 +386,12 @@ const ShopsNew = () => {
<FormField
label="سعرالدولاراليومي"
label="سعر الدولار اليومي"
>
<Field
type="number"
name="usd_rate"
placeholder="سعرالدولاراليومي"
placeholder="سعر الدولار اليومي"
/>
</FormField>
@ -431,7 +431,7 @@ const ShopsNew = () => {
<FormField label='السماحبمخزونسالب' labelFor='allow_negative_stock'>
<FormField label='السماح بمخزون سالب' labelFor='allow_negative_stock'>
<Field
name='allow_negative_stock'
id='allow_negative_stock'
@ -501,7 +501,7 @@ const ShopsNew = () => {
<FormField label="organizations" labelFor="organizations">
<FormField label="المنظمة" labelFor="organizations">
<Field name="organizations" id="organizations" component={SelectField} options={[]} itemRef={'organizations'}></Field>
</FormField>
@ -513,9 +513,9 @@ const ShopsNew = () => {
<BaseDivider />
<BaseButtons>
<BaseButton type="submit" color="info" label="Submit" />
<BaseButton type="reset" color="info" outline label="Reset" />
<BaseButton type='reset' color='danger' outline label='Cancel' onClick={() => router.push('/shops/shops-list')}/>
<BaseButton type="submit" color="info" label="حفظ" />
<BaseButton type="reset" color="info" outline label="إعادة تعيين" />
<BaseButton type='reset' color='danger' outline label='إلغاء' onClick={() => router.push('/shops/shops-list')}/>
</BaseButtons>
</Form>
</Formik>

View File

@ -34,9 +34,9 @@ const ShopsTablesPage = () => {
const dispatch = useAppDispatch();
const [filters] = useState([{label: 'اسمالمتجر', title: 'shop_name'},{label: 'اسمالمالك', title: 'owner_name'},{label: 'هاتفالمتجر', title: 'phone'},{label: 'العنوان', title: 'address'},{label: 'اسمالعملةالمحلية', title: 'currency_name'},
const [filters] = useState([{label: 'اسم المحل', title: 'shop_name'},{label: 'اسم المالك', title: 'owner_name'},{label: 'هاتف المحل', title: 'phone'},{label: 'العنوان', title: 'address'},{label: 'اسم العملة المحلية', title: 'currency_name'},
{label: 'سعرالدولاراليومي', title: 'usd_rate', number: 'true'},
{label: 'سعر الدولار اليومي', title: 'usd_rate', number: 'true'},
@ -86,28 +86,28 @@ const ShopsTablesPage = () => {
return (
<>
<Head>
<title>{getPageTitle('Shops')}</title>
<title>{getPageTitle('المحلات')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="Shops" main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title="المحلات" main>
{''}
</SectionTitleLineWithButton>
<CardBox className='mb-6' cardBoxClassName='flex flex-wrap'>
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/shops/shops-new'} color='info' label='New Item'/>}
{hasCreatePermission && <BaseButton className={'mr-3'} href={'/shops/shops-new'} color='info' label='إضافة محل'/>}
<BaseButton
className={'mr-3'}
color='info'
label='Filter'
label='إضافة تصفية'
onClick={addFilter}
/>
<BaseButton className={'mr-3'} color='info' label='Download CSV' onClick={getShopsCSV} />
<BaseButton className={'mr-3'} color='info' label='تنزيل CSV' onClick={getShopsCSV} />
{hasCreatePermission && (
<BaseButton
color='info'
label='Upload CSV'
label='رفع CSV'
onClick={() => setIsModalActive(true)}
/>
)}
@ -116,7 +116,7 @@ const ShopsTablesPage = () => {
<div id='delete-rows-button'></div>
<Link href={'/shops/shops-list'}>
Back to <span className='capitalize'>card</span>
العودة إلى عرض البطاقات
</Link>
</div>
@ -131,9 +131,9 @@ const ShopsTablesPage = () => {
</CardBox>
</SectionMain>
<CardBoxModal
title='Upload CSV'
title='رفع ملف CSV'
buttonColor='info'
buttonLabel={'Confirm'}
buttonLabel={'تأكيد'}
// buttonLabel={false ? 'Deleting...' : 'Confirm'}
isActive={isModalActive}
onConfirm={onModalConfirm}

View File

@ -46,13 +46,13 @@ const ShopsView = () => {
return (
<>
<Head>
<title>{getPageTitle('View shops')}</title>
<title>{getPageTitle('تفاصيل المحل')}</title>
</Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={removeLastCharacter('View shops')} main>
<SectionTitleLineWithButton icon={mdiChartTimelineVariant} title={'تفاصيل المحل'} main>
<BaseButton
color='info'
label='Edit'
label='تعديل'
href={`/shops/shops-edit/?id=${id}`}
/>
</SectionTitleLineWithButton>
@ -61,7 +61,7 @@ const ShopsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>اسمالمتجر</p>
<p className={'block font-bold mb-2'}>اسم المحل</p>
<p>{shops?.shop_name}</p>
</div>
@ -93,7 +93,7 @@ const ShopsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>اسمالمالك</p>
<p className={'block font-bold mb-2'}>اسم المالك</p>
<p>{shops?.owner_name}</p>
</div>
@ -125,7 +125,7 @@ const ShopsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>هاتفالمتجر</p>
<p className={'block font-bold mb-2'}>هاتف المحل</p>
<p>{shops?.phone}</p>
</div>
@ -158,7 +158,7 @@ const ShopsView = () => {
<FormField label='Multi Text' hasTextareaHeight>
<FormField label='العنوان' hasTextareaHeight>
<textarea className={'w-full'} disabled value={shops?.address} />
</FormField>
@ -188,7 +188,7 @@ const ShopsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>اسمالعملةالمحلية</p>
<p className={'block font-bold mb-2'}>اسم العملة المحلية</p>
<p>{shops?.currency_name}</p>
</div>
@ -226,8 +226,8 @@ const ShopsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>سعرالدولاراليومي</p>
<p>{shops?.usd_rate || 'No data'}</p>
<p className={'block font-bold mb-2'}>سعر الدولار اليومي</p>
<p>{shops?.usd_rate || 'لا توجد بيانات'}</p>
</div>
@ -267,7 +267,7 @@ const ShopsView = () => {
<FormField label='السماحبمخزونسالب'>
<FormField label='السماح بمخزون سالب'>
<SwitchField
field={{name: 'allow_negative_stock', value: shops?.allow_negative_stock}}
form={{setFieldValue: () => null}}
@ -341,7 +341,7 @@ const ShopsView = () => {
<div className={'mb-4'}>
<p className={'block font-bold mb-2'}>organizations</p>
<p className={'block font-bold mb-2'}>المنظمة</p>
@ -350,7 +350,7 @@ const ShopsView = () => {
<p>{shops?.organizations?.name ?? 'No data'}</p>
<p>{shops?.organizations?.name ?? 'لا توجد بيانات'}</p>
@ -383,7 +383,7 @@ const ShopsView = () => {
<>
<p className={'block font-bold mb-2'}>Categories المتجر</p>
<p className={'block font-bold mb-2'}>أقسام المحل</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -396,7 +396,7 @@ const ShopsView = () => {
<th>اسمالقسم</th>
<th>اسم القسم</th>
@ -404,7 +404,7 @@ const ShopsView = () => {
<th>ترتيبالعرض</th>
<th>ترتيب العرض</th>
@ -421,25 +421,25 @@ const ShopsView = () => {
<td data-label="category_name">
<td data-label="اسم القسم">
{ item.category_name }
</td>
<td data-label="description">
<td data-label="الوصف">
{ item.description }
</td>
<td data-label="sort_order">
<td data-label="ترتيب العرض">
{ item.sort_order }
</td>
<td data-label="is_active">
<td data-label="الحالة">
{ dataFormatter.booleanFormatter(item.is_active) }
</td>
@ -449,13 +449,13 @@ const ShopsView = () => {
</tbody>
</table>
</div>
{!shops?.categories_shop?.length && <div className={'text-center py-4'}>No data</div>}
{!shops?.categories_shop?.length && <div className={'text-center py-4'}>لا توجد بيانات</div>}
</CardBox>
</>
<>
<p className={'block font-bold mb-2'}>Products المتجر</p>
<p className={'block font-bold mb-2'}>منتجات المحل</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -470,11 +470,11 @@ const ShopsView = () => {
<th>اسمالمنتج</th>
<th>اسم المنتج</th>
<th>رمزالمنتج</th>
<th>رمز المنتج</th>
@ -482,37 +482,37 @@ const ShopsView = () => {
<th>سعرالتكلفةالحقيقي</th>
<th>سعر التكلفة</th>
<th>سعرالبيع</th>
<th>سعر البيع</th>
<th>سعرالبيعالسابق</th>
<th>سعر البيع السابق</th>
<th>سعرالتكلفةالسابق</th>
<th>سعر التكلفة السابق</th>
<th>السعربالدولار</th>
<th>السعر بالدولار</th>
<th>الكميةبالمخزون</th>
<th>الكمية بالمخزون</th>
<th>حدالتنبيهلنقصالمخزون</th>
<th>حد التنبيه لنقص المخزون</th>
<th>متاحللبيع</th>
<th>متاح للبيع</th>
</tr>
@ -527,61 +527,61 @@ const ShopsView = () => {
<td data-label="product_name">
<td data-label="اسم المنتج">
{ item.product_name }
</td>
<td data-label="sku">
<td data-label="رمز المنتج">
{ item.sku }
</td>
<td data-label="barcode">
<td data-label="الباركود">
{ item.barcode }
</td>
<td data-label="cost_price">
<td data-label="سعر التكلفة">
{ item.cost_price }
</td>
<td data-label="sale_price">
<td data-label="سعر البيع">
{ item.sale_price }
</td>
<td data-label="sale_price_backup">
<td data-label="سعر البيع السابق">
{ item.sale_price_backup }
</td>
<td data-label="cost_price_backup">
<td data-label="سعر التكلفة السابق">
{ item.cost_price_backup }
</td>
<td data-label="usd_price">
<td data-label="السعر بالدولار">
{ item.usd_price }
</td>
<td data-label="stock_quantity">
<td data-label="الكمية بالمخزون">
{ item.stock_quantity }
</td>
<td data-label="low_stock_threshold">
<td data-label="حد التنبيه لنقص المخزون">
{ item.low_stock_threshold }
</td>
@ -589,7 +589,7 @@ const ShopsView = () => {
<td data-label="is_active">
<td data-label="الحالة">
{ dataFormatter.booleanFormatter(item.is_active) }
</td>
@ -599,13 +599,13 @@ const ShopsView = () => {
</tbody>
</table>
</div>
{!shops?.products_shop?.length && <div className={'text-center py-4'}>No data</div>}
{!shops?.products_shop?.length && <div className={'text-center py-4'}>لا توجد بيانات</div>}
</CardBox>
</>
<>
<p className={'block font-bold mb-2'}>Sales_invoices المتجر</p>
<p className={'block font-bold mb-2'}>فواتير المحل</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -620,11 +620,11 @@ const ShopsView = () => {
<th>رقمالفاتورة</th>
<th>رقم الفاتورة</th>
<th>تاريخووقتالبيع</th>
<th>تاريخ ووقت البيع</th>
@ -632,7 +632,7 @@ const ShopsView = () => {
<th>الإجماليقبلالخصم</th>
<th>الإجمالي قبل الخصم</th>
@ -640,19 +640,19 @@ const ShopsView = () => {
<th>الإجماليالنهائي</th>
<th>الإجمالي النهائي</th>
<th>إجماليالتكلفة</th>
<th>إجمالي التكلفة</th>
<th>إجماليالربح</th>
<th>إجمالي الربح</th>
<th>طريقةالدفع</th>
<th>طريقة الدفع</th>
@ -673,61 +673,61 @@ const ShopsView = () => {
<td data-label="invoice_number">
<td data-label="رقم الفاتورة">
{ item.invoice_number }
</td>
<td data-label="sold_at">
<td data-label="تاريخ البيع">
{ dataFormatter.dateTimeFormatter(item.sold_at) }
</td>
<td data-label="status">
<td data-label="الحالة">
{ item.status }
</td>
<td data-label="subtotal_amount">
<td data-label="الإجمالي قبل الخصم">
{ item.subtotal_amount }
</td>
<td data-label="discount_amount">
<td data-label="الخصم">
{ item.discount_amount }
</td>
<td data-label="total_amount">
<td data-label="الإجمالي النهائي">
{ item.total_amount }
</td>
<td data-label="total_cost_amount">
<td data-label="إجمالي التكلفة">
{ item.total_cost_amount }
</td>
<td data-label="total_profit_amount">
<td data-label="إجمالي الربح">
{ item.total_profit_amount }
</td>
<td data-label="payment_method">
<td data-label="طريقة الدفع">
{ item.payment_method }
</td>
<td data-label="notes">
<td data-label="الملاحظات">
{ item.notes }
</td>
@ -739,14 +739,14 @@ const ShopsView = () => {
</tbody>
</table>
</div>
{!shops?.sales_invoices_shop?.length && <div className={'text-center py-4'}>No data</div>}
{!shops?.sales_invoices_shop?.length && <div className={'text-center py-4'}>لا توجد بيانات</div>}
</CardBox>
</>
<>
<p className={'block font-bold mb-2'}>Price_change_logs المتجر</p>
<p className={'block font-bold mb-2'}>سجل تغييرات الأسعار</p>
<CardBox
className='mb-6 border border-gray-300 rounded overflow-hidden'
hasTable
@ -761,19 +761,19 @@ const ShopsView = () => {
<th>تاريخالتغيير</th>
<th>تاريخ التغيير</th>
<th>نوعالتغيير</th>
<th>نوع التغيير</th>
<th>سعرالدولارقبل</th>
<th>سعر الدولار قبل</th>
<th>سعرالدولاربعد</th>
<th>سعر الدولار بعد</th>
@ -792,31 +792,31 @@ const ShopsView = () => {
<td data-label="changed_at">
<td data-label="وقت التغيير">
{ dataFormatter.dateTimeFormatter(item.changed_at) }
</td>
<td data-label="change_type">
<td data-label="نوع التغيير">
{ item.change_type }
</td>
<td data-label="usd_rate_before">
<td data-label="سعر الدولار السابق">
{ item.usd_rate_before }
</td>
<td data-label="usd_rate_after">
<td data-label="سعر الدولار الجديد">
{ item.usd_rate_after }
</td>
<td data-label="summary">
<td data-label="الملخص">
{ item.summary }
</td>
@ -826,7 +826,7 @@ const ShopsView = () => {
</tbody>
</table>
</div>
{!shops?.price_change_logs_shop?.length && <div className={'text-center py-4'}>No data</div>}
{!shops?.price_change_logs_shop?.length && <div className={'text-center py-4'}>لا توجد بيانات</div>}
</CardBox>
</>
@ -836,7 +836,7 @@ const ShopsView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/shops/shops-list')}
/>
</CardBox>

View File

@ -288,7 +288,7 @@ const UsersView = () => {
<p>{users?.app_role?.name ?? 'No data'}</p>
<p>{users?.app_role?.name ?? 'لا توجد بيانات'}</p>
@ -436,7 +436,7 @@ const UsersView = () => {
<p>{users?.organizations?.name ?? 'No data'}</p>
<p>{users?.organizations?.name ?? 'لا توجد بيانات'}</p>
@ -486,11 +486,11 @@ const UsersView = () => {
<th>رقمالفاتورة</th>
<th>رقم الفاتورة</th>
<th>تاريخووقتالبيع</th>
<th>تاريخ ووقت البيع</th>
@ -498,7 +498,7 @@ const UsersView = () => {
<th>الإجماليقبلالخصم</th>
<th>الإجمالي قبل الخصم</th>
@ -506,19 +506,19 @@ const UsersView = () => {
<th>الإجماليالنهائي</th>
<th>الإجمالي النهائي</th>
<th>إجماليالتكلفة</th>
<th>إجمالي التكلفة</th>
<th>إجماليالربح</th>
<th>إجمالي الربح</th>
<th>طريقةالدفع</th>
<th>طريقة الدفع</th>
@ -702,7 +702,7 @@ const UsersView = () => {
<BaseButton
color='info'
label='Back'
label='رجوع'
onClick={() => router.push('/users/users-list')}
/>
</CardBox>