mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-04-07 13:41:23 +00:00
Complete dashboard translations & small UI improvements (#69)
* fix dropdown action Estimate Dashboard and fix translating full Dasboard page * Update app.php * fix locale in app.php config * Wizard install with translation, customer portal with translation, and fixing hardcoding strings to get translation * fixes asked to review * fixes pint --------- Co-authored-by: Max <contact@agencetwogether.fr> Co-authored-by: Darko Gjorgjijoski <5760249+gdarko@users.noreply.github.com>
This commit is contained in:
@@ -88,7 +88,7 @@ class CustomerStatsController extends Controller
|
|||||||
($receiptTotals[$i] - $expenseTotals[$i])
|
($receiptTotals[$i] - $expenseTotals[$i])
|
||||||
);
|
);
|
||||||
$i++;
|
$i++;
|
||||||
array_push($months, $start->format('M'));
|
array_push($months, $start->translatedFormat('M'));
|
||||||
$monthCounter++;
|
$monthCounter++;
|
||||||
$end->startOfMonth();
|
$end->startOfMonth();
|
||||||
$start->addMonth()->startOfMonth();
|
$start->addMonth()->startOfMonth();
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class DashboardController extends Controller
|
|||||||
($receipt_totals[$i] - $expense_totals[$i])
|
($receipt_totals[$i] - $expense_totals[$i])
|
||||||
);
|
);
|
||||||
$i++;
|
$i++;
|
||||||
array_push($months, $start->format('M'));
|
array_push($months, $start->translatedFormat('M'));
|
||||||
$monthCounter++;
|
$monthCounter++;
|
||||||
$end->startOfMonth();
|
$end->startOfMonth();
|
||||||
$start->addMonth()->startOfMonth();
|
$start->addMonth()->startOfMonth();
|
||||||
|
|||||||
@@ -54,8 +54,8 @@ class CustomerSalesReportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->translatedFormat($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->translatedFormat($dateFormat);
|
||||||
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ class ExpensesReportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->translatedFormat($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->translatedFormat($dateFormat);
|
||||||
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ class ItemSalesReportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->translatedFormat($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->translatedFormat($dateFormat);
|
||||||
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ class ProfitLossReportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->translatedFormat($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->translatedFormat($dateFormat);
|
||||||
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ class TaxSummaryReportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $company->id);
|
||||||
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->format($dateFormat);
|
$from_date = Carbon::createFromFormat('Y-m-d', $request->from_date)->translatedFormat($dateFormat);
|
||||||
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->format($dateFormat);
|
$to_date = Carbon::createFromFormat('Y-m-d', $request->to_date)->translatedFormat($dateFormat);
|
||||||
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
$currency = Currency::findOrFail(CompanySetting::getSetting('currency', $company->id));
|
||||||
|
|
||||||
$colors = [
|
$colors = [
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ class BootstrapController extends Controller
|
|||||||
'menu' => $menu,
|
'menu' => $menu,
|
||||||
'current_customer_currency' => Currency::find($customer->currency_id),
|
'current_customer_currency' => Currency::find($customer->currency_id),
|
||||||
'modules' => Module::where('enabled', true)->pluck('name'),
|
'modules' => Module::where('enabled', true)->pluck('name'),
|
||||||
|
'current_company_language' => CompanySetting::getSetting('language', $customer->company_id),
|
||||||
]]);
|
]]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
app/Http/Controllers/V1/Installation/LanguagesController.php
Executable file
21
app/Http/Controllers/V1/Installation/LanguagesController.php
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace InvoiceShelf\Http\Controllers\V1\Installation;
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use InvoiceShelf\Http\Controllers\Controller;
|
||||||
|
|
||||||
|
class LanguagesController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display the languages page.
|
||||||
|
*
|
||||||
|
* @return JsonResponse
|
||||||
|
*/
|
||||||
|
public function languages()
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'languages' => config('invoiceshelf.languages'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,11 +19,13 @@ class OnboardingWizardController extends Controller
|
|||||||
if (! InstallUtils::dbMarkerExists()) {
|
if (! InstallUtils::dbMarkerExists()) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'profile_complete' => 0,
|
'profile_complete' => 0,
|
||||||
|
'profile_language' => 'en',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'profile_complete' => Setting::getSetting('profile_complete'),
|
'profile_complete' => Setting::getSetting('profile_complete'),
|
||||||
|
'profile_language' => Setting::getSetting('profile_language'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,4 +45,13 @@ class OnboardingWizardController extends Controller
|
|||||||
'profile_complete' => Setting::getSetting('profile_complete'),
|
'profile_complete' => Setting::getSetting('profile_complete'),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function saveLanguage(Request $request)
|
||||||
|
{
|
||||||
|
Setting::setSetting('profile_language', $request->profile_language);
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'profile_language' => Setting::getSetting('profile_language'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,6 @@ class RoleResource extends JsonResource
|
|||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->scope);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->scope);
|
||||||
|
|
||||||
return Carbon::parse($this->created_at)->format($dateFormat);
|
return Carbon::parse($this->created_at)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class EstimateViewedMail extends Mailable
|
|||||||
public function build()
|
public function build()
|
||||||
{
|
{
|
||||||
return $this->from(config('mail.from.address'), config('mail.from.name'))
|
return $this->from(config('mail.from.address'), config('mail.from.name'))
|
||||||
|
->subject(__('notification_view_estimate'))
|
||||||
->markdown('emails.viewed.estimate', ['data', $this->data]);
|
->markdown('emails.viewed.estimate', ['data', $this->data]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ class InvoiceViewedMail extends Mailable
|
|||||||
public function build()
|
public function build()
|
||||||
{
|
{
|
||||||
return $this->from(config('mail.from.address'), config('mail.from.name'))
|
return $this->from(config('mail.from.address'), config('mail.from.name'))
|
||||||
|
->subject(__('notification_view_invoice'))
|
||||||
->markdown('emails.viewed.invoice', ['data', $this->data]);
|
->markdown('emails.viewed.invoice', ['data', $this->data]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class Customer extends Authenticatable implements HasMedia
|
|||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->created_at)->format($dateFormat);
|
return Carbon::parse($this->created_at)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setPasswordAttribute($value)
|
public function setPasswordAttribute($value)
|
||||||
|
|||||||
@@ -112,14 +112,14 @@ class Estimate extends Model implements HasMedia
|
|||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->expiry_date)->format($dateFormat);
|
return Carbon::parse($this->expiry_date)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedEstimateDateAttribute($value)
|
public function getFormattedEstimateDateAttribute($value)
|
||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->estimate_date)->format($dateFormat);
|
return Carbon::parse($this->estimate_date)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scopeEstimatesBetween($query, $start, $end)
|
public function scopeEstimatesBetween($query, $start, $end)
|
||||||
|
|||||||
@@ -72,14 +72,14 @@ class Expense extends Model implements HasMedia
|
|||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->expense_date)->format($dateFormat);
|
return Carbon::parse($this->expense_date)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedCreatedAtAttribute($value)
|
public function getFormattedCreatedAtAttribute($value)
|
||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->created_at)->format($dateFormat);
|
return Carbon::parse($this->created_at)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getReceiptUrlAttribute($value)
|
public function getReceiptUrlAttribute($value)
|
||||||
|
|||||||
@@ -189,14 +189,14 @@ class Invoice extends Model implements HasMedia
|
|||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->due_date)->format($dateFormat);
|
return Carbon::parse($this->due_date)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedInvoiceDateAttribute($value)
|
public function getFormattedInvoiceDateAttribute($value)
|
||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->invoice_date)->format($dateFormat);
|
return Carbon::parse($this->invoice_date)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function scopeWhereStatus($query, $status)
|
public function scopeWhereStatus($query, $status)
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class Item extends Model
|
|||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', request()->header('company'));
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', request()->header('company'));
|
||||||
|
|
||||||
return Carbon::parse($this->created_at)->format($dateFormat);
|
return Carbon::parse($this->created_at)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function taxes(): HasMany
|
public function taxes(): HasMany
|
||||||
|
|||||||
@@ -74,14 +74,14 @@ class Payment extends Model implements HasMedia
|
|||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->created_at)->format($dateFormat);
|
return Carbon::parse($this->created_at)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedPaymentDateAttribute($value)
|
public function getFormattedPaymentDateAttribute($value)
|
||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->payment_date)->format($dateFormat);
|
return Carbon::parse($this->payment_date)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPaymentPdfUrlAttribute()
|
public function getPaymentPdfUrlAttribute()
|
||||||
|
|||||||
@@ -57,14 +57,14 @@ class RecurringInvoice extends Model
|
|||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->starts_at)->format($dateFormat);
|
return Carbon::parse($this->starts_at)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedNextInvoiceAtAttribute()
|
public function getFormattedNextInvoiceAtAttribute()
|
||||||
{
|
{
|
||||||
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
$dateFormat = CompanySetting::getSetting('carbon_date_format', $this->company_id);
|
||||||
|
|
||||||
return Carbon::parse($this->next_invoice_at)->format($dateFormat);
|
return Carbon::parse($this->next_invoice_at)->translatedFormat($dateFormat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFormattedLimitDateAttribute()
|
public function getFormattedLimitDateAttribute()
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class DateFormatter
|
|||||||
|
|
||||||
foreach (static::$formats as $format) {
|
foreach (static::$formats as $format) {
|
||||||
$new[] = [
|
$new[] = [
|
||||||
'display_date' => Carbon::now()->format($format['carbon_format']),
|
'display_date' => Carbon::now()->translatedFormat($format['carbon_format']),
|
||||||
'carbon_format_value' => $format['carbon_format'],
|
'carbon_format_value' => $format['carbon_format'],
|
||||||
'moment_format_value' => $format['moment_format'],
|
'moment_format_value' => $format['moment_format'],
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -103,9 +103,9 @@ class EnvironmentManager
|
|||||||
*/
|
*/
|
||||||
public function saveDatabaseVariables(DatabaseEnvironmentRequest $request)
|
public function saveDatabaseVariables(DatabaseEnvironmentRequest $request)
|
||||||
{
|
{
|
||||||
|
|
||||||
$dbEnv = [
|
$dbEnv = [
|
||||||
'APP_URL' => $request->get('app_url'),
|
'APP_URL' => $request->get('app_url'),
|
||||||
|
'APP_LOCALE' => $request->get('app_locale'),
|
||||||
'DB_CONNECTION' => $request->get('database_connection'),
|
'DB_CONNECTION' => $request->get('database_connection'),
|
||||||
'SANCTUM_STATEFUL_DOMAINS' => $request->get('app_domain'),
|
'SANCTUM_STATEFUL_DOMAINS' => $request->get('app_domain'),
|
||||||
'SESSION_DOMAIN' => explode(':', $request->get('app_domain'))[0],
|
'SESSION_DOMAIN' => explode(':', $request->get('app_domain'))[0],
|
||||||
|
|||||||
@@ -11,4 +11,4 @@ return [
|
|||||||
'Redis' => Illuminate\Support\Facades\Redis::class,
|
'Redis' => Illuminate\Support\Facades\Redis::class,
|
||||||
])->toArray(),
|
])->toArray(),
|
||||||
|
|
||||||
];
|
];
|
||||||
@@ -78,18 +78,18 @@ return [
|
|||||||
* List of Fiscal Years
|
* List of Fiscal Years
|
||||||
*/
|
*/
|
||||||
'fiscal_years' => [
|
'fiscal_years' => [
|
||||||
['key' => 'january-december', 'value' => '1-12'],
|
['key' => 'settings.preferences.fiscal_years.january_december', 'value' => '1-12'],
|
||||||
['key' => 'february-january', 'value' => '2-1'],
|
['key' => 'settings.preferences.fiscal_years.february_january', 'value' => '2-1'],
|
||||||
['key' => 'march-february', 'value' => '3-2'],
|
['key' => 'settings.preferences.fiscal_years.march_february', 'value' => '3-2'],
|
||||||
['key' => 'april-march', 'value' => '4-3'],
|
['key' => 'settings.preferences.fiscal_years.april_march', 'value' => '4-3'],
|
||||||
['key' => 'may-april', 'value' => '5-4'],
|
['key' => 'settings.preferences.fiscal_years.may_april', 'value' => '5-4'],
|
||||||
['key' => 'june-may', 'value' => '6-5'],
|
['key' => 'settings.preferences.fiscal_years.june_may', 'value' => '6-5'],
|
||||||
['key' => 'july-june', 'value' => '7-6'],
|
['key' => 'settings.preferences.fiscal_years.july_june', 'value' => '7-6'],
|
||||||
['key' => 'august-july', 'value' => '8-7'],
|
['key' => 'settings.preferences.fiscal_years.august_july', 'value' => '8-7'],
|
||||||
['key' => 'september-august', 'value' => '9-8'],
|
['key' => 'settings.preferences.fiscal_years.september_august', 'value' => '9-8'],
|
||||||
['key' => 'october-september', 'value' => '10-9'],
|
['key' => 'settings.preferences.fiscal_years.october_september', 'value' => '10-9'],
|
||||||
['key' => 'november-october', 'value' => '11-10'],
|
['key' => 'settings.preferences.fiscal_years.november_october', 'value' => '11-10'],
|
||||||
['key' => 'december-november', 'value' => '12-11'],
|
['key' => 'settings.preferences.fiscal_years.december_november', 'value' => '12-11'],
|
||||||
],
|
],
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -408,7 +408,7 @@ return [
|
|||||||
*/
|
*/
|
||||||
'customer_menu' => [
|
'customer_menu' => [
|
||||||
[
|
[
|
||||||
'title' => 'Dashboard',
|
'title' => 'navigation.dashboard',
|
||||||
'link' => '/customer/dashboard',
|
'link' => '/customer/dashboard',
|
||||||
'icon' => '',
|
'icon' => '',
|
||||||
'name' => '',
|
'name' => '',
|
||||||
@@ -418,7 +418,7 @@ return [
|
|||||||
'model' => '',
|
'model' => '',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'title' => 'Invoices',
|
'title' => 'navigation.invoices',
|
||||||
'link' => '/customer/invoices',
|
'link' => '/customer/invoices',
|
||||||
'icon' => '',
|
'icon' => '',
|
||||||
'name' => '',
|
'name' => '',
|
||||||
@@ -428,7 +428,7 @@ return [
|
|||||||
'model' => '',
|
'model' => '',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'title' => 'Estimates',
|
'title' => 'navigation.estimates',
|
||||||
'link' => '/customer/estimates',
|
'link' => '/customer/estimates',
|
||||||
'icon' => '',
|
'icon' => '',
|
||||||
'name' => '',
|
'name' => '',
|
||||||
@@ -438,7 +438,7 @@ return [
|
|||||||
'model' => '',
|
'model' => '',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'title' => 'Payments',
|
'title' => 'navigation.payments',
|
||||||
'link' => '/customer/payments',
|
'link' => '/customer/payments',
|
||||||
'icon' => '',
|
'icon' => '',
|
||||||
'name' => '',
|
'name' => '',
|
||||||
@@ -448,7 +448,7 @@ return [
|
|||||||
'model' => '',
|
'model' => '',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'title' => 'Settings',
|
'title' => 'navigation.settings',
|
||||||
'link' => '/customer/settings',
|
'link' => '/customer/settings',
|
||||||
'icon' => '',
|
'icon' => '',
|
||||||
'name' => '',
|
'name' => '',
|
||||||
|
|||||||
117
lang/en.json
117
lang/en.json
@@ -100,16 +100,35 @@
|
|||||||
"pay_invoice": "Pay Invoice",
|
"pay_invoice": "Pay Invoice",
|
||||||
"login_successfully": "Logged in successfully!",
|
"login_successfully": "Logged in successfully!",
|
||||||
"logged_out_successfully": "Logged out successfully",
|
"logged_out_successfully": "Logged out successfully",
|
||||||
"mark_as_default": "Mark as default"
|
"mark_as_default": "Mark as default",
|
||||||
|
"no_data_found": "No data found",
|
||||||
|
"pagination": {
|
||||||
|
"previous": "Previous",
|
||||||
|
"next": "Next",
|
||||||
|
"showing": "Showing",
|
||||||
|
"to": "to",
|
||||||
|
"of": "of",
|
||||||
|
"results": "results"
|
||||||
|
},
|
||||||
|
"file_upload": {
|
||||||
|
"drag_a_file": "Drag a file here or",
|
||||||
|
"browse": "browse",
|
||||||
|
"to_choose": "to choose a file"
|
||||||
|
},
|
||||||
|
"multiselect": {
|
||||||
|
"the_list_is_empty": "The list is empty",
|
||||||
|
"no_results_found": "No results found"
|
||||||
|
},
|
||||||
|
"copy_to_clipboard": "Copy to Clipboard"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"select_year": "Select year",
|
"select_year": "Select year",
|
||||||
"cards": {
|
"cards": {
|
||||||
"due_amount": "Amount Due",
|
"due_amount": "Amount Due",
|
||||||
"customers": "Customers",
|
"customers": "Customer | Customers",
|
||||||
"invoices": "Invoices",
|
"invoices": "Invoice | Invoices",
|
||||||
"estimates": "Estimates",
|
"estimates": "Estimate | Estimates",
|
||||||
"payments": "Payments"
|
"payments": "Payment | Payments"
|
||||||
},
|
},
|
||||||
"chart_info": {
|
"chart_info": {
|
||||||
"total_sales": "Sales",
|
"total_sales": "Sales",
|
||||||
@@ -548,7 +567,18 @@
|
|||||||
"hour": "Hour",
|
"hour": "Hour",
|
||||||
"day_month": "Day of month",
|
"day_month": "Day of month",
|
||||||
"month": "Month",
|
"month": "Month",
|
||||||
"day_week": "Day of week"
|
"day_week": "Day of week",
|
||||||
|
"every_minute": "Every Minute",
|
||||||
|
"every_30_minute": "Every 30 Minute",
|
||||||
|
"every_hour": "Every Hour",
|
||||||
|
"every_2_hour": "Every 2 Hour",
|
||||||
|
"every_day_at_midnight": "Every day at midnight",
|
||||||
|
"every_week": "Every Week",
|
||||||
|
"every_15_days_at_midnight": "Every 15 days at midnight",
|
||||||
|
"on_the_first_day_of_every_month_at_midnight": "On the first day of every month at 00:00",
|
||||||
|
"every_6_month": "Every 6 Month",
|
||||||
|
"every_year_on_the_first_day_of_january_at_midnight": "Every year on the first day of january at 00:00",
|
||||||
|
"custom": "Custom"
|
||||||
},
|
},
|
||||||
"confirm_delete": "You will not be able to recover this Invoice | You will not be able to recover these Invoices",
|
"confirm_delete": "You will not be able to recover this Invoice | You will not be able to recover these Invoices",
|
||||||
"created_message": "Recurring Invoice created successfully",
|
"created_message": "Recurring Invoice created successfully",
|
||||||
@@ -557,7 +587,12 @@
|
|||||||
"marked_as_sent_message": "Recurring Invoice marked as sent successfully",
|
"marked_as_sent_message": "Recurring Invoice marked as sent successfully",
|
||||||
"user_email_does_not_exist": "User email does not exist",
|
"user_email_does_not_exist": "User email does not exist",
|
||||||
"something_went_wrong": "something went wrong",
|
"something_went_wrong": "something went wrong",
|
||||||
"invalid_due_amount_message": "Total Recurring Invoice amount cannot be less than total paid amount for this Recurring Invoice. Please update the invoice or delete the associated payments to continue."
|
"invalid_due_amount_message": "Total Recurring Invoice amount cannot be less than total paid amount for this Recurring Invoice. Please update the invoice or delete the associated payments to continue.",
|
||||||
|
"limit": {
|
||||||
|
"none": "None",
|
||||||
|
"date": "Date",
|
||||||
|
"count": "Count"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"payments": {
|
"payments": {
|
||||||
"title": "Payments",
|
"title": "Payments",
|
||||||
@@ -595,7 +630,8 @@
|
|||||||
"created_message": "Payment created successfully",
|
"created_message": "Payment created successfully",
|
||||||
"updated_message": "Payment updated successfully",
|
"updated_message": "Payment updated successfully",
|
||||||
"deleted_message": "Payment deleted successfully | Payments deleted successfully",
|
"deleted_message": "Payment deleted successfully | Payments deleted successfully",
|
||||||
"invalid_amount_message": "Payment amount is invalid"
|
"invalid_amount_message": "Payment amount is invalid",
|
||||||
|
"amount_due": "Due Amount"
|
||||||
},
|
},
|
||||||
"expenses": {
|
"expenses": {
|
||||||
"title": "Expenses",
|
"title": "Expenses",
|
||||||
@@ -700,7 +736,8 @@
|
|||||||
"installed": "Installed",
|
"installed": "Installed",
|
||||||
"no_modules_installed": "No Modules Installed Yet!",
|
"no_modules_installed": "No Modules Installed Yet!",
|
||||||
"disable_warning": "All the settings for this particular will be reverted.",
|
"disable_warning": "All the settings for this particular will be reverted.",
|
||||||
"what_you_get": "What you get"
|
"what_you_get": "What you get",
|
||||||
|
"sign_up_and_get_token": "Sign up & Get Token"
|
||||||
},
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"title": "Users",
|
"title": "Users",
|
||||||
@@ -752,7 +789,11 @@
|
|||||||
"date_range": "Select Date Range",
|
"date_range": "Select Date Range",
|
||||||
"to_date": "To Date",
|
"to_date": "To Date",
|
||||||
"from_date": "From Date",
|
"from_date": "From Date",
|
||||||
"report_type": "Report Type"
|
"report_type": "Report Type",
|
||||||
|
"sort": {
|
||||||
|
"by_customer": "By Customer",
|
||||||
|
"by_item": "By Item"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"taxes": {
|
"taxes": {
|
||||||
"taxes": "Taxes",
|
"taxes": "Taxes",
|
||||||
@@ -920,7 +961,14 @@
|
|||||||
"added_message": "Custom Field added successfully",
|
"added_message": "Custom Field added successfully",
|
||||||
"press_enter_to_add": "Press enter to add new option",
|
"press_enter_to_add": "Press enter to add new option",
|
||||||
"model_in_use": "Cannot update model for fields which are already in use.",
|
"model_in_use": "Cannot update model for fields which are already in use.",
|
||||||
"type_in_use": "Cannot update type for fields which are already in use."
|
"type_in_use": "Cannot update type for fields which are already in use.",
|
||||||
|
"model_type": {
|
||||||
|
"customer": "Customer",
|
||||||
|
"invoice": "Invoice",
|
||||||
|
"estimate": "Estimate",
|
||||||
|
"expense": "Expense",
|
||||||
|
"payment": "Payment"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"customization": {
|
"customization": {
|
||||||
"customization": "customization",
|
"customization": "customization",
|
||||||
@@ -1041,7 +1089,12 @@
|
|||||||
"note_updated": "Note Updated successfully",
|
"note_updated": "Note Updated successfully",
|
||||||
"note_confirm_delete": "You will not be able to recover this Note",
|
"note_confirm_delete": "You will not be able to recover this Note",
|
||||||
"already_in_use": "Note is already in use",
|
"already_in_use": "Note is already in use",
|
||||||
"deleted_message": "Note deleted successfully"
|
"deleted_message": "Note deleted successfully",
|
||||||
|
"types": {
|
||||||
|
"estimate": "Estimate",
|
||||||
|
"invoice": "Invoice",
|
||||||
|
"payment": "Payment"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"account_settings": {
|
"account_settings": {
|
||||||
@@ -1196,7 +1249,21 @@
|
|||||||
"on_hold": "On Hold",
|
"on_hold": "On Hold",
|
||||||
"update_status": "Update Status",
|
"update_status": "Update Status",
|
||||||
"completed": "Completed",
|
"completed": "Completed",
|
||||||
"company_currency_unchangeable": "Company currency cannot be changed"
|
"company_currency_unchangeable": "Company currency cannot be changed",
|
||||||
|
"fiscal_years": {
|
||||||
|
"january_december": "January - December",
|
||||||
|
"february_january": "February - January",
|
||||||
|
"march_february": "March - February",
|
||||||
|
"april_march": "April - March",
|
||||||
|
"may_april": "May - April",
|
||||||
|
"june_may": "June - May",
|
||||||
|
"july_june": "July - June",
|
||||||
|
"august_july": "August - July",
|
||||||
|
"september_august": "September - August",
|
||||||
|
"october_september": "October - September",
|
||||||
|
"november_october": "November - October",
|
||||||
|
"december_november": "December - November"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"update_app": {
|
"update_app": {
|
||||||
"title": "Update App",
|
"title": "Update App",
|
||||||
@@ -1355,6 +1422,10 @@
|
|||||||
"next": "Next",
|
"next": "Next",
|
||||||
"continue": "Continue",
|
"continue": "Continue",
|
||||||
"skip": "Skip",
|
"skip": "Skip",
|
||||||
|
"install_language": {
|
||||||
|
"title": "Choose your language",
|
||||||
|
"description": "Select language wizard to install InvoiceShelf"
|
||||||
|
},
|
||||||
"database": {
|
"database": {
|
||||||
"database": "Site URL & Database",
|
"database": "Site URL & Database",
|
||||||
"connection": "Database Connection",
|
"connection": "Database Connection",
|
||||||
@@ -1381,7 +1452,14 @@
|
|||||||
"verify_now": "Verify Now",
|
"verify_now": "Verify Now",
|
||||||
"success": "Domain Verify Successfully.",
|
"success": "Domain Verify Successfully.",
|
||||||
"failed": "Domain verification failed. Please enter valid domain name.",
|
"failed": "Domain verification failed. Please enter valid domain name.",
|
||||||
"verify_and_continue": "Verify And Continue"
|
"verify_and_continue": "Verify And Continue",
|
||||||
|
"notes": {
|
||||||
|
"notes" : "Notes:",
|
||||||
|
"not_contain" : "App domain should not contain",
|
||||||
|
"or" : "or",
|
||||||
|
"in_front": "in front of the domain.",
|
||||||
|
"if_you": "If you're accessing the website on a different port, please mention the port. For example:"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"mail": {
|
"mail": {
|
||||||
"host": "Mail Host",
|
"host": "Mail Host",
|
||||||
@@ -1532,5 +1610,14 @@
|
|||||||
"pdf_received_from": "Received from:",
|
"pdf_received_from": "Received from:",
|
||||||
"pdf_tax_label": "Tax",
|
"pdf_tax_label": "Tax",
|
||||||
"pdf_tax_id": "Tax-ID",
|
"pdf_tax_id": "Tax-ID",
|
||||||
"pdf_vat_id": "VAT-ID"
|
"pdf_vat_id": "VAT-ID",
|
||||||
|
"mail_thanks": "Thanks",
|
||||||
|
"mail_view_estimate":"View Estimate",
|
||||||
|
"mail_viewed_estimate": ":name viewed this Estimate.",
|
||||||
|
"mail_view_invoice": "View Invoice",
|
||||||
|
"mail_viewed_invoice": ":name viewed this Invoice.",
|
||||||
|
"mail_view_payment": "View Payment",
|
||||||
|
"notification_view_estimate": "[Notification] Estimate viewed",
|
||||||
|
"notification_view_invoice": "[Notification] Invoice viewed",
|
||||||
|
"You have received a new invoice from <b>{COMPANY_NAME}</b>.</br> Please download using the button below:": "You have received a new invoice from <b>{COMPANY_NAME}</b>.</br> Please download using the button below:"
|
||||||
}
|
}
|
||||||
|
|||||||
127
lang/fr.json
127
lang/fr.json
@@ -100,16 +100,35 @@
|
|||||||
"pay_invoice": "Payer facture",
|
"pay_invoice": "Payer facture",
|
||||||
"login_successfully": "Identifié avec succès!",
|
"login_successfully": "Identifié avec succès!",
|
||||||
"logged_out_successfully": "Déconnecté avec succès",
|
"logged_out_successfully": "Déconnecté avec succès",
|
||||||
"mark_as_default": "Marquer par défaut"
|
"mark_as_default": "Marquer par défaut",
|
||||||
|
"no_data_found": "Aucune donnée pour le moment",
|
||||||
|
"pagination": {
|
||||||
|
"previous": "Précédent",
|
||||||
|
"next": "Suivant",
|
||||||
|
"showing": "Affichage de",
|
||||||
|
"to": "à",
|
||||||
|
"of": "sur",
|
||||||
|
"results": "résultats"
|
||||||
|
},
|
||||||
|
"file_upload": {
|
||||||
|
"drag_a_file": "Déposez un fichier ici ou",
|
||||||
|
"browse": "parcourez",
|
||||||
|
"to_choose": "pour choisir un fichier"
|
||||||
|
},
|
||||||
|
"multiselect": {
|
||||||
|
"the_list_is_empty": "La liste est vide",
|
||||||
|
"no_results_found": "Aucun résultat"
|
||||||
|
},
|
||||||
|
"copy_to_clipboard": "Copier dans le presse-papier"
|
||||||
},
|
},
|
||||||
"dashboard": {
|
"dashboard": {
|
||||||
"select_year": "Sélectionnez l'année",
|
"select_year": "Sélectionnez l'année",
|
||||||
"cards": {
|
"cards": {
|
||||||
"due_amount": "Encours clients",
|
"due_amount": "Encours clients",
|
||||||
"customers": "Clients",
|
"customers": "Client | Clients",
|
||||||
"invoices": "Factures",
|
"invoices": "Facture | Factures",
|
||||||
"estimates": "Devis",
|
"estimates": "Devis | Devis",
|
||||||
"payments": "Paiements"
|
"payments": "Paiement | Paiements"
|
||||||
},
|
},
|
||||||
"chart_info": {
|
"chart_info": {
|
||||||
"total_sales": "Ventes",
|
"total_sales": "Ventes",
|
||||||
@@ -548,7 +567,18 @@
|
|||||||
"hour": "Heure",
|
"hour": "Heure",
|
||||||
"day_month": "Jour du mois",
|
"day_month": "Jour du mois",
|
||||||
"month": "Mois",
|
"month": "Mois",
|
||||||
"day_week": "Jour de la semaine"
|
"day_week": "Jour de la semaine",
|
||||||
|
"every_minute": "Toutes les minutes",
|
||||||
|
"every_30_minute": "Toutes les 30 minutes",
|
||||||
|
"every_hour": "Toutes les heures",
|
||||||
|
"every_2_hour": "Toutes les 2 heures",
|
||||||
|
"every_day_at_midnight": "Tous les jours à minuit",
|
||||||
|
"every_week": "Toutes les semaines",
|
||||||
|
"every_15_days_at_midnight": "Tous les 15 jours à minuit",
|
||||||
|
"on_the_first_day_of_every_month_at_midnight": "Au premier jour du mois à minuit",
|
||||||
|
"every_6_month": "Tous les 6 mois",
|
||||||
|
"every_year_on_the_first_day_of_january_at_midnight": "Tous les ans, au premier janvier à minuit",
|
||||||
|
"custom": "Personnalisée"
|
||||||
},
|
},
|
||||||
"confirm_delete": "Vous ne pourrez pas récupérer cette facture | Vous ne pourrez pas récupérer ces factures",
|
"confirm_delete": "Vous ne pourrez pas récupérer cette facture | Vous ne pourrez pas récupérer ces factures",
|
||||||
"created_message": "Facture récurrente créée",
|
"created_message": "Facture récurrente créée",
|
||||||
@@ -557,7 +587,12 @@
|
|||||||
"marked_as_sent_message": "Facture récurrente envoyée",
|
"marked_as_sent_message": "Facture récurrente envoyée",
|
||||||
"user_email_does_not_exist": "L'email de l'utilisateur n'existe pas",
|
"user_email_does_not_exist": "L'email de l'utilisateur n'existe pas",
|
||||||
"something_went_wrong": "une erreur s’est produite",
|
"something_went_wrong": "une erreur s’est produite",
|
||||||
"invalid_due_amount_message": "Le montant total de la facture récurrente ne peut pas être inférieur au montant total payé pour cette facture récurrente. Veuillez mettre à jour la facture ou supprimer les paiements associés pour continuer."
|
"invalid_due_amount_message": "Le montant total de la facture récurrente ne peut pas être inférieur au montant total payé pour cette facture récurrente. Veuillez mettre à jour la facture ou supprimer les paiements associés pour continuer.",
|
||||||
|
"limit": {
|
||||||
|
"none": "Aucun",
|
||||||
|
"date": "Date",
|
||||||
|
"count": "Nombre"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"payments": {
|
"payments": {
|
||||||
"title": "Paiements",
|
"title": "Paiements",
|
||||||
@@ -595,7 +630,8 @@
|
|||||||
"created_message": "Paiement créé",
|
"created_message": "Paiement créé",
|
||||||
"updated_message": "Paiement mis à jour",
|
"updated_message": "Paiement mis à jour",
|
||||||
"deleted_message": "Paiement supprimé | Paiements supprimés",
|
"deleted_message": "Paiement supprimé | Paiements supprimés",
|
||||||
"invalid_amount_message": "Le montant du paiement est invalide"
|
"invalid_amount_message": "Le montant du paiement est invalide",
|
||||||
|
"amount_due": "Montant dû"
|
||||||
},
|
},
|
||||||
"expenses": {
|
"expenses": {
|
||||||
"title": "Dépenses",
|
"title": "Dépenses",
|
||||||
@@ -700,7 +736,8 @@
|
|||||||
"installed": "Installé",
|
"installed": "Installé",
|
||||||
"no_modules_installed": "Aucun module installé !",
|
"no_modules_installed": "Aucun module installé !",
|
||||||
"disable_warning": "Tous les paramètres de ce module seront réinitialisés.",
|
"disable_warning": "Tous les paramètres de ce module seront réinitialisés.",
|
||||||
"what_you_get": "Ce que vous obtenez"
|
"what_you_get": "Ce que vous obtenez",
|
||||||
|
"sign_up_and_get_token": "Inscrivez-vous et obtenez votre Jeton"
|
||||||
},
|
},
|
||||||
"users": {
|
"users": {
|
||||||
"title": "Utilisateurs",
|
"title": "Utilisateurs",
|
||||||
@@ -752,7 +789,11 @@
|
|||||||
"date_range": "Période",
|
"date_range": "Période",
|
||||||
"to_date": "Au",
|
"to_date": "Au",
|
||||||
"from_date": "Du",
|
"from_date": "Du",
|
||||||
"report_type": "Trier"
|
"report_type": "Trier",
|
||||||
|
"sort": {
|
||||||
|
"by_customer": "Par Client",
|
||||||
|
"by_item": "Par Article"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"taxes": {
|
"taxes": {
|
||||||
"taxes": "Taxes",
|
"taxes": "Taxes",
|
||||||
@@ -863,6 +904,8 @@
|
|||||||
"company_info": {
|
"company_info": {
|
||||||
"company_info": "Coordonnées de la société",
|
"company_info": "Coordonnées de la société",
|
||||||
"company_name": "Nom",
|
"company_name": "Nom",
|
||||||
|
"tax_id": "Numéro d'identification fiscale",
|
||||||
|
"vat_id": "Numéro d'identification TVA",
|
||||||
"company_logo": "Logo",
|
"company_logo": "Logo",
|
||||||
"section_description": "Saisissez ici les coordonnées de votre entreprise qui s'afficheront sur tous vos documents.",
|
"section_description": "Saisissez ici les coordonnées de votre entreprise qui s'afficheront sur tous vos documents.",
|
||||||
"phone": "Téléphone",
|
"phone": "Téléphone",
|
||||||
@@ -918,7 +961,14 @@
|
|||||||
"added_message": "Champ personnalisé ajouté",
|
"added_message": "Champ personnalisé ajouté",
|
||||||
"press_enter_to_add": "Appuyez sur Entrée pour ajouter une nouvelle option",
|
"press_enter_to_add": "Appuyez sur Entrée pour ajouter une nouvelle option",
|
||||||
"model_in_use": "Impossible de mettre à jour le modèle pour les champs qui sont déjà utilisés.",
|
"model_in_use": "Impossible de mettre à jour le modèle pour les champs qui sont déjà utilisés.",
|
||||||
"type_in_use": "Impossible de mettre à jour le type des champs déjà utilisés."
|
"type_in_use": "Impossible de mettre à jour le type des champs déjà utilisés.",
|
||||||
|
"model_type": {
|
||||||
|
"customer": "Client",
|
||||||
|
"invoice": "Facture",
|
||||||
|
"estimate": "Devis",
|
||||||
|
"expense": "Dépense",
|
||||||
|
"payment": "Paiement"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"customization": {
|
"customization": {
|
||||||
"customization": "Personnalisation",
|
"customization": "Personnalisation",
|
||||||
@@ -1039,7 +1089,12 @@
|
|||||||
"note_updated": "Note de bas de page mise à jour",
|
"note_updated": "Note de bas de page mise à jour",
|
||||||
"note_confirm_delete": "Vous ne pourrez pas récupérer cette note de bas de page",
|
"note_confirm_delete": "Vous ne pourrez pas récupérer cette note de bas de page",
|
||||||
"already_in_use": "La note de bas de page est déjà utilisée",
|
"already_in_use": "La note de bas de page est déjà utilisée",
|
||||||
"deleted_message": "Note de bas de page supprimée"
|
"deleted_message": "Note de bas de page supprimée",
|
||||||
|
"types": {
|
||||||
|
"estimate": "Devis",
|
||||||
|
"invoice": "Facture",
|
||||||
|
"payment": "Paiement"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"account_settings": {
|
"account_settings": {
|
||||||
@@ -1194,7 +1249,21 @@
|
|||||||
"on_hold": "En attente",
|
"on_hold": "En attente",
|
||||||
"update_status": "Mettre à jour le statut",
|
"update_status": "Mettre à jour le statut",
|
||||||
"completed": "Terminé",
|
"completed": "Terminé",
|
||||||
"company_currency_unchangeable": "La devise de la société ne peut pas être modifiée"
|
"company_currency_unchangeable": "La devise de la société ne peut pas être modifiée",
|
||||||
|
"fiscal_years": {
|
||||||
|
"january_december": "Janvier - Décembre",
|
||||||
|
"february_january": "Février - Janvier",
|
||||||
|
"march_february": "Mars - Février",
|
||||||
|
"april_march": "Avril - Mars",
|
||||||
|
"may_april": "Mai - Avril",
|
||||||
|
"june_may": "Juin - Mai",
|
||||||
|
"july_june": "Juillet - Juin",
|
||||||
|
"august_july": "Aout - Juillet",
|
||||||
|
"september_august": "Septembre - Aout",
|
||||||
|
"october_september": "Octobre - Septembre",
|
||||||
|
"november_october": "Novembre - Octobre",
|
||||||
|
"december_november": "Décembre - Novembre"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"update_app": {
|
"update_app": {
|
||||||
"title": "Mise à jour",
|
"title": "Mise à jour",
|
||||||
@@ -1267,6 +1336,12 @@
|
|||||||
"aws_region": "Région AWS",
|
"aws_region": "Région AWS",
|
||||||
"aws_bucket": "Bucket",
|
"aws_bucket": "Bucket",
|
||||||
"aws_root": "Répertoire",
|
"aws_root": "Répertoire",
|
||||||
|
"s3_endpoint": "S3 Endpoint",
|
||||||
|
"s3_key": "S3 Key",
|
||||||
|
"s3_secret": "S3 Secret",
|
||||||
|
"s3_region": "S3 Region",
|
||||||
|
"s3_bucket": "S3 Bucket",
|
||||||
|
"s3_root": "S3 Root",
|
||||||
"do_spaces_type": "Type",
|
"do_spaces_type": "Type",
|
||||||
"do_spaces_key": "Key",
|
"do_spaces_key": "Key",
|
||||||
"do_spaces_secret": "Secret",
|
"do_spaces_secret": "Secret",
|
||||||
@@ -1347,6 +1422,10 @@
|
|||||||
"next": "Suivant",
|
"next": "Suivant",
|
||||||
"continue": "Poursuivre",
|
"continue": "Poursuivre",
|
||||||
"skip": "Ignorer",
|
"skip": "Ignorer",
|
||||||
|
"install_language": {
|
||||||
|
"title": "Choix de la langue",
|
||||||
|
"description": "Sélectionner la langue de l'assistant pour installer InvoiceShelf"
|
||||||
|
},
|
||||||
"database": {
|
"database": {
|
||||||
"database": "URL du site et base de données",
|
"database": "URL du site et base de données",
|
||||||
"connection": "Connexion à la base de données",
|
"connection": "Connexion à la base de données",
|
||||||
@@ -1373,7 +1452,14 @@
|
|||||||
"verify_now": "Vérifier maintenant",
|
"verify_now": "Vérifier maintenant",
|
||||||
"success": "Vérification du domaine réussie.",
|
"success": "Vérification du domaine réussie.",
|
||||||
"failed": "La vérification du domaine a échoué. Veuillez entrer un nom de domaine valide.",
|
"failed": "La vérification du domaine a échoué. Veuillez entrer un nom de domaine valide.",
|
||||||
"verify_and_continue": "Vérifier et continuer"
|
"verify_and_continue": "Vérifier et continuer",
|
||||||
|
"notes": {
|
||||||
|
"notes" : "Notes :",
|
||||||
|
"not_contain" : "Le domaine de l'application ne doit pas contenir",
|
||||||
|
"or" : "ou",
|
||||||
|
"in_front": "devant le domaine.",
|
||||||
|
"if_you": "Si vous accédez au site Web sur un autre port, veuillez mentionner le port. Par exemple :"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"mail": {
|
"mail": {
|
||||||
"host": "Serveur email",
|
"host": "Serveur email",
|
||||||
@@ -1522,5 +1608,16 @@
|
|||||||
"pdf_bill_to": "Facturer à",
|
"pdf_bill_to": "Facturer à",
|
||||||
"pdf_ship_to": "Expédier à",
|
"pdf_ship_to": "Expédier à",
|
||||||
"pdf_received_from": "Reçu de :",
|
"pdf_received_from": "Reçu de :",
|
||||||
"pdf_tax_label": "Taxe"
|
"pdf_tax_label": "Taxe",
|
||||||
|
"pdf_tax_id": "Tax-ID",
|
||||||
|
"pdf_vat_id": "VAT-ID",
|
||||||
|
"mail_thanks": "Merci",
|
||||||
|
"mail_view_estimate":"Voir le Devis",
|
||||||
|
"mail_viewed_estimate": ":name a consulté ce Devis.",
|
||||||
|
"mail_view_invoice": "Voir la Facture",
|
||||||
|
"mail_viewed_invoice": ":name a consulté cette Facture.",
|
||||||
|
"mail_view_payment": "Voir le Paiement",
|
||||||
|
"notification_view_estimate": "[Notification] Un Devis a été consulté",
|
||||||
|
"notification_view_invoice": "[Notification] Une Facture a été consultée",
|
||||||
|
"You have received a new invoice from <b>{COMPANY_NAME}</b>.</br> Please download using the button below:": "Vous avez reçu une nouvelle facture de <b>{COMPANY_NAME}</b>.</br> Vous pouvez la télécharger en cliquant sur le bouton :"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
{{ token }}
|
{{ token }}
|
||||||
</span>
|
</span>
|
||||||
<svg
|
<svg
|
||||||
v-tooltip="{ content: 'Copy to Clipboard' }"
|
v-tooltip="{ content: $t('general.copy_to_clipboard') }"
|
||||||
class="
|
class="
|
||||||
absolute
|
absolute
|
||||||
right-0
|
right-0
|
||||||
|
|||||||
@@ -178,7 +178,7 @@
|
|||||||
v$.confirm_password.$errors[0].$message
|
v$.confirm_password.$errors[0].$message
|
||||||
"
|
"
|
||||||
:content-loading="isFetchingInitialData"
|
:content-loading="isFetchingInitialData"
|
||||||
label="Confirm Password"
|
:label="$t('customers.confirm_password')"
|
||||||
>
|
>
|
||||||
<BaseInput
|
<BaseInput
|
||||||
v-model.trim="customerStore.currentCustomer.confirm_password"
|
v-model.trim="customerStore.currentCustomer.confirm_password"
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
<BaseMultiselect
|
<BaseMultiselect
|
||||||
v-model="noteStore.currentNote.type"
|
v-model="noteStore.currentNote.type"
|
||||||
:options="types"
|
:options="types"
|
||||||
value-prop="type"
|
value-prop="value"
|
||||||
class="mt-2"
|
class="mt-2"
|
||||||
/>
|
/>
|
||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
@@ -122,7 +122,11 @@ const route = useRoute()
|
|||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
let isSaving = ref(false)
|
let isSaving = ref(false)
|
||||||
const types = reactive(['Invoice', 'Estimate', 'Payment'])
|
const types = reactive([
|
||||||
|
{label: t('settings.customization.notes.types.invoice'), value: 'Invoice'},
|
||||||
|
{label: t('settings.customization.notes.types.estimate'), value: 'Estimate'},
|
||||||
|
{label: t('settings.customization.notes.types.payment'), value: 'Payment'}
|
||||||
|
])
|
||||||
let fields = ref(['customer', 'customerCustom'])
|
let fields = ref(['customer', 'customerCustom'])
|
||||||
|
|
||||||
const modalActive = computed(() => {
|
const modalActive = computed(() => {
|
||||||
@@ -164,7 +168,7 @@ watch(
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (route.name === 'estimates.create') {
|
if (route.name === 'estimates.create') {
|
||||||
noteStore.currentNote.type = 'Estimate'
|
noteStore.currentNote.type = 'Estimate'
|
||||||
} else if (route.name === 'invoices.create') {
|
} else if (route.name === 'invoices.create' || route.name === 'recurring-invoices.create') {
|
||||||
noteStore.currentNote.type = 'Invoice'
|
noteStore.currentNote.type = 'Invoice'
|
||||||
} else {
|
} else {
|
||||||
noteStore.currentNote.type = 'Payment'
|
noteStore.currentNote.type = 'Payment'
|
||||||
|
|||||||
@@ -96,7 +96,7 @@
|
|||||||
@click="cancelPreview"
|
@click="cancelPreview"
|
||||||
>
|
>
|
||||||
<BaseIcon name="PencilIcon" class="h-5 mr-2" />
|
<BaseIcon name="PencilIcon" class="h-5 mr-2" />
|
||||||
Edit
|
{{ $t('general.edit') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
<iframe
|
<iframe
|
||||||
:src="templateUrl"
|
:src="templateUrl"
|
||||||
@@ -166,7 +166,7 @@ let estimateMailForm = reactive({
|
|||||||
id: null,
|
id: null,
|
||||||
from: null,
|
from: null,
|
||||||
to: null,
|
to: null,
|
||||||
subject: 'New Estimate',
|
subject: t('estimates.new_estimate'),
|
||||||
body: null,
|
body: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@
|
|||||||
@click="cancelPreview"
|
@click="cancelPreview"
|
||||||
>
|
>
|
||||||
<BaseIcon name="PencilIcon" class="h-5 mr-2" />
|
<BaseIcon name="PencilIcon" class="h-5 mr-2" />
|
||||||
Edit
|
{{ $t('general.edit') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
||||||
<iframe
|
<iframe
|
||||||
@@ -181,7 +181,7 @@ const invoiceMailForm = reactive({
|
|||||||
id: null,
|
id: null,
|
||||||
from: null,
|
from: null,
|
||||||
to: null,
|
to: null,
|
||||||
subject: 'New Invoice',
|
subject: t('invoices.new_invoice'),
|
||||||
body: null,
|
body: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@
|
|||||||
@click="cancelPreview"
|
@click="cancelPreview"
|
||||||
>
|
>
|
||||||
<BaseIcon name="PencilIcon" class="h-5 mr-2" />
|
<BaseIcon name="PencilIcon" class="h-5 mr-2" />
|
||||||
Edit
|
{{ $t('general.edit') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
|
|
||||||
<iframe
|
<iframe
|
||||||
@@ -181,7 +181,7 @@ const paymentMailForm = reactive({
|
|||||||
id: null,
|
id: null,
|
||||||
from: null,
|
from: null,
|
||||||
to: null,
|
to: null,
|
||||||
subject: 'New Payment',
|
subject: t('payments.new_payment'),
|
||||||
body: null,
|
body: null,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
<BaseMultiselect
|
<BaseMultiselect
|
||||||
v-model="customFieldStore.currentCustomField.model_type"
|
v-model="customFieldStore.currentCustomField.model_type"
|
||||||
:options="modelTypes"
|
:options="modelTypes"
|
||||||
|
value-prop="value"
|
||||||
:can-deselect="false"
|
:can-deselect="false"
|
||||||
:invalid="v$.currentCustomField.model_type.$error"
|
:invalid="v$.currentCustomField.model_type.$error"
|
||||||
:searchable="true"
|
:searchable="true"
|
||||||
@@ -229,11 +230,11 @@ const { t } = useI18n()
|
|||||||
let isSaving = ref(false)
|
let isSaving = ref(false)
|
||||||
|
|
||||||
const modelTypes = reactive([
|
const modelTypes = reactive([
|
||||||
'Customer',
|
{label: t('settings.custom_fields.model_type.customer'), value: 'Customer'},
|
||||||
'Invoice',
|
{label: t('settings.custom_fields.model_type.invoice'), value: 'Invoice'},
|
||||||
'Estimate',
|
{label: t('settings.custom_fields.model_type.estimate'), value: 'Estimate'},
|
||||||
'Expense',
|
{label: t('settings.custom_fields.model_type.expense'), value: 'Expense'},
|
||||||
'Payment',
|
{label: t('settings.custom_fields.model_type.payment'), value: 'Payment'}
|
||||||
])
|
])
|
||||||
|
|
||||||
const dataTypes = reactive([
|
const dataTypes = reactive([
|
||||||
@@ -286,9 +287,6 @@ const isRequiredField = computed({
|
|||||||
const rules = computed(() => {
|
const rules = computed(() => {
|
||||||
return {
|
return {
|
||||||
currentCustomField: {
|
currentCustomField: {
|
||||||
type: {
|
|
||||||
required: helpers.withMessage(t('validation.required'), required),
|
|
||||||
},
|
|
||||||
name: {
|
name: {
|
||||||
required: helpers.withMessage(t('validation.required'), required),
|
required: helpers.withMessage(t('validation.required'), required),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -20,10 +20,25 @@ export const useInstallationStore = (useWindow = false) => {
|
|||||||
database_username: null,
|
database_username: null,
|
||||||
database_password: null,
|
database_password: null,
|
||||||
app_url: window.location.origin,
|
app_url: window.location.origin,
|
||||||
|
app_locale: null
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
|
fetchInstallationLanguages() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
axios
|
||||||
|
.get(`/api/v1/installation/languages`)
|
||||||
|
.then((response) => {
|
||||||
|
resolve(response)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
handleError(err)
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
fetchInstallationRequirements() {
|
fetchInstallationRequirements() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
axios
|
axios
|
||||||
@@ -66,6 +81,20 @@ export const useInstallationStore = (useWindow = false) => {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
addInstallationLanguage(data) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
axios
|
||||||
|
.post(`/api/v1/installation/wizard-language`, data)
|
||||||
|
.then((response) => {
|
||||||
|
resolve(response)
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
handleError(err)
|
||||||
|
reject(err)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
fetchInstallationPermissions() {
|
fetchInstallationPermissions() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
axios
|
axios
|
||||||
|
|||||||
@@ -36,17 +36,17 @@ export const useRecurringInvoiceStore = (useWindow = false) => {
|
|||||||
},
|
},
|
||||||
|
|
||||||
frequencies: [
|
frequencies: [
|
||||||
{ label: 'Every Minute', value: '* * * * *' },
|
{ label: global.t('recurring_invoices.frequency.every_minute'), value: '* * * * *' },
|
||||||
{ label: 'Every 30 Minute', value: '*/30 * * * *' },
|
{ label: global.t('recurring_invoices.frequency.every_30_minute'), value: '*/30 * * * *' },
|
||||||
{ label: 'Every Hour', value: '0 * * * *' },
|
{ label: global.t('recurring_invoices.frequency.every_hour'), value: '0 * * * *' },
|
||||||
{ label: 'Every 2 Hour', value: '0 */2 * * *' },
|
{ label: global.t('recurring_invoices.frequency.every_2_hour'), value: '0 */2 * * *' },
|
||||||
{ label: 'Every day at midnight ', value: '0 0 * * *' },
|
{ label: global.t('recurring_invoices.frequency.every_day_at_midnight'), value: '0 0 * * *' },
|
||||||
{ label: 'Every Week', value: '0 0 * * 0' },
|
{ label: global.t('recurring_invoices.frequency.every_week'), value: '0 0 * * 0' },
|
||||||
{ label: 'Every 15 days at midnight', value: '0 5 */15 * *' },
|
{ label: global.t('recurring_invoices.frequency.every_15_days_at_midnight'), value: '0 5 */15 * *' },
|
||||||
{ label: 'On the first day of every month at 00:00', value: '0 0 1 * *' },
|
{ label: global.t('recurring_invoices.frequency.on_the_first_day_of_every_month_at_midnight'), value: '0 0 1 * *' },
|
||||||
{ label: 'Every 6 Month', value: '0 0 1 */6 *' },
|
{ label: global.t('recurring_invoices.frequency.every_6_month'), value: '0 0 1 */6 *' },
|
||||||
{ label: 'Every year on the first day of january at 00:00', value: '0 0 1 1 *' },
|
{ label: global.t('recurring_invoices.frequency.every_year_on_the_first_day_of_january_at_midnight'), value: '0 0 1 1 *' },
|
||||||
{ label: 'Custom', value: 'CUSTOM' },
|
{ label: global.t('recurring_invoices.frequency.custom'), value: 'CUSTOM' },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import Guid from 'guid'
|
import Guid from 'guid'
|
||||||
import recurringInvoiceItemStub from './recurring-invoice-item'
|
import recurringInvoiceItemStub from './recurring-invoice-item'
|
||||||
import taxStub from './tax'
|
import taxStub from './tax'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
|
const { t } = useI18n()
|
||||||
return {
|
return {
|
||||||
currency: null,
|
currency: null,
|
||||||
customer: null,
|
customer: null,
|
||||||
@@ -42,7 +44,7 @@ export default function () {
|
|||||||
fields: [],
|
fields: [],
|
||||||
invoices: [],
|
invoices: [],
|
||||||
selectedNote: null,
|
selectedNote: null,
|
||||||
selectedFrequency: { label: 'Every Week', value: '0 0 * * 0' },
|
selectedFrequency: { label: t('recurring_invoices.frequency.every_week'), value: '0 0 * * 0' },
|
||||||
selectedInvoice: null,
|
selectedInvoice: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,7 +231,7 @@
|
|||||||
v$.currentCustomer.confirm_password.$errors[0].$message
|
v$.currentCustomer.confirm_password.$errors[0].$message
|
||||||
"
|
"
|
||||||
:content-loading="isFetchingInitialData"
|
:content-loading="isFetchingInitialData"
|
||||||
label="Confirm Password"
|
:label="$t('customers.confirm_password')"
|
||||||
>
|
>
|
||||||
<BaseInput
|
<BaseInput
|
||||||
v-model.trim="customerStore.currentCustomer.confirm_password"
|
v-model.trim="customerStore.currentCustomer.confirm_password"
|
||||||
|
|||||||
@@ -128,17 +128,19 @@ import { useCustomerStore } from '@/scripts/admin/stores/customer'
|
|||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { useCompanyStore } from '@/scripts/admin/stores/company'
|
import { useCompanyStore } from '@/scripts/admin/stores/company'
|
||||||
import ChartPlaceholder from './CustomerChartPlaceholder.vue'
|
import ChartPlaceholder from './CustomerChartPlaceholder.vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const companyStore = useCompanyStore()
|
const companyStore = useCompanyStore()
|
||||||
const customerStore = useCustomerStore()
|
const customerStore = useCustomerStore()
|
||||||
const utils = inject('utils')
|
const utils = inject('utils')
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
|
||||||
let isLoading = ref(false)
|
let isLoading = ref(false)
|
||||||
let chartData = reactive({})
|
let chartData = reactive({})
|
||||||
let data = reactive({})
|
let data = reactive({})
|
||||||
let years = reactive(['This year', 'Previous year'])
|
let years = reactive([{label: t('dateRange.this_year'), value: 'This year'}, {label: t('dateRange.previous_year'), value: 'Previous year'}])
|
||||||
let selectedYear = ref('This year')
|
let selectedYear = ref('This year')
|
||||||
|
|
||||||
const getChartExpenses = computed(() => {
|
const getChartExpenses = computed(() => {
|
||||||
|
|||||||
@@ -7,17 +7,20 @@
|
|||||||
|
|
||||||
<BaseDescriptionList>
|
<BaseDescriptionList>
|
||||||
<BaseDescriptionListItem
|
<BaseDescriptionListItem
|
||||||
|
v-if="selectedViewCustomer.name"
|
||||||
:content-loading="contentLoading"
|
:content-loading="contentLoading"
|
||||||
:label="$t('customers.display_name')"
|
:label="$t('customers.display_name')"
|
||||||
:value="selectedViewCustomer?.name"
|
:value="selectedViewCustomer?.name"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<BaseDescriptionListItem
|
<BaseDescriptionListItem
|
||||||
|
v-if="selectedViewCustomer.contact_name"
|
||||||
:content-loading="contentLoading"
|
:content-loading="contentLoading"
|
||||||
:label="$t('customers.primary_contact_name')"
|
:label="$t('customers.primary_contact_name')"
|
||||||
:value="selectedViewCustomer?.contact_name"
|
:value="selectedViewCustomer?.contact_name"
|
||||||
/>
|
/>
|
||||||
<BaseDescriptionListItem
|
<BaseDescriptionListItem
|
||||||
|
v-if="selectedViewCustomer.email"
|
||||||
:content-loading="contentLoading"
|
:content-loading="contentLoading"
|
||||||
:label="$t('customers.email')"
|
:label="$t('customers.email')"
|
||||||
:value="selectedViewCustomer?.email"
|
:value="selectedViewCustomer?.email"
|
||||||
@@ -36,11 +39,13 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<BaseDescriptionListItem
|
<BaseDescriptionListItem
|
||||||
|
v-if="selectedViewCustomer.phone"
|
||||||
:content-loading="contentLoading"
|
:content-loading="contentLoading"
|
||||||
:label="$t('customers.phone_number')"
|
:label="$t('customers.phone_number')"
|
||||||
:value="selectedViewCustomer?.phone"
|
:value="selectedViewCustomer?.phone"
|
||||||
/>
|
/>
|
||||||
<BaseDescriptionListItem
|
<BaseDescriptionListItem
|
||||||
|
v-if="selectedViewCustomer.website"
|
||||||
:content-loading="contentLoading"
|
:content-loading="contentLoading"
|
||||||
:label="$t('customers.website')"
|
:label="$t('customers.website')"
|
||||||
:value="selectedViewCustomer?.website"
|
:value="selectedViewCustomer?.website"
|
||||||
@@ -89,8 +94,8 @@
|
|||||||
v-if="field.type === 'Switch'"
|
v-if="field.type === 'Switch'"
|
||||||
class="text-sm font-bold leading-5 text-black non-italic"
|
class="text-sm font-bold leading-5 text-black non-italic"
|
||||||
>
|
>
|
||||||
<span v-if="field.default_answer === 1"> Yes </span>
|
<span v-if="field.default_answer === 1"> {{ $t('general.yes') }} </span>
|
||||||
<span v-else> No </span>
|
<span v-else> {{ $t('general.no') }} </span>
|
||||||
</p>
|
</p>
|
||||||
<p v-else class="text-sm font-bold leading-5 text-black non-italic">
|
<p v-else class="text-sm font-bold leading-5 text-black non-italic">
|
||||||
{{ field.default_answer }}
|
{{ field.default_answer }}
|
||||||
|
|||||||
@@ -156,13 +156,16 @@ import LineChart from '@/scripts/admin/components/charts/LineChart.vue'
|
|||||||
import ChartPlaceholder from './DashboardChartPlaceholder.vue'
|
import ChartPlaceholder from './DashboardChartPlaceholder.vue'
|
||||||
import abilities from '@/scripts/admin/stub/abilities'
|
import abilities from '@/scripts/admin/stub/abilities'
|
||||||
import { useUserStore } from '@/scripts/admin/stores/user'
|
import { useUserStore } from '@/scripts/admin/stores/user'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
const dashboardStore = useDashboardStore()
|
const dashboardStore = useDashboardStore()
|
||||||
const companyStore = useCompanyStore()
|
const companyStore = useCompanyStore()
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
const utils = inject('utils')
|
const utils = inject('utils')
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const years = ref(['This year', 'Previous year'])
|
const years = ref( [{label: t('dateRange.this_year'), value: 'This year'}, {label: t( 'dateRange.previous_year'), value:
|
||||||
|
'Previous year'}])
|
||||||
const selectedYear = ref('This year')
|
const selectedYear = ref('This year')
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
:icon-component="CustomerIcon"
|
:icon-component="CustomerIcon"
|
||||||
:loading="!dashboardStore.isDashboardDataLoaded"
|
:loading="!dashboardStore.isDashboardDataLoaded"
|
||||||
route="/admin/customers"
|
route="/admin/customers"
|
||||||
:label="$t('dashboard.cards.customers')"
|
:label="(dashboardStore.stats.totalCustomerCount <= 1 ? $t('dashboard.cards.customers', 1) : $t('dashboard.cards.customers', 2))"
|
||||||
>
|
>
|
||||||
{{ dashboardStore.stats.totalCustomerCount }}
|
{{ dashboardStore.stats.totalCustomerCount }}
|
||||||
</DashboardStatsItem>
|
</DashboardStatsItem>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
:icon-component="InvoiceIcon"
|
:icon-component="InvoiceIcon"
|
||||||
:loading="!dashboardStore.isDashboardDataLoaded"
|
:loading="!dashboardStore.isDashboardDataLoaded"
|
||||||
route="/admin/invoices"
|
route="/admin/invoices"
|
||||||
:label="$t('dashboard.cards.invoices')"
|
:label="(dashboardStore.stats.totalInvoiceCount <= 1 ? $t('dashboard.cards.invoices', 1) : $t('dashboard.cards.invoices', 2))"
|
||||||
>
|
>
|
||||||
{{ dashboardStore.stats.totalInvoiceCount }}
|
{{ dashboardStore.stats.totalInvoiceCount }}
|
||||||
</DashboardStatsItem>
|
</DashboardStatsItem>
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
:icon-component="EstimateIcon"
|
:icon-component="EstimateIcon"
|
||||||
:loading="!dashboardStore.isDashboardDataLoaded"
|
:loading="!dashboardStore.isDashboardDataLoaded"
|
||||||
route="/admin/estimates"
|
route="/admin/estimates"
|
||||||
:label="$t('dashboard.cards.estimates')"
|
:label="(dashboardStore.stats.totalEstimateCount <= 1 ? $t( 'dashboard.cards.estimates', 1) : $t('dashboard.cards.estimates', 2))"
|
||||||
>
|
>
|
||||||
{{ dashboardStore.stats.totalEstimateCount }}
|
{{ dashboardStore.stats.totalEstimateCount }}
|
||||||
</DashboardStatsItem>
|
</DashboardStatsItem>
|
||||||
|
|||||||
@@ -95,7 +95,7 @@
|
|||||||
v-if="hasAtleastOneEstimateAbility()"
|
v-if="hasAtleastOneEstimateAbility()"
|
||||||
#cell-actions="{ row }"
|
#cell-actions="{ row }"
|
||||||
>
|
>
|
||||||
<EstimateDropdown :row="row" :table="estimateTableComponent" />
|
<EstimateDropdown :row="row.data" :table="estimateTableComponent" />
|
||||||
</template>
|
</template>
|
||||||
</BaseTable>
|
</BaseTable>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -216,7 +216,7 @@
|
|||||||
|
|
||||||
<template #cell-status="{ row }">
|
<template #cell-status="{ row }">
|
||||||
<BaseEstimateStatusBadge :status="row.data.status" class="px-3 py-1">
|
<BaseEstimateStatusBadge :status="row.data.status" class="px-3 py-1">
|
||||||
{{ row.data.status }}
|
<BaseEstimateStatusLabel :status="row.data.status"/>
|
||||||
</BaseEstimateStatusBadge>
|
</BaseEstimateStatusBadge>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -249,6 +249,7 @@ import abilities from '@/scripts/admin/stub/abilities'
|
|||||||
import ObservatoryIcon from '@/scripts/components/icons/empty/ObservatoryIcon.vue'
|
import ObservatoryIcon from '@/scripts/components/icons/empty/ObservatoryIcon.vue'
|
||||||
import EstimateDropDown from '@/scripts/admin/components/dropdowns/EstimateIndexDropdown.vue'
|
import EstimateDropDown from '@/scripts/admin/components/dropdowns/EstimateIndexDropdown.vue'
|
||||||
import SendEstimateModal from '@/scripts/admin/components/modal-components/SendEstimateModal.vue'
|
import SendEstimateModal from '@/scripts/admin/components/modal-components/SendEstimateModal.vue'
|
||||||
|
import BaseEstimateStatusLabel from "@/scripts/components/base/BaseEstimateStatusLabel.vue";
|
||||||
|
|
||||||
const estimateStore = useEstimateStore()
|
const estimateStore = useEstimateStore()
|
||||||
const dialogStore = useDialogStore()
|
const dialogStore = useDialogStore()
|
||||||
@@ -258,12 +259,12 @@ const tableComponent = ref(null)
|
|||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const showFilters = ref(false)
|
const showFilters = ref(false)
|
||||||
const status = ref([
|
const status = ref([
|
||||||
'DRAFT',
|
{label: t('estimates.draft'), value: 'DRAFT'},
|
||||||
'SENT',
|
{label: t('estimates.sent'), value: 'SENT'},
|
||||||
'VIEWED',
|
{label: t('estimates.viewed'), value: 'VIEWED'},
|
||||||
'EXPIRED',
|
{label: t('estimates.expired'), value: 'EXPIRED'},
|
||||||
'ACCEPTED',
|
{label: t('estimates.accepted'), value: 'ACCEPTED'},
|
||||||
'REJECTED',
|
{label: t('estimates.rejected'), value: 'REJECTED'},
|
||||||
])
|
])
|
||||||
|
|
||||||
const isRequestOngoing = ref(true)
|
const isRequestOngoing = ref(true)
|
||||||
|
|||||||
@@ -212,7 +212,7 @@
|
|||||||
:status="estimate.status"
|
:status="estimate.status"
|
||||||
class="px-1 text-xs"
|
class="px-1 text-xs"
|
||||||
>
|
>
|
||||||
{{ estimate.status }}
|
<BaseEstimateStatusLabel :status="estimate.status" />
|
||||||
</BaseEstimateStatusBadge>
|
</BaseEstimateStatusBadge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -278,19 +278,19 @@ const expenseColumns = computed(() => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'expense_date',
|
key: 'expense_date',
|
||||||
label: 'Date',
|
label: t('expenses.date'),
|
||||||
thClass: 'extra',
|
thClass: 'extra',
|
||||||
tdClass: 'font-medium text-gray-900',
|
tdClass: 'font-medium text-gray-900',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'name',
|
key: 'name',
|
||||||
label: 'Category',
|
label: t('expenses.category'),
|
||||||
thClass: 'extra',
|
thClass: 'extra',
|
||||||
tdClass: 'cursor-pointer font-medium text-primary-500',
|
tdClass: 'cursor-pointer font-medium text-primary-500',
|
||||||
},
|
},
|
||||||
{ key: 'user_name', label: 'Customer' },
|
{ key: 'user_name', label: t('expenses.customer') },
|
||||||
{ key: 'notes', label: 'Note' },
|
{ key: 'notes', label: t('expenses.note') },
|
||||||
{ key: 'amount', label: 'Amount' },
|
{ key: 'amount', label: t('expenses.amount') },
|
||||||
{
|
{
|
||||||
key: 'actions',
|
key: 'actions',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<BaseWizard
|
<BaseWizard
|
||||||
:steps="7"
|
:steps="8"
|
||||||
:current-step="currentStepNumber"
|
:current-step="currentStepNumber"
|
||||||
@click="onNavClick"
|
@click="onNavClick"
|
||||||
>
|
>
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import Step0SetLanguage from './Step0SetLanguage.vue'
|
||||||
import Step1RequirementsCheck from './Step1RequirementsCheck.vue'
|
import Step1RequirementsCheck from './Step1RequirementsCheck.vue'
|
||||||
import Step2PermissionCheck from './Step2PermissionCheck.vue'
|
import Step2PermissionCheck from './Step2PermissionCheck.vue'
|
||||||
import Step3DatabaseConfig from './Step3DatabaseConfig.vue'
|
import Step3DatabaseConfig from './Step3DatabaseConfig.vue'
|
||||||
@@ -34,6 +35,7 @@ import { useRouter } from 'vue-router'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
step_0: Step0SetLanguage,
|
||||||
step_1: Step1RequirementsCheck,
|
step_1: Step1RequirementsCheck,
|
||||||
step_2: Step2PermissionCheck,
|
step_2: Step2PermissionCheck,
|
||||||
step_3: Step3DatabaseConfig,
|
step_3: Step3DatabaseConfig,
|
||||||
@@ -45,11 +47,12 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
let stepComponent = ref('step_1')
|
let stepComponent = ref('step_0')
|
||||||
let currentStepNumber = ref(1)
|
let currentStepNumber = ref(1)
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const installationStore = useInstallationStore()
|
const installationStore = useInstallationStore()
|
||||||
|
const { global } = window.i18n
|
||||||
|
|
||||||
checkCurrentProgress()
|
checkCurrentProgress()
|
||||||
|
|
||||||
@@ -61,6 +64,10 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(typeof res.data.profile_language === 'string') {
|
||||||
|
global.locale.value = res.data.profile_language
|
||||||
|
}
|
||||||
|
|
||||||
let dbstep = parseInt(res.data.profile_complete)
|
let dbstep = parseInt(res.data.profile_complete)
|
||||||
|
|
||||||
if (dbstep) {
|
if (dbstep) {
|
||||||
@@ -93,7 +100,7 @@ export default {
|
|||||||
|
|
||||||
currentStepNumber.value++
|
currentStepNumber.value++
|
||||||
|
|
||||||
if (currentStepNumber.value <= 8) {
|
if (currentStepNumber.value <= 9) {
|
||||||
stepComponent.value = 'step_' + currentStepNumber.value
|
stepComponent.value = 'step_' + currentStepNumber.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,85 @@
|
|||||||
|
<template>
|
||||||
|
<BaseWizardStep
|
||||||
|
:title="$t('wizard.install_language.title')"
|
||||||
|
:description="$t('wizard.install_language.description')"
|
||||||
|
>
|
||||||
|
<div class="w-full md:w-2/3">
|
||||||
|
<div class="mb-6">
|
||||||
|
<BaseInputGroup
|
||||||
|
:label="$t('wizard.language')"
|
||||||
|
:content-loading="isFetchingInitialData"
|
||||||
|
required
|
||||||
|
>
|
||||||
|
<BaseMultiselect
|
||||||
|
v-model="currentLanguage"
|
||||||
|
:content-loading="isFetchingInitialData"
|
||||||
|
:options="languages"
|
||||||
|
label="name"
|
||||||
|
value-prop="code"
|
||||||
|
:placeholder="$t('settings.preferences.select_language')"
|
||||||
|
class="w-full"
|
||||||
|
track-by="name"
|
||||||
|
:searchable="true"
|
||||||
|
@change="changeLanguage"
|
||||||
|
/>
|
||||||
|
</BaseInputGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<BaseButton
|
||||||
|
v-show="!isFetchingInitialData"
|
||||||
|
@click="next"
|
||||||
|
>
|
||||||
|
{{ $t('wizard.continue') }}
|
||||||
|
<template #left="slotProps">
|
||||||
|
<BaseIcon name="ArrowRightIcon" :class="slotProps.class" />
|
||||||
|
</template>
|
||||||
|
</BaseButton>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</BaseWizardStep>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { useInstallationStore } from '@/scripts/admin/stores/installation.js'
|
||||||
|
|
||||||
|
const { global } = window.i18n
|
||||||
|
|
||||||
|
const emit = defineEmits(['next'])
|
||||||
|
|
||||||
|
let isFetchingInitialData = ref(false)
|
||||||
|
let isSaving = ref(false)
|
||||||
|
let languages = ref([])
|
||||||
|
let currentLanguage = 'en'
|
||||||
|
|
||||||
|
const installationStore = useInstallationStore()
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getLanguages()
|
||||||
|
})
|
||||||
|
|
||||||
|
async function getLanguages() {
|
||||||
|
isFetchingInitialData.value = true
|
||||||
|
|
||||||
|
const res = await installationStore.fetchInstallationLanguages()
|
||||||
|
|
||||||
|
languages.value = res.data.languages
|
||||||
|
|
||||||
|
isFetchingInitialData.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
isSaving.value = true
|
||||||
|
emit('next')
|
||||||
|
isSaving.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeLanguage(event){
|
||||||
|
if(typeof global.locale !== 'string') {
|
||||||
|
global.locale.value = event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
@@ -36,11 +36,13 @@ export default {
|
|||||||
const database_connection = ref('mysql')
|
const database_connection = ref('mysql')
|
||||||
const isSaving = ref(false)
|
const isSaving = ref(false)
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
const { global } = window.i18n
|
||||||
|
|
||||||
const notificationStore = useNotificationStore()
|
const notificationStore = useNotificationStore()
|
||||||
const installationStore = useInstallationStore()
|
const installationStore = useInstallationStore()
|
||||||
|
|
||||||
const databaseData = computed(() => {
|
const databaseData = computed(() => {
|
||||||
|
installationStore.currentDataBaseData.app_locale = global.locale.value
|
||||||
return installationStore.currentDataBaseData
|
return installationStore.currentDataBaseData
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -75,6 +77,12 @@ export default {
|
|||||||
|
|
||||||
emit('next', 3)
|
emit('next', 3)
|
||||||
|
|
||||||
|
let language = {
|
||||||
|
profile_language: global.locale.value,
|
||||||
|
}
|
||||||
|
await installationStore.addInstallationLanguage(language)
|
||||||
|
|
||||||
|
|
||||||
notificationStore.showNotification({
|
notificationStore.showNotification({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: t('wizard.success.' + res.data.success),
|
message: t('wizard.success.' + res.data.success),
|
||||||
|
|||||||
@@ -18,17 +18,15 @@
|
|||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="mt-4 mb-0 text-sm text-gray-600">Notes:</p>
|
<p class="mt-4 mb-0 text-sm text-gray-600">{{ $t('wizard.verify_domain.notes.notes') }}</p>
|
||||||
<ul class="w-full text-gray-600 list-disc list-inside">
|
<ul class="w-full text-gray-600 list-disc list-inside">
|
||||||
<li class="text-sm leading-8">
|
<li class="text-sm leading-8">
|
||||||
App domain should not contain
|
{{ $t('wizard.verify_domain.notes.not_contain') }}
|
||||||
<b class="inline-block px-1 bg-gray-100 rounded-sm">https://</b> or
|
<b class="inline-block px-1 bg-gray-100 rounded-sm">https://</b> {{ $t('wizard.verify_domain.notes.or') }}
|
||||||
<b class="inline-block px-1 bg-gray-100 rounded-sm">http</b> in front of
|
<b class="inline-block px-1 bg-gray-100 rounded-sm">http</b> {{ $t('wizard.verify_domain.notes.in_front') }}
|
||||||
the domain.
|
|
||||||
</li>
|
</li>
|
||||||
<li class="text-sm leading-8">
|
<li class="text-sm leading-8">
|
||||||
If you're accessing the website on a different port, please mention the
|
{{ $t('wizard.verify_domain.notes.if_you') }}
|
||||||
port. For example:
|
|
||||||
<b class="inline-block px-1 bg-gray-100">localhost:8080</b>
|
<b class="inline-block px-1 bg-gray-100">localhost:8080</b>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
<BaseMultiselect
|
<BaseMultiselect
|
||||||
v-model="currentPreferences.fiscal_year"
|
v-model="currentPreferences.fiscal_year"
|
||||||
:content-loading="isFetchingInitialData"
|
:content-loading="isFetchingInitialData"
|
||||||
:options="globalStore.fiscalYears"
|
:options="fiscalYearsList"
|
||||||
label="key"
|
label="key"
|
||||||
value-prop="value"
|
value-prop="value"
|
||||||
:placeholder="$t('settings.preferences.select_financial_year')"
|
:placeholder="$t('settings.preferences.select_financial_year')"
|
||||||
@@ -174,6 +174,14 @@ const router = useRouter()
|
|||||||
|
|
||||||
isFetchingInitialData.value = true
|
isFetchingInitialData.value = true
|
||||||
|
|
||||||
|
const fiscalYearsList = computed(() => {
|
||||||
|
return globalStore.fiscalYears.map((item) => {
|
||||||
|
return Object.assign({}, item, {
|
||||||
|
key: t(item.key),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
const options = reactive([
|
const options = reactive([
|
||||||
{
|
{
|
||||||
title: tm('settings.customization.invoices.allow'),
|
title: tm('settings.customization.invoices.allow'),
|
||||||
|
|||||||
@@ -225,7 +225,7 @@
|
|||||||
<!-- Invoice status -->
|
<!-- Invoice status -->
|
||||||
<template #cell-status="{ row }">
|
<template #cell-status="{ row }">
|
||||||
<BaseInvoiceStatusBadge :status="row.data.status" class="px-3 py-1">
|
<BaseInvoiceStatusBadge :status="row.data.status" class="px-3 py-1">
|
||||||
{{ row.data.status }}
|
<BaseInvoiceStatusLabel :status="row.data.status" />
|
||||||
</BaseInvoiceStatusBadge>
|
</BaseInvoiceStatusBadge>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@
|
|||||||
:status="row.data.paid_status"
|
:status="row.data.paid_status"
|
||||||
class="px-1 py-0.5 ml-2"
|
class="px-1 py-0.5 ml-2"
|
||||||
>
|
>
|
||||||
{{ row.data.paid_status }}
|
<BaseInvoiceStatusLabel :status="row.data.paid_status" />
|
||||||
</BasePaidStatusBadge>
|
</BasePaidStatusBadge>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -277,6 +277,7 @@ import { debouncedWatch } from '@vueuse/core'
|
|||||||
import MoonwalkerIcon from '@/scripts/components/icons/empty/MoonwalkerIcon.vue'
|
import MoonwalkerIcon from '@/scripts/components/icons/empty/MoonwalkerIcon.vue'
|
||||||
import InvoiceDropdown from '@/scripts/admin/components/dropdowns/InvoiceIndexDropdown.vue'
|
import InvoiceDropdown from '@/scripts/admin/components/dropdowns/InvoiceIndexDropdown.vue'
|
||||||
import SendInvoiceModal from '@/scripts/admin/components/modal-components/SendInvoiceModal.vue'
|
import SendInvoiceModal from '@/scripts/admin/components/modal-components/SendInvoiceModal.vue'
|
||||||
|
import BaseInvoiceStatusLabel from "@/scripts/components/base/BaseInvoiceStatusLabel.vue";
|
||||||
// Stores
|
// Stores
|
||||||
const invoiceStore = useInvoiceStore()
|
const invoiceStore = useInvoiceStore()
|
||||||
const dialogStore = useDialogStore()
|
const dialogStore = useDialogStore()
|
||||||
@@ -291,12 +292,21 @@ const showFilters = ref(false)
|
|||||||
|
|
||||||
const status = ref([
|
const status = ref([
|
||||||
{
|
{
|
||||||
label: 'Status',
|
label: t('invoices.status'),
|
||||||
options: ['DRAFT', 'DUE', 'SENT', 'VIEWED', 'COMPLETED'],
|
options: [
|
||||||
|
{label: t('general.draft'), value: 'DRAFT'},
|
||||||
|
{label: t('general.due'), value: 'DUE'},
|
||||||
|
{label: t('general.sent'), value: 'SENT'},
|
||||||
|
{label: t('invoices.viewed'), value: 'VIEWED'},
|
||||||
|
{label: t('invoices.completed'), value: 'COMPLETED'}
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Paid Status',
|
label: t('invoices.paid_status'),
|
||||||
options: ['UNPAID', 'PAID', 'PARTIALLY_PAID'],
|
options: [
|
||||||
|
{label: t('invoices.unpaid'), value: 'UNPAID'},
|
||||||
|
{label: t('invoices.paid'), value: 'PAID'},
|
||||||
|
{label: t('invoices.partially_paid'), value: 'PARTIALLY_PAID'}],
|
||||||
},
|
},
|
||||||
,
|
,
|
||||||
])
|
])
|
||||||
|
|||||||
@@ -454,7 +454,7 @@ onSearched = debounce(onSearched, 500)
|
|||||||
:status="invoice.status"
|
:status="invoice.status"
|
||||||
class="px-1 text-xs"
|
class="px-1 text-xs"
|
||||||
>
|
>
|
||||||
{{ invoice.status }}
|
<BaseInvoiceStatusLabel :status="invoice.status" />
|
||||||
</BaseEstimateStatusBadge>
|
</BaseEstimateStatusBadge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -101,7 +101,7 @@
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
<BaseButton variant="primary-outline" type="button">
|
<BaseButton variant="primary-outline" type="button">
|
||||||
Sign up & Get Token
|
{{ $t('modules.sign_up_and_get_token') }}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
:label="$t('payments.invoice')"
|
:label="$t('payments.invoice')"
|
||||||
:help-text="
|
:help-text="
|
||||||
selectedInvoice
|
selectedInvoice
|
||||||
? `Due Amount: ${
|
? `${t('payments.amount_due')}: ${
|
||||||
paymentStore.currentPayment.maxPayableAmount / 100
|
paymentStore.currentPayment.maxPayableAmount / 100
|
||||||
}`
|
}`
|
||||||
: ''
|
: ''
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ const paymentColumns = computed(() => {
|
|||||||
{ key: 'payment_number', label: t('payments.payment_number') },
|
{ key: 'payment_number', label: t('payments.payment_number') },
|
||||||
{ key: 'name', label: t('payments.customer') },
|
{ key: 'name', label: t('payments.customer') },
|
||||||
{ key: 'payment_mode', label: t('payments.payment_mode') },
|
{ key: 'payment_mode', label: t('payments.payment_mode') },
|
||||||
{ key: 'invoice_number', label: t('invoices.invoice_number') },
|
{ key: 'invoice_number', label: t('payments.invoice') },
|
||||||
{ key: 'amount', label: t('payments.amount') },
|
{ key: 'amount', label: t('payments.amount') },
|
||||||
{
|
{
|
||||||
key: 'actions',
|
key: 'actions',
|
||||||
|
|||||||
@@ -230,7 +230,7 @@
|
|||||||
:status="row.data.status"
|
:status="row.data.status"
|
||||||
class="px-3 py-1"
|
class="px-3 py-1"
|
||||||
>
|
>
|
||||||
{{ row.data.status }}
|
<BaseRecurringInvoiceStatusLabel :status="row.data.status" />
|
||||||
</BaseRecurringInvoiceStatusBadge>
|
</BaseRecurringInvoiceStatusBadge>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -276,7 +276,11 @@ const userStore = useUserStore()
|
|||||||
const table = ref(null)
|
const table = ref(null)
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const showFilters = ref(false)
|
const showFilters = ref(false)
|
||||||
const statusList = ref(['ACTIVE', 'ON_HOLD', 'ALL'])
|
const statusList = ref([
|
||||||
|
{label: t('recurring_invoices.active'), value: 'ACTIVE'},
|
||||||
|
{label: t('recurring_invoices.on_hold'), value: 'ON_HOLD'},
|
||||||
|
{label: t('recurring_invoices.all'), value: 'ALL'}
|
||||||
|
])
|
||||||
const isRequestOngoing = ref(true)
|
const isRequestOngoing = ref(true)
|
||||||
const activeTab = ref('recurring-invoices.all')
|
const activeTab = ref('recurring-invoices.all')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|||||||
@@ -129,7 +129,7 @@
|
|||||||
:invalid="v.status.$error"
|
:invalid="v.status.$error"
|
||||||
:placeholder="$t('recurring_invoices.select_a_status')"
|
:placeholder="$t('recurring_invoices.select_a_status')"
|
||||||
value-prop="value"
|
value-prop="value"
|
||||||
label="value"
|
label="key"
|
||||||
/>
|
/>
|
||||||
</BaseInputGroup>
|
</BaseInputGroup>
|
||||||
|
|
||||||
@@ -186,6 +186,7 @@ import { useDebounceFn } from '@vueuse/core'
|
|||||||
import { useRecurringInvoiceStore } from '@/scripts/admin/stores/recurring-invoice'
|
import { useRecurringInvoiceStore } from '@/scripts/admin/stores/recurring-invoice'
|
||||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import ExchangeRateConverter from '@/scripts/admin/components/estimate-invoice-common/ExchangeRateConverter.vue'
|
import ExchangeRateConverter from '@/scripts/admin/components/estimate-invoice-common/ExchangeRateConverter.vue'
|
||||||
|
|
||||||
@@ -207,13 +208,14 @@ const props = defineProps({
|
|||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const recurringInvoiceStore = useRecurringInvoiceStore()
|
const recurringInvoiceStore = useRecurringInvoiceStore()
|
||||||
const globalStore = useGlobalStore()
|
const globalStore = useGlobalStore()
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
const isLoadingNextDate = ref(false)
|
const isLoadingNextDate = ref(false)
|
||||||
|
|
||||||
const limits = reactive([
|
const limits = reactive([
|
||||||
{ label: 'None', value: 'NONE' },
|
{ label: t('recurring_invoices.limit.none'), value: 'NONE' },
|
||||||
{ label: 'Date', value: 'DATE' },
|
{ label: t('recurring_invoices.limit.date'), value: 'DATE' },
|
||||||
{ label: 'Count', value: 'COUNT' },
|
{ label: t('recurring_invoices.limit.count'), value: 'COUNT' },
|
||||||
])
|
])
|
||||||
|
|
||||||
const isCustomFrequency = computed(() => {
|
const isCustomFrequency = computed(() => {
|
||||||
@@ -226,9 +228,17 @@ const isCustomFrequency = computed(() => {
|
|||||||
|
|
||||||
const getStatusOptions = computed(() => {
|
const getStatusOptions = computed(() => {
|
||||||
if (props.isEdit) {
|
if (props.isEdit) {
|
||||||
return globalStore.config.recurring_invoice_status.update_status
|
return globalStore.config.recurring_invoice_status.update_status.map((item) => {
|
||||||
|
return Object.assign({}, item, {
|
||||||
|
key: t(item.key),
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return globalStore.config.recurring_invoice_status.create_status
|
return globalStore.config.recurring_invoice_status.create_status.map((item) => {
|
||||||
|
return Object.assign({}, item, {
|
||||||
|
key: t(item.key),
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
|
|||||||
@@ -27,10 +27,15 @@
|
|||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<!-- Invoice date -->
|
||||||
|
<template #cell-invoice_date="{ row }">
|
||||||
|
{{ row.data.formatted_invoice_date }}
|
||||||
|
</template>
|
||||||
|
|
||||||
<!-- Invoice status -->
|
<!-- Invoice status -->
|
||||||
<template #cell-status="{ row }">
|
<template #cell-status="{ row }">
|
||||||
<BaseInvoiceStatusBadge :status="row.data.status" class="px-3 py-1">
|
<BaseInvoiceStatusBadge :status="row.data.status" class="px-3 py-1">
|
||||||
{{ row.data.status }}
|
<BaseInvoiceStatusLabel :status="row.data.status" />
|
||||||
</BaseInvoiceStatusBadge>
|
</BaseInvoiceStatusBadge>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ onSearched = debounce(onSearched, 500)
|
|||||||
:status="invoice.status"
|
:status="invoice.status"
|
||||||
class="px-1 text-xs"
|
class="px-1 text-xs"
|
||||||
>
|
>
|
||||||
{{ invoice.status }}
|
<BaseRecurringInvoiceStatusLabel :status="invoice.status" />
|
||||||
</BaseRecurringInvoiceStatusBadge>
|
</BaseRecurringInvoiceStatusBadge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -156,7 +156,16 @@ const dateRange = reactive([
|
|||||||
])
|
])
|
||||||
|
|
||||||
const selectedRange = ref(dateRange[2])
|
const selectedRange = ref(dateRange[2])
|
||||||
const reportTypes = ref(['By Customer', 'By Item'])
|
const reportTypes = ref([
|
||||||
|
{
|
||||||
|
label: t('reports.sales.sort.by_customer'),
|
||||||
|
value: 'By Customer'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('reports.sales.sort.by_item'),
|
||||||
|
value: 'By Item'
|
||||||
|
}
|
||||||
|
])
|
||||||
const selectedType = ref('By Customer')
|
const selectedType = ref('By Customer')
|
||||||
let range = ref(new Date())
|
let range = ref(new Date())
|
||||||
let url = ref(null)
|
let url = ref(null)
|
||||||
|
|||||||
@@ -30,6 +30,10 @@
|
|||||||
<span class="text-xs text-gray-500"> ({{ row.data.slug }})</span>
|
<span class="text-xs text-gray-500"> ({{ row.data.slug }})</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #cell-model_type="{ row }">
|
||||||
|
{{ getModelType(row.data.model_type) }}
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #cell-is_required="{ row }">
|
<template #cell-is_required="{ row }">
|
||||||
<BaseBadge
|
<BaseBadge
|
||||||
:bg-color="
|
:bg-color="
|
||||||
@@ -147,4 +151,21 @@ function addCustomField() {
|
|||||||
async function refreshTable() {
|
async function refreshTable() {
|
||||||
table.value && table.value.refresh()
|
table.value && table.value.refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getModelType(type) {
|
||||||
|
switch (type) {
|
||||||
|
case 'Customer':
|
||||||
|
return t('settings.custom_fields.model_type.customer')
|
||||||
|
case 'Invoice':
|
||||||
|
return t('settings.custom_fields.model_type.invoice')
|
||||||
|
case 'Estimate':
|
||||||
|
return t('settings.custom_fields.model_type.estimate')
|
||||||
|
case 'Expense':
|
||||||
|
return t('settings.custom_fields.model_type.expense')
|
||||||
|
case 'Payment':
|
||||||
|
return t('settings.custom_fields.model_type.payment')
|
||||||
|
default:
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
.color
|
.color
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{ row.data.set_as_default ? 'Yes' : 'No'.replace('_', ' ') }}
|
{{ row.data.set_as_default ? $t('general.yes') : $t('general.no').replace('_', ' ') }}
|
||||||
</BaseBadge>
|
</BaseBadge>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,9 @@
|
|||||||
:load-data="refreshTable"
|
:load-data="refreshTable"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
<template #cell-type="{ row }">
|
||||||
|
{{ getLabelNote(row.data.type) }}
|
||||||
|
</template>
|
||||||
</BaseTable>
|
</BaseTable>
|
||||||
</BaseSettingCard>
|
</BaseSettingCard>
|
||||||
</template>
|
</template>
|
||||||
@@ -113,4 +116,17 @@ async function openNoteSelectModal() {
|
|||||||
async function refreshTable() {
|
async function refreshTable() {
|
||||||
table.value && table.value.refresh()
|
table.value && table.value.refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getLabelNote(type) {
|
||||||
|
switch (type) {
|
||||||
|
case 'Estimate':
|
||||||
|
return t('settings.customization.notes.types.estimate')
|
||||||
|
case 'Invoice':
|
||||||
|
return t('settings.customization.notes.types.invoice')
|
||||||
|
case 'Payment':
|
||||||
|
return t('settings.customization.notes.types.payment')
|
||||||
|
default:
|
||||||
|
return type
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -95,7 +95,7 @@
|
|||||||
<BaseMultiselect
|
<BaseMultiselect
|
||||||
v-model="settingsForm.fiscal_year"
|
v-model="settingsForm.fiscal_year"
|
||||||
:content-loading="isFetchingInitialData"
|
:content-loading="isFetchingInitialData"
|
||||||
:options="globalStore.config.fiscal_years"
|
:options="fiscalYearsList"
|
||||||
label="key"
|
label="key"
|
||||||
value-prop="value"
|
value-prop="value"
|
||||||
:invalid="v$.fiscal_year.$error"
|
:invalid="v$.fiscal_year.$error"
|
||||||
@@ -197,6 +197,14 @@ const retrospectiveEditOptions = computed(() => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const fiscalYearsList = computed(() => {
|
||||||
|
return globalStore.config.fiscal_years.map((item) => {
|
||||||
|
return Object.assign({}, item, {
|
||||||
|
key: t(item.key),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => settingsForm.carbon_date_format,
|
() => settingsForm.carbon_date_format,
|
||||||
(val) => {
|
(val) => {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
border-t border-b border-gray-200 border-solid
|
border-t border-b border-gray-200 border-solid
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Component
|
{{ $t('settings.customization.component') }}
|
||||||
</th>
|
</th>
|
||||||
<th
|
<th
|
||||||
class="
|
class="
|
||||||
@@ -57,7 +57,7 @@
|
|||||||
border-t border-b border-gray-200 border-solid
|
border-t border-b border-gray-200 border-solid
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
Parameter
|
{{ $t('settings.customization.Parameter') }}
|
||||||
</th>
|
</th>
|
||||||
<th
|
<th
|
||||||
class="
|
class="
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
variant="white"
|
variant="white"
|
||||||
@click.prevent="removeComponent(element)"
|
@click.prevent="removeComponent(element)"
|
||||||
>
|
>
|
||||||
Remove
|
{{ $t('general.remove') }}
|
||||||
<template #left="slotProps">
|
<template #left="slotProps">
|
||||||
<BaseIcon
|
<BaseIcon
|
||||||
name="XIcon"
|
name="XIcon"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<BaseInput
|
<BaseInput
|
||||||
v-model="name"
|
v-model="name"
|
||||||
placeholder="Search..."
|
:placeholder="$t('global_search.search')"
|
||||||
container-class="!rounded"
|
container-class="!rounded"
|
||||||
class="h-8 md:h-9 !rounded"
|
class="h-8 md:h-9 !rounded"
|
||||||
@input="onSearch"
|
@input="onSearch"
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
:status="invoice.paid_status"
|
:status="invoice.paid_status"
|
||||||
class="px-3 py-1"
|
class="px-3 py-1"
|
||||||
>
|
>
|
||||||
{{ invoice.paid_status }}
|
<BaseInvoiceStatusLabel :status="invoice.paid_status" />
|
||||||
</BaseInvoiceStatusBadge>
|
</BaseInvoiceStatusBadge>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -181,11 +181,11 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<slot v-if="noOptions" name="nooptions">
|
<slot v-if="noOptions" name="nooptions">
|
||||||
<div :class="classList.noOptions" v-html="noOptionsText"></div>
|
<div :class="classList.noOptions" v-html="$t('general.multiselect.the_list_is_empty')"></div>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<slot v-if="noResults" name="noresults">
|
<slot v-if="noResults" name="noresults">
|
||||||
<div :class="classList.noResults" v-html="noResultsText"></div>
|
<div :class="classList.noResults" v-html="$t('general.multiselect.no_results_found')"></div>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<slot name="afterlist" :options="fo"> </slot>
|
<slot name="afterlist" :options="fo"> </slot>
|
||||||
|
|||||||
@@ -49,8 +49,39 @@
|
|||||||
<script type="text/babel" setup>
|
<script type="text/babel" setup>
|
||||||
import FlatPickr from 'vue-flatpickr-component'
|
import FlatPickr from 'vue-flatpickr-component'
|
||||||
import 'flatpickr/dist/flatpickr.css'
|
import 'flatpickr/dist/flatpickr.css'
|
||||||
|
import { Arabic } from 'flatpickr/dist/l10n/ar.js'
|
||||||
|
import { Czech } from 'flatpickr/dist/l10n/cs.js'
|
||||||
|
import { German } from 'flatpickr/dist/l10n/de.js'
|
||||||
|
import { Greek } from 'flatpickr/dist/l10n/gr.js'
|
||||||
|
import { english } from 'flatpickr/dist/l10n/default.js'
|
||||||
|
import { Spanish } from 'flatpickr/dist/l10n/es.js'
|
||||||
|
import { Persian } from 'flatpickr/dist/l10n/fa.js'
|
||||||
|
import { Finnish } from 'flatpickr/dist/l10n/fi.js'
|
||||||
|
import { French } from 'flatpickr/dist/l10n/fr.js'
|
||||||
|
import { Hindi } from 'flatpickr/dist/l10n/hi.js'
|
||||||
|
import { Croatian } from 'flatpickr/dist/l10n/hr.js'
|
||||||
|
import { Indonesian } from 'flatpickr/dist/l10n/id.js'
|
||||||
|
import { Italian } from 'flatpickr/dist/l10n/it.js'
|
||||||
|
import { Japanese } from 'flatpickr/dist/l10n/ja.js'
|
||||||
|
import { Korean } from 'flatpickr/dist/l10n/ko.js'
|
||||||
|
import { Lithuanian } from 'flatpickr/dist/l10n/lt.js'
|
||||||
|
import { Latvian } from 'flatpickr/dist/l10n/lv.js'
|
||||||
|
import { Dutch } from 'flatpickr/dist/l10n/nl.js'
|
||||||
|
import { Polish } from 'flatpickr/dist/l10n/pl.js'
|
||||||
|
import { Portuguese } from 'flatpickr/dist/l10n/pt.js'
|
||||||
|
import { Romanian } from 'flatpickr/dist/l10n/ro.js'
|
||||||
|
import { Russian } from 'flatpickr/dist/l10n/ru.js'
|
||||||
|
import { Slovak } from 'flatpickr/dist/l10n/sk.js'
|
||||||
|
import { Slovenian } from 'flatpickr/dist/l10n/sl.js'
|
||||||
|
import { Serbian } from 'flatpickr/dist/l10n/sr.js'
|
||||||
|
import { Swedish } from 'flatpickr/dist/l10n/sv.js'
|
||||||
|
import { Thai } from 'flatpickr/dist/l10n/th.js'
|
||||||
|
import { Turkish } from 'flatpickr/dist/l10n/tr.js'
|
||||||
|
import { Vietnamese } from 'flatpickr/dist/l10n/vn.js'
|
||||||
|
import { Mandarin } from 'flatpickr/dist/l10n/zh.js'
|
||||||
import { computed, reactive, watch, ref, useSlots } from 'vue'
|
import { computed, reactive, watch, ref, useSlots } from 'vue'
|
||||||
import { useCompanyStore } from '@/scripts/admin/stores/company'
|
import { useCompanyStore } from '@/scripts/admin/stores/company'
|
||||||
|
import { useUserStore } from '@/scripts/admin/stores/user'
|
||||||
|
|
||||||
const dp = ref(null)
|
const dp = ref(null)
|
||||||
|
|
||||||
@@ -104,10 +135,112 @@ const slots = useSlots()
|
|||||||
|
|
||||||
const companyStore = useCompanyStore()
|
const companyStore = useCompanyStore()
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
|
||||||
|
//Localize Flatpicker stuff
|
||||||
|
const lang = userStore.currentUserSettings.language
|
||||||
|
let fpLocale = null
|
||||||
|
switch(lang){
|
||||||
|
case 'ar':
|
||||||
|
fpLocale = Arabic;
|
||||||
|
break;
|
||||||
|
case 'cs':
|
||||||
|
fpLocale = Czech;
|
||||||
|
break;
|
||||||
|
case 'de':
|
||||||
|
fpLocale = German;
|
||||||
|
break;
|
||||||
|
case 'el':
|
||||||
|
fpLocale = Greek;
|
||||||
|
break;
|
||||||
|
case 'en':
|
||||||
|
fpLocale = english;
|
||||||
|
break;
|
||||||
|
case 'es':
|
||||||
|
fpLocale = Spanish;
|
||||||
|
break;
|
||||||
|
case 'fa':
|
||||||
|
fpLocale = Persian;
|
||||||
|
break;
|
||||||
|
case 'fi':
|
||||||
|
fpLocale = Finnish;
|
||||||
|
break;
|
||||||
|
case 'fr':
|
||||||
|
fpLocale = French;
|
||||||
|
break;
|
||||||
|
case 'hi':
|
||||||
|
fpLocale = Hindi;
|
||||||
|
break;
|
||||||
|
case 'hr':
|
||||||
|
fpLocale = Croatian;
|
||||||
|
break;
|
||||||
|
case 'id':
|
||||||
|
fpLocale = Indonesian;
|
||||||
|
break;
|
||||||
|
case 'it':
|
||||||
|
fpLocale = Italian;
|
||||||
|
break;
|
||||||
|
case 'ja':
|
||||||
|
fpLocale = Japanese;
|
||||||
|
break;
|
||||||
|
case 'ko':
|
||||||
|
fpLocale = Korean;
|
||||||
|
break;
|
||||||
|
case 'lt':
|
||||||
|
fpLocale = Lithuanian;
|
||||||
|
break;
|
||||||
|
case 'lv':
|
||||||
|
fpLocale = Latvian;
|
||||||
|
break;
|
||||||
|
case 'nl':
|
||||||
|
fpLocale = Dutch;
|
||||||
|
break;
|
||||||
|
case 'pl':
|
||||||
|
fpLocale = Polish;
|
||||||
|
break;
|
||||||
|
case 'pt':
|
||||||
|
case 'pt_BR':
|
||||||
|
fpLocale = Portuguese;
|
||||||
|
break;
|
||||||
|
case 'ro':
|
||||||
|
fpLocale = Romanian;
|
||||||
|
break;
|
||||||
|
case 'ru':
|
||||||
|
fpLocale = Russian;
|
||||||
|
break;
|
||||||
|
case 'sk':
|
||||||
|
fpLocale = Slovak;
|
||||||
|
break;
|
||||||
|
case 'sl':
|
||||||
|
fpLocale = Slovenian;
|
||||||
|
break;
|
||||||
|
case 'sr':
|
||||||
|
fpLocale = Serbian;
|
||||||
|
break;
|
||||||
|
case 'sv':
|
||||||
|
fpLocale = Swedish;
|
||||||
|
break;
|
||||||
|
case 'th':
|
||||||
|
fpLocale = Thai;
|
||||||
|
break;
|
||||||
|
case 'tr':
|
||||||
|
fpLocale = Turkish;
|
||||||
|
break;
|
||||||
|
case 'vi':
|
||||||
|
fpLocale = Vietnamese;
|
||||||
|
break;
|
||||||
|
case 'zh':
|
||||||
|
fpLocale = Mandarin;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fpLocale = english;
|
||||||
|
}
|
||||||
|
|
||||||
let config = reactive({
|
let config = reactive({
|
||||||
altInput: true,
|
altInput: true,
|
||||||
enableTime: props.enableTime,
|
enableTime: props.enableTime,
|
||||||
time_24hr: props.time24hr,
|
time_24hr: props.time24hr,
|
||||||
|
locale: fpLocale
|
||||||
})
|
})
|
||||||
|
|
||||||
const date = computed({
|
const date = computed({
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<template>
|
||||||
|
{{ labelStatus }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
status: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const labelStatus = computed(() => {
|
||||||
|
switch (props.status) {
|
||||||
|
case 'DRAFT':
|
||||||
|
return t('estimates.draft')
|
||||||
|
case 'SENT':
|
||||||
|
return t('estimates.sent')
|
||||||
|
case 'VIEWED':
|
||||||
|
return t('estimates.viewed')
|
||||||
|
case 'EXPIRED':
|
||||||
|
return t('estimates.expired')
|
||||||
|
case 'ACCEPTED':
|
||||||
|
return t('estimates.accepted')
|
||||||
|
case 'REJECTED':
|
||||||
|
return t('estimates.rejected')
|
||||||
|
case 'DECLINED':
|
||||||
|
return t('estimates.declined')
|
||||||
|
default:
|
||||||
|
return props.status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
class="h-6 mb-2 text-xl leading-6 text-gray-400"
|
class="h-6 mb-2 text-xl leading-6 text-gray-400"
|
||||||
/>
|
/>
|
||||||
<p class="text-xs leading-4 text-center text-gray-400">
|
<p class="text-xs leading-4 text-center text-gray-400">
|
||||||
Drag a file here or
|
{{ $t('general.file_upload.drag_a_file') }}
|
||||||
<a
|
<a
|
||||||
class="
|
class="
|
||||||
cursor-pointer
|
cursor-pointer
|
||||||
@@ -83,9 +83,9 @@
|
|||||||
href="#"
|
href="#"
|
||||||
@click.prevent.stop="onBrowse"
|
@click.prevent.stop="onBrowse"
|
||||||
>
|
>
|
||||||
browse
|
{{ $t('general.file_upload.browse') }}
|
||||||
</a>
|
</a>
|
||||||
to choose a file
|
{{ $t('general.file_upload.to_choose') }}
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs leading-4 text-center text-gray-400 mt-2">
|
<p class="text-xs leading-4 text-center text-gray-400 mt-2">
|
||||||
{{ recommendedText }}
|
{{ recommendedText }}
|
||||||
|
|||||||
43
resources/scripts/components/base/BaseInvoiceStatusLabel.vue
Normal file
43
resources/scripts/components/base/BaseInvoiceStatusLabel.vue
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
{{ labelStatus }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
status: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const labelStatus = computed(() => {
|
||||||
|
switch (props.status) {
|
||||||
|
case 'DRAFT':
|
||||||
|
return t('general.draft')
|
||||||
|
case 'SENT':
|
||||||
|
return t('general.sent')
|
||||||
|
case 'VIEWED':
|
||||||
|
return t('invoices.viewed')
|
||||||
|
case 'COMPLETED':
|
||||||
|
return t('invoices.completed')
|
||||||
|
case 'DUE':
|
||||||
|
return t('general.due')
|
||||||
|
case 'OVERDUE':
|
||||||
|
return t('invoices.overdue')
|
||||||
|
case 'UNPAID':
|
||||||
|
return t('invoices.unpaid')
|
||||||
|
case 'PARTIALLY_PAID':
|
||||||
|
return t('invoices.partially_paid')
|
||||||
|
case 'PAID':
|
||||||
|
return t('invoices.paid')
|
||||||
|
default:
|
||||||
|
return props.status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
{{ labelStatus }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { computed } from 'vue'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
status: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const labelStatus = computed(() => {
|
||||||
|
switch (props.status) {
|
||||||
|
case 'COMPLETED':
|
||||||
|
return t('recurring_invoices.complete')
|
||||||
|
case 'ON_HOLD':
|
||||||
|
return t('recurring_invoices.on_hold')
|
||||||
|
case 'ACTIVE':
|
||||||
|
return t('recurring_invoices.active')
|
||||||
|
default:
|
||||||
|
return props.status
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
@@ -128,7 +128,7 @@
|
|||||||
class="w-6 h-6 text-gray-400"
|
class="w-6 h-6 text-gray-400"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<span class="block mt-1">{{ noResultsMessage }}</span>
|
<span class="block mt-1">{{ $t('general.no_data_found') }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BaseTablePagination
|
<BaseTablePagination
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
"
|
"
|
||||||
@click="pageClicked(pagination.currentPage - 1)"
|
@click="pageClicked(pagination.currentPage - 1)"
|
||||||
>
|
>
|
||||||
Previous
|
{{ $t('general.pagination.previous') }}
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="#"
|
||||||
@@ -60,13 +60,13 @@
|
|||||||
"
|
"
|
||||||
@click="pageClicked(pagination.currentPage + 1)"
|
@click="pageClicked(pagination.currentPage + 1)"
|
||||||
>
|
>
|
||||||
Next
|
{{ $t('general.pagination.next') }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
|
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p class="text-sm text-gray-700">
|
<p class="text-sm text-gray-700">
|
||||||
Showing
|
{{ $t('general.pagination.showing') }}
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
<span
|
<span
|
||||||
v-if="pagination.limit && pagination.currentPage"
|
v-if="pagination.limit && pagination.currentPage"
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
to
|
{{ $t('general.pagination.to') }}
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
<span
|
<span
|
||||||
v-if="pagination.limit && pagination.currentPage"
|
v-if="pagination.limit && pagination.currentPage"
|
||||||
@@ -96,13 +96,13 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
of
|
{{ $t('general.pagination.of') }}
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
<span v-if="pagination.totalCount" class="font-medium">
|
<span v-if="pagination.totalCount" class="font-medium">
|
||||||
{{ pagination.totalCount }}
|
{{ pagination.totalCount }}
|
||||||
</span>
|
</span>
|
||||||
{{ ' ' }}
|
{{ ' ' }}
|
||||||
results
|
{{ $t('general.pagination.results') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
'inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium',
|
'inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium',
|
||||||
]"
|
]"
|
||||||
>
|
>
|
||||||
{{ item.title }}
|
{{ $t(item.title) }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
'block pl-3 pr-4 py-2 border-l-4 text-base font-medium',
|
'block pl-3 pr-4 py-2 border-l-4 text-base font-medium',
|
||||||
]"
|
]"
|
||||||
:aria-current="item.current ? 'page' : undefined"
|
:aria-current="item.current ? 'page' : undefined"
|
||||||
>{{ item.title }}
|
>{{ $t(item.title) }}
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="pt-4 pb-3 border-t border-gray-200">
|
<div class="pt-4 pb-3 border-t border-gray-200">
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
: 'border-transparent text-gray-600 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-800',
|
: 'border-transparent text-gray-600 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-800',
|
||||||
'block pl-3 pr-4 py-2 border-l-4 text-base font-medium',
|
'block pl-3 pr-4 py-2 border-l-4 text-base font-medium',
|
||||||
]"
|
]"
|
||||||
>{{ item.title }}</router-link
|
>{{ $t(item.title) }}</router-link
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { handleError } from '@/scripts/customer/helpers/error-handling'
|
|||||||
import { useUserStore } from './user'
|
import { useUserStore } from './user'
|
||||||
const { defineStore } = window.pinia
|
const { defineStore } = window.pinia
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
const { global } = window.i18n
|
||||||
export const useGlobalStore = defineStore({
|
export const useGlobalStore = defineStore({
|
||||||
id: 'CustomerPortalGlobalStore',
|
id: 'CustomerPortalGlobalStore',
|
||||||
state: () => ({
|
state: () => ({
|
||||||
@@ -29,7 +30,12 @@ export const useGlobalStore = defineStore({
|
|||||||
this.currency = response.data.data.currency
|
this.currency = response.data.data.currency
|
||||||
this.enabledModules = response.data.meta.modules
|
this.enabledModules = response.data.meta.modules
|
||||||
Object.assign(userStore.userForm, response.data.data)
|
Object.assign(userStore.userForm, response.data.data)
|
||||||
window.i18n.locale = response.data.default_language
|
|
||||||
|
if(typeof global.locale !== 'string') {
|
||||||
|
global.locale.value =
|
||||||
|
response.data.meta.current_company_language || 'en'
|
||||||
|
}
|
||||||
|
|
||||||
this.isAppLoaded = true
|
this.isAppLoaded = true
|
||||||
resolve(response)
|
resolve(response)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
:icon-component="InvoiceIcon"
|
:icon-component="InvoiceIcon"
|
||||||
:loading="!globalStore.getDashboardDataLoaded"
|
:loading="!globalStore.getDashboardDataLoaded"
|
||||||
:route="{ name: 'invoices.dashboard' }"
|
:route="{ name: 'invoices.dashboard' }"
|
||||||
:label="$t('dashboard.cards.invoices')"
|
:label="(dashboardStore.invoiceCount <= 1 ? $t('dashboard.cards.invoices', 1) : $t('dashboard.cards.invoices', 2))"
|
||||||
>
|
>
|
||||||
{{ dashboardStore.invoiceCount }}
|
{{ dashboardStore.invoiceCount }}
|
||||||
</DashboardStatsItem>
|
</DashboardStatsItem>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
:icon-component="EstimateIcon"
|
:icon-component="EstimateIcon"
|
||||||
:loading="!globalStore.getDashboardDataLoaded"
|
:loading="!globalStore.getDashboardDataLoaded"
|
||||||
:route="{ name: 'estimates.dashboard' }"
|
:route="{ name: 'estimates.dashboard' }"
|
||||||
:label="$t('dashboard.cards.estimates')"
|
:label="(dashboardStore.estimateCount <= 1 ? $t('dashboard.cards.estimates', 1) : $t('dashboard.cards.estimates', 2))"
|
||||||
>
|
>
|
||||||
{{ dashboardStore.estimateCount }}
|
{{ dashboardStore.estimateCount }}
|
||||||
</DashboardStatsItem>
|
</DashboardStatsItem>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
:icon-component="PaymentIcon"
|
:icon-component="PaymentIcon"
|
||||||
:loading="!globalStore.getDashboardDataLoaded"
|
:loading="!globalStore.getDashboardDataLoaded"
|
||||||
:route="{ name: 'payments.dashboard' }"
|
:route="{ name: 'payments.dashboard' }"
|
||||||
:label="$t('dashboard.cards.payments')"
|
:label="(dashboardStore.paymentCount <= 1 ? $t('dashboard.cards.payments', 1 ) : $t('dashboard.cards.payments', 2))"
|
||||||
>
|
>
|
||||||
{{ dashboardStore.paymentCount }}
|
{{ dashboardStore.paymentCount }}
|
||||||
</DashboardStatsItem>
|
</DashboardStatsItem>
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
<template #cell-paid_status="{ row }">
|
<template #cell-paid_status="{ row }">
|
||||||
<BasePaidStatusBadge :status="row.data.paid_status">
|
<BasePaidStatusBadge :status="row.data.paid_status">
|
||||||
{{ row.data.paid_status }}
|
<BaseInvoiceStatusLabel :status="row.data.paid_status" />
|
||||||
</BasePaidStatusBadge>
|
</BasePaidStatusBadge>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #cell-status="{ row }">
|
<template #cell-status="{ row }">
|
||||||
<BaseEstimateStatusBadge :status="row.data.status" class="px-3 py-1">
|
<BaseEstimateStatusBadge :status="row.data.status" class="px-3 py-1">
|
||||||
{{ row.data.status }}
|
<BaseEstimateStatusLabel :status="row.data.status" />
|
||||||
</BaseEstimateStatusBadge>
|
</BaseEstimateStatusBadge>
|
||||||
</template>
|
</template>
|
||||||
<template #cell-total="{ row }">
|
<template #cell-total="{ row }">
|
||||||
|
|||||||
@@ -108,7 +108,7 @@
|
|||||||
|
|
||||||
<template #cell-status="{ row }">
|
<template #cell-status="{ row }">
|
||||||
<BaseEstimateStatusBadge :status="row.data.status" class="px-3 py-1">
|
<BaseEstimateStatusBadge :status="row.data.status" class="px-3 py-1">
|
||||||
{{ row.data.status }}
|
<BaseEstimateStatusLabel :status="row.data.status" />
|
||||||
</BaseEstimateStatusBadge>
|
</BaseEstimateStatusBadge>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -156,12 +156,12 @@ let showFilters = ref(false)
|
|||||||
let isFetchingInitialData = ref(true)
|
let isFetchingInitialData = ref(true)
|
||||||
|
|
||||||
const status = ref([
|
const status = ref([
|
||||||
'DRAFT',
|
{label: t('estimates.draft'), value: 'DRAFT'},
|
||||||
'SENT',
|
{label: t('estimates.sent'), value: 'SENT'},
|
||||||
'VIEWED',
|
{label: t('estimates.viewed'), value: 'VIEWED'},
|
||||||
'EXPIRED',
|
{label: t('estimates.expired'), value: 'EXPIRED'},
|
||||||
'ACCEPTED',
|
{label: t('estimates.accepted'), value: 'ACCEPTED'},
|
||||||
'REJECTED',
|
{label: t('estimates.rejected'), value: 'REJECTED'},
|
||||||
])
|
])
|
||||||
const filters = reactive({
|
const filters = reactive({
|
||||||
status: '',
|
status: '',
|
||||||
@@ -240,7 +240,7 @@ function toggleFilter() {
|
|||||||
|
|
||||||
async function fetchData({ page, sort }) {
|
async function fetchData({ page, sort }) {
|
||||||
let data = {
|
let data = {
|
||||||
status: filters.status,
|
status: filters.status.value,
|
||||||
estimate_number: filters.estimate_number,
|
estimate_number: filters.estimate_number,
|
||||||
from_date: filters.from_date,
|
from_date: filters.from_date,
|
||||||
to_date: filters.to_date,
|
to_date: filters.to_date,
|
||||||
|
|||||||
@@ -170,7 +170,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<BaseEstimateStatusBadge :status="estimate.status">
|
<BaseEstimateStatusBadge :status="estimate.status">
|
||||||
{{ estimate.status }}
|
<BaseEstimateStatusLabel :status="estimate.status" />
|
||||||
</BaseEstimateStatusBadge>
|
</BaseEstimateStatusBadge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@
|
|||||||
|
|
||||||
<template #cell-status="{ row }">
|
<template #cell-status="{ row }">
|
||||||
<BaseInvoiceStatusBadge :status="row.data.status" class="px-3 py-1">
|
<BaseInvoiceStatusBadge :status="row.data.status" class="px-3 py-1">
|
||||||
{{ row.data.status }}
|
<BaseInvoiceStatusLabel :status="row.data.status" />
|
||||||
</BaseInvoiceStatusBadge>
|
</BaseInvoiceStatusBadge>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
:status="row.data.paid_status"
|
:status="row.data.paid_status"
|
||||||
class="px-3 py-1"
|
class="px-3 py-1"
|
||||||
>
|
>
|
||||||
{{ row.data.paid_status }}
|
<BaseInvoiceStatusLabel :status="row.data.paid_status" />
|
||||||
</BaseInvoiceStatusBadge>
|
</BaseInvoiceStatusBadge>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -160,7 +160,13 @@ const route = useRoute()
|
|||||||
const table = ref(null)
|
const table = ref(null)
|
||||||
let isFetchingInitialData = ref(true)
|
let isFetchingInitialData = ref(true)
|
||||||
let showFilters = ref(false)
|
let showFilters = ref(false)
|
||||||
const status = ref(['DRAFT', 'DUE', 'SENT', 'VIEWED', 'COMPLETED'])
|
const status = ref([
|
||||||
|
{label: t('general.draft'), value: 'DRAFT'},
|
||||||
|
{label: t('general.due'), value: 'DUE'},
|
||||||
|
{label: t('general.sent'), value: 'SENT'},
|
||||||
|
{label: t('invoices.viewed'), value: 'VIEWED'},
|
||||||
|
{label: t('invoices.completed'), value: 'COMPLETED'}
|
||||||
|
])
|
||||||
const filters = reactive({
|
const filters = reactive({
|
||||||
status: '',
|
status: '',
|
||||||
from_date: '',
|
from_date: '',
|
||||||
@@ -247,7 +253,7 @@ function toggleFilter() {
|
|||||||
|
|
||||||
async function fetchData({ page, sort }) {
|
async function fetchData({ page, sort }) {
|
||||||
let data = {
|
let data = {
|
||||||
status: filters.status,
|
status: filters.status.value,
|
||||||
invoice_number: filters.invoice_number,
|
invoice_number: filters.invoice_number,
|
||||||
from_date: filters.from_date,
|
from_date: filters.from_date,
|
||||||
to_date: filters.to_date,
|
to_date: filters.to_date,
|
||||||
|
|||||||
@@ -175,7 +175,7 @@
|
|||||||
{{ invoice.invoice_number }}
|
{{ invoice.invoice_number }}
|
||||||
</div>
|
</div>
|
||||||
<BaseInvoiceStatusBadge :status="invoice.status">
|
<BaseInvoiceStatusBadge :status="invoice.status">
|
||||||
{{ invoice.status }}
|
<BaseInvoiceStatusLabel :status="invoice.status" />
|
||||||
</BaseInvoiceStatusBadge>
|
</BaseInvoiceStatusBadge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
{!! $data['body'] !!}
|
{!! $data['body'] !!}
|
||||||
@if(!$data['attach']['data'])
|
@if(!$data['attach']['data'])
|
||||||
@component('mail::button', ['url' => $data['url']])
|
@component('mail::button', ['url' => $data['url']])
|
||||||
View Estimate
|
@lang('mail_view_estimate')
|
||||||
@endcomponent
|
@endcomponent
|
||||||
@endif
|
@endif
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
{!! $data['body'] !!}
|
{!! $data['body'] !!}
|
||||||
@if(!$data['attach']['data'])
|
@if(!$data['attach']['data'])
|
||||||
@component('mail::button', ['url' => $data['url']])
|
@component('mail::button', ['url' => $data['url']])
|
||||||
View Invoice
|
@lang('mail_view_invoice')
|
||||||
@endcomponent
|
@endcomponent
|
||||||
@endif
|
@endif
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
{!! $data['body'] !!}
|
{!! $data['body'] !!}
|
||||||
@if(!$data['attach']['data'])
|
@if(!$data['attach']['data'])
|
||||||
@component('mail::button', ['url' => $data['url']])
|
@component('mail::button', ['url' => $data['url']])
|
||||||
View Payment
|
@lang('mail_view_payment')
|
||||||
@endcomponent
|
@endcomponent
|
||||||
@endif
|
@endif
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
@component('mail::message')
|
@component('mail::message')
|
||||||
{{ $data['user']['name'] }} viewed this Estimate.
|
@lang('mail_viewed_estimate', ['name' => $data['user']['name']])
|
||||||
|
|
||||||
@component('mail::button', ['url' => url('/admin/estimates/'.$data['estimate']['id'].'/view')])
|
@component('mail::button', ['url' => url('/admin/estimates/'.$data['estimate']['id'].'/view')])@lang('mail_view_estimate')
|
||||||
View Estimate
|
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|
||||||
Thanks,<br>
|
@lang('mail_thanks'),<br>
|
||||||
{{ config('app.name') }}
|
{{ config('app.name') }}
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
@component('mail::message')
|
@component('mail::message')
|
||||||
{{ $data['user']['name'] }} viewed this Invoice.
|
@lang('mail_viewed_invoice', ['name' => $data['user']['name']])
|
||||||
|
|
||||||
@component('mail::button', ['url' => url('/admin/invoices/'.$data['invoice']['id'].'/view')])
|
@component('mail::button', ['url' => url('/admin/invoices/'.$data['invoice']['id'].'/view')])@lang('mail_view_invoice')
|
||||||
View Invoice
|
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|
||||||
Thanks,<br>
|
@lang('mail_thanks'),<br>
|
||||||
{{ config('app.name') }}
|
{{ config('app.name') }}
|
||||||
@endcomponent
|
@endcomponent
|
||||||
|
|||||||
@@ -164,6 +164,10 @@ Route::prefix('/v1')->group(function () {
|
|||||||
|
|
||||||
Route::post('/wizard-step', [OnboardingWizardController::class, 'updateStep']);
|
Route::post('/wizard-step', [OnboardingWizardController::class, 'updateStep']);
|
||||||
|
|
||||||
|
Route::post('/wizard-language', [OnboardingWizardController::class, 'saveLanguage']);
|
||||||
|
|
||||||
|
Route::get('/languages', [LanguagesController::class, 'languages']);
|
||||||
|
|
||||||
Route::get('/requirements', [RequirementsController::class, 'requirements']);
|
Route::get('/requirements', [RequirementsController::class, 'requirements']);
|
||||||
|
|
||||||
Route::get('/permissions', [FilePermissionsController::class, 'permissions']);
|
Route::get('/permissions', [FilePermissionsController::class, 'permissions']);
|
||||||
|
|||||||
Reference in New Issue
Block a user