Fix Invoice TS

This commit is contained in:
Thomas Peterson 2026-02-16 18:10:23 +01:00
parent 9937165710
commit be27d4b6f0
17 changed files with 363 additions and 218 deletions

View File

@ -7,6 +7,7 @@ use PSC\Shop\OrderBundle\Service\Order;
use PSC\System\SettingsBundle\Service\Instance;
use PSC\System\SettingsBundle\Service\Shop;
use PSC\System\SettingsBundle\Service\Token;
use PSC\System\SettingsBundle\Service\Version;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
@ -21,7 +22,8 @@ return static function (ContainerConfigurator $containerConfigurator): void {
'shopService' => service(Shop::class),
'orderService' => service(Order::class),
'tokenService' => service(Token::class),
'mediaService' => service(MediaManager::class)
'mediaService' => service(MediaManager::class),
'versionService' => service(Version::class)
]
]
);

View File

@ -22,16 +22,16 @@ use PSC\Shop\ProductBundle\Model\Lang\Item;
class Product
{
#[OA\Property(type: 'string')]
private string $title = "";
private string $title = '';
#[OA\Property(type: 'string')]
private string $uuid = "";
private string $uuid = '';
#[OA\Property(type: 'string')]
private string $nrIntern = "";
private string $nrIntern = '';
#[OA\Property(type: 'string')]
private string $nrExtern = "";
private string $nrExtern = '';
#[OA\Property(type: 'integer')]
private int $uid = 0;
@ -40,7 +40,7 @@ class Product
private ?IProductTypeObject $specialProductTypeObject = null;
#[OA\Property(type: 'string')]
private string $shopUuid = "";
private string $shopUuid = '';
#[OA\Property(ref: new Model(type: Media::class))]
private ?Media $image1 = null;
@ -73,34 +73,34 @@ class Product
private ?OriginalProduct $originalProduct = null;
#[OA\Property(type: 'string')]
private string $custom1 = "";
private string $custom1 = '';
#[OA\Property(type: 'string')]
private string $custom2 = "";
private string $custom2 = '';
#[OA\Property(type: 'string')]
private string $custom3 = "";
private string $custom3 = '';
#[OA\Property(type: 'string')]
private string $custom4 = "";
private string $custom4 = '';
#[OA\Property(type: 'string')]
private string $custom5 = "";
private string $custom5 = '';
#[OA\Property(type: 'string')]
private string $custom6 = "";
private string $custom6 = '';
#[OA\Property(type: 'string')]
private string $custom7 = "";
private string $custom7 = '';
#[OA\Property(type: 'string')]
private string $custom8 = "";
private string $custom8 = '';
#[OA\Property(type: 'string')]
private string $custom9 = "";
private string $custom9 = '';
#[OA\Property(type: 'string')]
private string $custom10 = "";
private string $custom10 = '';
public function getTitle(): string
{

View File

@ -1,107 +1,90 @@
{% extends 'backend_base.html.twig' %}
{% extends 'backend_tailwind_base.html.twig' %}
{% block header %}
<div class="flex flex-wrap items-center gap-4 justify-between w-full">
<div>
<h1 class="text-psc text-2xl font-medium flex flex-row gap-1">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-8">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.25 6.087c0-.355.186-.676.401-.959.221-.29.349-.634.349-1.003 0-1.036-1.007-1.875-2.25-1.875s-2.25.84-2.25 1.875c0 .369.128.713.349 1.003.215.283.401.604.401.959v0a.64.64 0 01-.657.643 48.39 48.39 0 01-4.163-.3c.186 1.613.293 3.25.315 4.907a.656.656 0 01-.658.663v0c-.355 0-.676-.186-.959-.401a1.647 1.647 0 00-1.003-.349c-1.036 0-1.875 1.007-1.875 2.25s.84 2.25 1.875 2.25c.369 0 .713-.128 1.003-.349.283-.215.604-.401.959-.401v0c.31 0 .555.26.532.57a48.039 48.039 0 01-.642 5.056c1.518.19 3.058.309 4.616.354a.64.64 0 00.657-.643v0c0-.355-.186-.676-.401-.959a1.647 1.647 0 01-.349-1.003c0-1.035 1.008-1.875 2.25-1.875 1.243 0 2.25.84 2.25 1.875 0 .369-.128.713-.349 1.003-.215.283-.401.604-.401.959v0c0 .333.277.599.61.58a48.1 48.1 0 005.427-.63 48.05 48.05 0 00.582-4.717.532.532 0 00-.533-.57v0c-.355 0-.676.186-.959.401-.29.221-.634.349-1.003.349-1.035 0-1.875-1.007-1.875-2.25s.84-2.25 1.875-2.25c.37 0 .713.128 1.003.349.283.215.604.401.959.401v0a.656.656 0 00.658-.663 48.422 48.422 0 00-.37-5.36c-1.886.342-3.81.574-5.766.689a.578.578 0 01-.61-.58v0z" />
</svg>
Apps <span class="text-gray-500">Liste</span>
</h1>
</div>
<div class="flex flex-wrap items-center gap-4 justify-end shrink-0 ml-auto">
<a href="{{ path('psc_system_plugin_backend_clear_cache') }}" class="inline-flex items-center justify-center py-1 gap-1 font-medium rounded-md px-4 text-sm text-white shadow-lg bg-gray-500 hover:bg-gray-600 hover:ring-2 hover:ring-gray-500 hover:ring-offset-2 min-h-[2.25rem]">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="button-icon">
<path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182M2.985 19.644l3.181-3.182" />
</svg>
Clear Cache
</a>
</div>
</div>
{% endblock %}
{% block body %}
<div class="header">
<div class="row">
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6">
<h3>
<i class="fab fa-app-store"></i>
App <span>>
Liste </span>
</h3>
</div>
<div class="col-xs-6 col-sm-6 col-md-6 col-lg-6 text-end">
<a href="{{ path('psc_system_plugin_backend_clear_cache') }}" class="btn btn-default btn-sm">Clear Cache</a>
</div>
</div>
</div>
<div class="body">
<div class="panel">
<div class="body">
<table class="table table-striped table-sm">
<thead class="">
<tr>
<th>Name</th>
<th>Version</th>
<th>Pfad</th>
<th>Aktiviert?</th>
<th></th>
<th></th>
<div class="flex flex-col gap-6">
<div class="rounded-md border bg-white px-7.5 py-6 shadow-lg dark:border-strokedark dark:bg-boxdark">
<div class="overflow-x-auto">
<table class="min-w-full text-sm">
<thead class="bg-slate-50 dark:bg-gray-800">
<tr class="border-b-2 border-gray-200 dark:border-gray-700">
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Name</th>
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Version</th>
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Pfad</th>
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Status</th>
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Beschreibung</th>
<th class="px-4 py-4 text-right text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Aktionen</th>
</tr>
</thead>
<tbody>
<tr>
<td><b>PrintshopCreator App (Core)</b></td>
<td>{{ version.datum }} ({{ version.release }})</td>
<td></td>
<td><span class="badge bg-success">Ja</span></td>
<td>
</td>
<td><button type="button" class="btn btn-success btn-sm" data-bs-toggle="modal" data-bs-target="#upgradeApp">Update installieren</button>
</td>
</tr>
<tr class="divider"><td colspan="6"></td></tr>
</thead>
<tbody class="bg-white dark:bg-boxdark">
{# Core App Row #}
<tr class="border-t border-gray-100 hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800/50 transition-colors">
<td class="px-4 py-3 font-medium text-gray-900 dark:text-gray-100">PrintshopCreator App (Core)</td>
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ version.datum }} ({{ version.release }})</td>
<td class="px-4 py-3 text-gray-500 dark:text-gray-400">-</td>
<td class="px-4 py-3">
<span class="badge-yes">Ja</span>
</td>
<td class="px-4 py-3 text-gray-500 dark:text-gray-400">Kernsystem</td>
<td class="px-4 py-3 text-right"></td>
</tr>
{# Plugin Rows #}
{% for plugin in plugins %}
<tr {% if loop.index is odd %}class="color"{% endif %}>
<td><b>{{ plugin.name }}</b></td>
<td>{{ plugin.version }}</td>
<td>{{ plugin.path }}</td>
<td>{% if plugin.installed and plugin.shouldBeDeInstalled == false %}<span class="badge bg-success">Ja</span>{% else %}<span class="badge bg-warning">Nein</span>{% endif %}</td>
<td>
<tr class="border-t border-gray-100 hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800/50 transition-colors">
<td class="px-4 py-3 font-medium text-gray-900 dark:text-gray-100">{{ plugin.name }}</td>
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ plugin.version }}</td>
<td class="px-4 py-3 text-gray-500 dark:text-gray-400 font-mono text-xs">{{ plugin.path }}</td>
<td class="px-4 py-3">
{% if plugin.installed and plugin.shouldBeDeInstalled == false %}
<a href="{{ path("psc_system_plugin_backend_list_disable", {uuid: plugin.id}) }}" class="btn btn-warning btn-sm"><span class="fa fa-edit"></span> Deaktivieren</a>
<span class="badge-yes">Ja</span>
{% else %}
<a href="{{ path("psc_system_plugin_backend_list_enable", {uuid: plugin.id}) }}" class="btn btn-info btn-sm"><span class="fa fa-edit"></span> Aktivieren</a>
<span class="badge-no">Nein</span>
{% endif %}
</td>
<td></td>
<td class="px-4 py-3 text-gray-500 dark:text-gray-400 text-xs">{{ plugin.description }}</td>
<td class="px-4 py-3 text-right">
<div class="flex flex-row gap-2 justify-end">
{% if plugin.installed and plugin.shouldBeDeInstalled == false %}
<a href="{{ path("psc_system_plugin_backend_list_disable", {uuid: plugin.id}) }}" title="Deaktivieren">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="table-icon text-yellow-600 hover:text-yellow-700 dark:text-yellow-500 dark:hover:text-yellow-400">
<path stroke-linecap="round" stroke-linejoin="round" d="M5.636 5.636a9 9 0 1012.728 0M12 3v9" />
</svg>
</a>
{% else %}
<a href="{{ path("psc_system_plugin_backend_list_enable", {uuid: plugin.id}) }}" title="Aktivieren">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="table-icon text-green-600 hover:text-green-700 dark:text-green-500 dark:hover:text-green-400">
<path stroke-linecap="round" stroke-linejoin="round" d="M5.636 5.636a9 9 0 1012.728 0M12 3v9" />
</svg>
</a>
{% endif %}
</div>
</td>
</tr>
<tr><td colspan="6">{{ plugin.description }}</td></tr>
<tr class="divider"><td colspan="6"></td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="modal fade" id="upgradeApp" tabindex="-1" role="dialog" aria-labelledby="upgradeApp" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">PrintshopCreator App (Core) Update</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p> Wenn Sie diese Funktions ausführen, wird der Server neu gestartet.
Das BackOffice sowie alle Shops sind für bis zu 5 Minuten nicht erreichbar.
Nach dem Neustart müssen Sie sich neu in das BackOffice einloggen.<br/>
In den Systemeinstellungen > Wartungsankündigung können Sie Ihren Kunden optional eine Wartungsankündigung einblenden lassen.</p>
</div>
<div class="modal-footer">
<h5>Jetzt ausführen?</h5>
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Nein</button>
<button type="button" class="upgrade btn btn-primary">Ja</button>
</div>
</div>
</div>
</tbody>
</table>
</div>
</div>
{% endblock %}
{% block javascripts %}
{{ parent() }}
<script>
window.addEventListener("load", (event) => {
document.querySelector('.upgrade').addEventListener("click", (event) => {
fetch('{{ path('psc_backend_system_settings_upgrade') }}').then((result) => {
document.location='{{ path('psc_backend_login') }}';
});
})
});
</script>
</div>
{% endblock %}

View File

@ -0,0 +1,21 @@
<?php
namespace PSC\System\SettingsBundle\Controller\Backend;
use PSC\System\SettingsBundle\Service\Version;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Attribute\Route;
#[Route(path: '/backend/system/version')]
class VersionController extends AbstractController
{
#[Route(path: '/changelog', name: 'psc_system_version_backend_changelog')]
#[Template('@PSCSystemSettings/backend/version/changelog.html.twig')]
public function changelogAction(Version $versionService): array
{
return [
'version' => $versionService,
];
}
}

View File

@ -0,0 +1,56 @@
{% extends 'backend_tailwind_base.html.twig' %}
{% block header %}
<div class="flex flex-wrap items-center gap-4 justify-between w-full">
<div>
<h1 class="text-psc text-2xl font-medium flex flex-row gap-1">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-8">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25" />
</svg>
Changelog <span class="text-gray-500">v{{ version.release }}</span>
</h1>
</div>
</div>
{% endblock %}
{% block body %}
<div class="flex flex-col gap-6">
<div class="rounded-md border bg-white px-7.5 py-6 shadow-lg dark:border-strokedark dark:bg-boxdark">
<div class="overflow-x-auto">
<table class="min-w-full text-sm">
<thead class="bg-slate-50 dark:bg-gray-800">
<tr class="border-b-2 border-gray-200 dark:border-gray-700">
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Version</th>
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Datum</th>
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Änderungen</th>
</tr>
</thead>
<tbody class="bg-white dark:bg-boxdark">
{% for entry in version.changelog %}
<tr class="border-t border-gray-100 hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800/50 transition-colors align-top">
<td class="px-4 py-3">
<span class="inline-flex items-center px-2.5 py-1 rounded-md text-xs font-mono font-medium bg-psc-50 text-psc-700 border border-psc-200 dark:bg-psc-900 dark:text-psc-300 dark:border-psc-700">
v{{ entry.version }}
</span>
</td>
<td class="px-4 py-3 text-gray-900 dark:text-gray-100 whitespace-nowrap">{{ entry.datum }}</td>
<td class="px-4 py-3">
<ul class="space-y-1">
{% for change in entry.changes %}
<li class="flex items-start gap-2 text-gray-700 dark:text-gray-300">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-4 h-4 mt-0.5 shrink-0 text-psc-500">
<path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5" />
</svg>
{{ change }}
</li>
{% endfor %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,40 @@
<?php
namespace PSC\System\SettingsBundle\Service;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Yaml\Yaml;
class Version
{
private ?array $data = null;
public function __construct(
private readonly KernelInterface $kernel,
) {}
private function load(): void
{
if ($this->data === null) {
$this->data = Yaml::parse(file_get_contents($this->kernel->getProjectDir() . '/version.yaml'));
}
}
public function getRelease(): string
{
$this->load();
return $this->data['info']['release'] ?? '';
}
public function getDatum(): string
{
$this->load();
return $this->data['info']['datum'] ?? '';
}
public function getChangelog(): array
{
$this->load();
return $this->data['changelog'] ?? [];
}
}

View File

@ -52,6 +52,11 @@
<hr/>
{% endif %}
<p class="text-center text-psc">{{ date("now")|date('d.m.Y H:i:s') }}</p>
<p class="mt-1 text-center">
<a href="{{ path('psc_system_version_backend_changelog') }}" class="text-xs text-gray-400 hover:text-psc-500 transition-colors">
v{{ versionService.release }} ({{ versionService.datum }})
</a>
</p>
</nav>
</aside>
<div x-data :class="{'lg:pl-[var(--collapsed-sidebar-width)] rtl:lg:pr-[var(--collapsed-sidebar-width)]': ! $store.sideBar.isOpen,' lg:pl-[var(--sidebar-width)] rtl:lg:pr-[var(--sidebar-width)]': $store.sideBar.isOpen,}" class="flex-col gap-y-6 w-screen flex-1 rtl:lg:pl-0 h-full transition-all" style="display: flex">

View File

@ -1,4 +1,5 @@
<?php
namespace PSC\Component\ApiBundle\Api\System;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
@ -13,6 +14,6 @@ class VersionTest extends WebTestCase
$this->assertResponseIsSuccessful();
$data = json_decode($client->getResponse()->getContent(), true);
$this->assertSame("2.3", $data['release']);
$this->assertSame('2.3.2', $data['release']);
}
}

View File

@ -1 +1,4 @@
{% if position.product.specialProductTypeObject.typ == 9 %}
<h4>Gutscheincode: {{ position.product.specialProductTypeObject.voucherCode }}</h4>
{% endif %}

View File

@ -27,7 +27,6 @@ class ButtonComponent extends Component<{ loadOrder }, { disabled: boolean, savi
&& order.payment.title != ""
&& order.shipping.title != ""
&& order.shop.name != ""
&& order.account.title != ""
&& order.invoiceAddress.uuid != ""
&& order.type != 0
) {

View File

@ -1,7 +1,7 @@
import { useEffect, useState } from 'react'
import NiceModal, { useModal, bootstrapDialog } from "@ebay/nice-modal-react"
import Button from '../base/Button'
import {RJSFSchema} from "@rjsf/utils"
import { RJSFSchema } from "@rjsf/utils"
import validator from "@rjsf/validator-ajv6"
import Form from "@rjsf/core"
import CountryService from '../../services/country'
@ -19,7 +19,7 @@ const Addressdiv = NiceModal.create(
const [schema, setSchema] = useState<RJSFSchema>({})
useEffect(() => {
if(address) {
if (address) {
setFormData({
email: address.email,
firstname: address.firstname,
@ -34,14 +34,14 @@ const Addressdiv = NiceModal.create(
ustid: address.ustid
})
}
}, [address])
}, [address])
useEffect(() => {
country_api.getCountry(shop).then(( data ) => {
country_api.getCountry(shop).then((data) => {
var countrys: array = [];
data.forEach((item) => {
countrys.push({'title': item.code, 'const': item.code})
countrys.push({ 'title': item.code, 'const': item.code })
})
var schema: RJSFSchema = {
@ -50,16 +50,16 @@ const Addressdiv = NiceModal.create(
required: ['email'],
properties: {
email: { type: 'string', format: 'email', title: 'E-Mail' },
company: { type: 'string', title: 'Company'},
firstname: { type: 'string', title: 'Firstname'},
lastname: { type: 'string', title: 'Lastname'},
street: { type: 'string', title: 'Street'},
houseNumber: { type: 'string', title: 'Housenumber'},
zip: { type: 'string', title: 'Zip'},
city: { type: 'string', title: 'City'},
phone: { type: 'string', title: 'Phone'},
ustid: { type: 'string', title: 'UstId'},
country: { type: 'string', title: 'Country', oneOf: countrys}
company: { type: 'string', title: 'Company' },
firstname: { type: 'string', title: 'Firstname' },
lastname: { type: 'string', title: 'Lastname' },
street: { type: 'string', title: 'Street' },
houseNumber: { type: 'string', title: 'Housenumber' },
zip: { type: 'string', title: 'Zip' },
city: { type: 'string', title: 'City' },
phone: { type: 'string', title: 'Phone' },
ustid: { type: 'string', title: 'UstId' },
country: { type: 'string', title: 'Country', oneOf: countrys }
}
};
@ -113,13 +113,6 @@ const Addressdiv = NiceModal.create(
}
}}
/>
<Button
type={4}
variant="warning"
onClick={() => {
modal.remove()
}}
/>
</Modal.Footer>
</Modal>
)

View File

@ -2,31 +2,31 @@ import * as React from 'react'
import * as PropTypes from 'prop-types'
import ContactSelect from './ContactSelect'
import AddressSelect from './AddressSelect'
import {Contact} from '../../model/contact'
import {Address} from '../../model/address'
import {useEffect, useState} from 'react'
import { Contact } from '../../model/contact'
import { Address } from '../../model/address'
import { useEffect, useState } from 'react'
import OrderState from '../../state/order'
import {container} from "tsyringe-neo"
import { container } from "tsyringe-neo"
import AccountSelectComponent from '../account/AccountSelectComponent'
import Order from '../../model/order'
import { Shop } from '../../model/shop'
const ContactComponent = ({order, shop}) => {
const ContactComponent = ({ order, shop }) => {
let orderState = container.resolve(OrderState)
const [contact, setContact] = useState<Contact>(new Contact())
const changeAddress = (address: Address, type: Number) => {
if(type == 1) {
if (type == 1) {
orderState.getCurrentOrder().value.invoiceAddress = address
order.invoiceAddress = address
}
if(type == 2) {
if (type == 2) {
orderState.getCurrentOrder().value.deliveryAddress = address
order.deliveryAddress = address
}
if(type == 3) {
if (type == 3) {
orderState.getCurrentOrder().value.senderAddress = address
order.senderAddress = address
}
@ -49,14 +49,9 @@ const ContactComponent = ({order, shop}) => {
onChange={setContact}
/>
</div>
<div>
<AccountSelectComponent
shop={shop} order={order}
/>
</div>
</div>
{ order.contact.uuid != "" && (
{order.contact.uuid != "" && (
<>
<h3 className="text-base font-medium mb-2 text-gray-700 dark:text-gray-200 flex items-center gap-2">
<svg className="w-5 h-5 text-green-600 dark:text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">

View File

@ -1,8 +1,8 @@
import { useEffect, useState } from 'react';
import NiceModal, { useModal, bootstrapDialog } from "@ebay/nice-modal-react";
import Button from '../base/Button'
import {RJSFSchema} from "@rjsf/utils";
import {Contact} from "../../model/contact";
import { RJSFSchema } from "@rjsf/utils";
import { Contact } from "../../model/contact";
import validator from "@rjsf/validator-ajv6";
import Form from "@rjsf/core";
import CountryService from "../../services/country";
@ -21,7 +21,7 @@ const ContactModal = NiceModal.create(
useEffect(() => {
if(contact.uid != "") {
if (contact.uid != "") {
setFormData({
email: contact.username,
firstname: contact.layouter_data.firstname,
@ -36,7 +36,7 @@ const ContactModal = NiceModal.create(
ustid: contact.layouter_data.ustid
});
}
}, [contact]);
}, [contact]);
const uiSchema: RJSFSchema = {
"ui:submitButtonOptions": {
@ -50,11 +50,11 @@ const ContactModal = NiceModal.create(
};
useEffect(() => {
country_api.getCountry(shop).then(( data ) => {
country_api.getCountry(shop).then((data) => {
var countrys = [];
data.forEach((item) => {
countrys.push({'title': item.code, 'const': item.code})
countrys.push({ 'title': item.code, 'const': item.code })
})
var schema: RJSFSchema = {
@ -63,16 +63,16 @@ const ContactModal = NiceModal.create(
required: ['email'],
properties: {
email: { type: 'string', format: 'email', title: 'E-Mail' },
company: { type: 'string', title: 'Company'},
firstname: { type: 'string', title: 'Firstname'},
lastname: { type: 'string', title: 'Lastname'},
street: { type: 'string', title: 'Street'},
houseNumber: { type: 'string', title: 'Housenumber'},
zip: { type: 'string', title: 'Zip'},
city: { type: 'string', title: 'City'},
phone: { type: 'string', title: 'Phone'},
ustid: { type: 'string', title: 'UstId'},
country: { type: 'string', title: 'Country', oneOf: countrys}
company: { type: 'string', title: 'Company' },
firstname: { type: 'string', title: 'Firstname' },
lastname: { type: 'string', title: 'Lastname' },
street: { type: 'string', title: 'Street' },
houseNumber: { type: 'string', title: 'Housenumber' },
zip: { type: 'string', title: 'Zip' },
city: { type: 'string', title: 'City' },
phone: { type: 'string', title: 'Phone' },
ustid: { type: 'string', title: 'UstId' },
country: { type: 'string', title: 'Country', oneOf: countrys }
}
};
@ -104,7 +104,7 @@ const ContactModal = NiceModal.create(
variant="success"
onClick={() => {
if (action === "Save") {
if (formData) {
if (formData) {
modal.resolve(formData);
modal.remove();
}
@ -114,13 +114,6 @@ const ContactModal = NiceModal.create(
}
}}
/>
<Button
type={4}
variant="warning"
onClick={() => {
modal.remove();
}}
/>
</Modal.Footer>
</Modal>
);

File diff suppressed because one or more lines are too long

View File

@ -2,6 +2,6 @@
<a href="/apps/backend/component/invoice/index/create#/{{ uuid }}" target="_blank" class="btn btn-warning btn-sm">Auftrag bearbeiten (BETA)</a>
{% else %}
<div class="panel">
<div class="body"><a href="/apps/backend/component/invoice/index/create" target="_blank" class="btn btn-warning btn-sm">Auftrag anlegen (BETA)</a></div>
<div class="body"><a href="/apps/backend/component/invoice/index/create" target="_blank" class="inline-flex items-center justify-center py-1 gap-1 font-medium rounded-sm px-4 text-sm text-white shadow-lg bg-indigo-500 hover:bg-indigo-600 hover:ring-2 hover:ring-indigo-500 hover:ring-offset-2 min-h-[2.25rem]">Auftrag anlegen (BETA)</a></div>
</div>
{% endif %}

View File

@ -1760,6 +1760,11 @@ html {
border-color: rgb(209 213 219 / var(--tw-border-opacity));
}
.border-psc-200{
--tw-border-opacity: 1;
border-color: rgb(226 128 119 / var(--tw-border-opacity));
}
.border-psc-500{
--tw-border-opacity: 1;
border-color: rgb(234 100 27 / var(--tw-border-opacity));
@ -1849,6 +1854,11 @@ html {
background-color: rgb(101 163 13 / var(--tw-bg-opacity));
}
.bg-psc-50{
--tw-bg-opacity: 1;
background-color: rgb(238 180 175 / var(--tw-bg-opacity));
}
.bg-psc-500{
--tw-bg-opacity: 1;
background-color: rgb(234 100 27 / var(--tw-bg-opacity));
@ -2082,6 +2092,10 @@ html {
text-align: end;
}
.align-top{
vertical-align: top;
}
.font-mono{
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
@ -2229,6 +2243,11 @@ html {
color: rgb(172 48 37 / var(--tw-text-opacity));
}
.text-psc-700{
--tw-text-opacity: 1;
color: rgb(144 40 31 / var(--tw-text-opacity));
}
.text-purple-600{
--tw-text-opacity: 1;
color: rgb(147 51 234 / var(--tw-text-opacity));
@ -3139,6 +3158,11 @@ html {
border-color: rgb(55 65 81 / var(--tw-border-opacity));
}
:is(.dark .dark\:border-psc-700){
--tw-border-opacity: 1;
border-color: rgb(144 40 31 / var(--tw-border-opacity));
}
:is(.dark .dark\:border-red-500){
--tw-border-opacity: 1;
border-color: rgb(239 68 68 / var(--tw-border-opacity));
@ -3190,6 +3214,11 @@ html {
background-color: rgb(17 24 39 / 0.8);
}
:is(.dark .dark\:bg-psc-900){
--tw-bg-opacity: 1;
background-color: rgb(88 25 19 / var(--tw-bg-opacity));
}
:is(.dark .dark\:bg-red-100){
--tw-bg-opacity: 1;
background-color: rgb(254 226 226 / var(--tw-bg-opacity));
@ -3248,6 +3277,11 @@ html {
color: rgb(34 197 94 / var(--tw-text-opacity));
}
:is(.dark .dark\:text-psc-300){
--tw-text-opacity: 1;
color: rgb(220 102 91 / var(--tw-text-opacity));
}
:is(.dark .dark\:text-psc-400){
--tw-text-opacity: 1;
color: rgb(214 76 63 / var(--tw-text-opacity));

View File

@ -1,3 +1,23 @@
info:
datum: 03.02.2026
release: 2.3.2
changelog:
- version: 2.3.2
datum: 03.02.2026
changes:
- "VoucherBundle: CSV Upload für Gutscheincodes"
- "VoucherBundle: Vorschau vor Import"
- "Gutschein-Produkt: Verknüpfung mit VoucherBundle"
- "Plugin-Liste: Tailwind Redesign"
- "Kontakt-Liste: Tailwind Redesign"
- version: 2.3.1
datum: 15.01.2026
changes:
- "Bugfixes und Verbesserungen"
- version: 2.3.0
datum: 01.01.2026
changes:
- "Initiales Release"