Compare commits
84
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6da70e015
|
||
|
|
afead7fd61
|
||
|
|
69acbf708b
|
||
|
|
08ebfae030
|
||
|
|
a597839379
|
||
|
|
e0fe6a8622
|
||
|
|
5ebce653dc
|
||
|
|
61eb2404a2
|
||
|
|
e199dfccc7
|
||
|
|
1d0a2b09d5
|
||
|
|
1886257b63
|
||
|
|
eda1415e86
|
||
|
|
4e9c7f8c3c
|
||
|
|
eebf4aff00
|
||
|
|
6dae33507f
|
||
|
|
96d5aa2219
|
||
|
|
6c326b89e2
|
||
|
|
6c821d41b4
|
||
|
|
ade02f4736
|
||
|
|
bb5b510315
|
||
|
|
1267cb3d95
|
||
|
|
c7641b85e7
|
||
|
|
ee4b8e9d65
|
||
|
|
58d4f982e9
|
||
|
|
ad06cfaa58
|
||
|
|
aa2e0e9b4a
|
||
|
|
d1c926541a
|
||
|
|
9929e00a3f
|
||
|
|
bf415a2a46
|
||
|
|
c0bfa5b334
|
||
|
|
e122248a97
|
||
|
|
d2bb1d4936
|
||
|
|
b8a901b041
|
||
|
|
ede5c24a5d
|
||
|
|
0ae7040804
|
||
|
|
f370ccba88
|
||
|
|
a128168e7f
|
||
|
|
3e9c25f6fe
|
||
|
|
352311a82e
|
||
|
|
c97d80a724
|
||
|
|
532dbfd8d6
|
||
|
|
49f3a371e5
|
||
|
|
2bcaf13ee3
|
||
|
|
2fc5812eba
|
||
|
|
63ca6e7557
|
||
|
|
224cdc0eda
|
||
|
|
42da9eb778
|
||
|
|
d1dee27191
|
||
|
|
726b1818d0
|
||
|
|
75f0ae7668
|
||
|
|
b43ed72040
|
||
|
|
5dc4350b20
|
||
|
|
829588150a
|
||
|
|
54d901e45e
|
||
|
|
5e1692efdb
|
||
|
|
32733668ff
|
||
|
|
3034217ff8
|
||
|
|
c664b0a4bf
|
||
|
|
f397354c1e
|
||
|
|
e3992d9d55
|
||
|
|
0f7c9aa02f
|
||
|
|
b531589c52
|
||
|
|
dc824a0f70
|
||
|
|
1a06326589
|
||
|
|
9780aa62cb
|
||
|
|
cc3cfc15c8
|
||
|
|
a877484d56
|
||
|
|
da5c2121ba
|
||
|
|
73c7d8434e
|
||
|
|
3f7817fd1f
|
||
|
|
361671a362
|
||
|
|
b2babcf30f
|
||
|
|
ea579614b3
|
||
|
|
d8786e74d5
|
||
|
|
9e448e62c6
|
||
|
|
7f1177cc55
|
||
|
|
a941f5a1cd
|
||
|
|
ba5dfdbe4d
|
||
|
|
5557f00e57
|
||
|
|
baddc17b33
|
||
|
|
8d495c9f37
|
||
|
|
cc8f1e1ace
|
||
|
|
97e04d785c
|
||
|
|
0c102da1d7
|
No files matched your search
Vendored
+2
-2
@@ -35,7 +35,7 @@ pipeline {
|
|||||||
sh 'vendor/bin/phpunit --log-junit unit_test_results.xml --testdox tests'
|
sh 'vendor/bin/phpunit --log-junit unit_test_results.xml --testdox tests'
|
||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
success {
|
always {
|
||||||
archiveArtifacts 'unit_test_results.xml'
|
archiveArtifacts 'unit_test_results.xml'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ pipeline {
|
|||||||
sh 'php vendor/bin/phpstan analyse -c phpstan.neon --error-format=prettyJson > static_code_analysis_results.json'
|
sh 'php vendor/bin/phpstan analyse -c phpstan.neon --error-format=prettyJson > static_code_analysis_results.json'
|
||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
success {
|
always {
|
||||||
archiveArtifacts 'static_code_analysis_results.json'
|
archiveArtifacts 'static_code_analysis_results.json'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"esoko/soko-web": "0.8",
|
"esoko/soko-web": "0.13.1",
|
||||||
"firebase/php-jwt": "^6.4"
|
"firebase/php-jwt": "^6.4"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|||||||
Generated
+79
-4
@@ -4,17 +4,92 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "a89a42e04596ab159fc41abbd9390068",
|
"content-hash": "59130fbd82b1c81275666b16adb0c1a1",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "cocur/slugify",
|
||||||
|
"version": "v4.3.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/cocur/slugify.git",
|
||||||
|
"reference": "652234ef5f1be844a2ae1c36ad1b4c88b05160f9"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/cocur/slugify/zipball/652234ef5f1be844a2ae1c36ad1b4c88b05160f9",
|
||||||
|
"reference": "652234ef5f1be844a2ae1c36ad1b4c88b05160f9",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-mbstring": "*",
|
||||||
|
"php": "^7.1 || ~8.0.0 || ~8.1.0 || ~8.2.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/config": "<3.4 || >=4,<4.3",
|
||||||
|
"symfony/dependency-injection": "<3.4 || >=4,<4.3",
|
||||||
|
"symfony/http-kernel": "<3.4 || >=4,<4.3",
|
||||||
|
"twig/twig": "<2.12.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"laravel/framework": "^5.0|^6.0|^7.0|^8.0",
|
||||||
|
"latte/latte": "~2.2",
|
||||||
|
"league/container": "^2.2.0",
|
||||||
|
"mikey179/vfsstream": "~1.6.8",
|
||||||
|
"mockery/mockery": "^1.3",
|
||||||
|
"nette/di": "~2.4",
|
||||||
|
"pimple/pimple": "~1.1",
|
||||||
|
"plumphp/plum": "~0.1",
|
||||||
|
"symfony/config": "^3.4 || ^4.3 || ^5.0 || ^6.0",
|
||||||
|
"symfony/dependency-injection": "^3.4 || ^4.3 || ^5.0 || ^6.0",
|
||||||
|
"symfony/http-kernel": "^3.4 || ^4.3 || ^5.0 || ^6.0",
|
||||||
|
"symfony/phpunit-bridge": "^5.4 || ^6.0",
|
||||||
|
"twig/twig": "^2.12.1 || ~3.0",
|
||||||
|
"zendframework/zend-modulemanager": "~2.2",
|
||||||
|
"zendframework/zend-servicemanager": "~2.2",
|
||||||
|
"zendframework/zend-view": "~2.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Cocur\\Slugify\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Florian Eckerstorfer",
|
||||||
|
"email": "florian@eckerstorfer.co",
|
||||||
|
"homepage": "https://florian.ec"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ivo Bathke",
|
||||||
|
"email": "ivo.bathke@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Converts a string into a slug.",
|
||||||
|
"keywords": [
|
||||||
|
"slug",
|
||||||
|
"slugify"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/cocur/slugify/issues",
|
||||||
|
"source": "https://github.com/cocur/slugify/tree/v4.3.0"
|
||||||
|
},
|
||||||
|
"time": "2022-12-07T19:48:48+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "esoko/soko-web",
|
"name": "esoko/soko-web",
|
||||||
"version": "v0.8",
|
"version": "v0.13.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.esoko.eu/esoko/soko-web.git",
|
"url": "https://git.esoko.eu/esoko/soko-web.git",
|
||||||
"reference": "219b42f995b8e34432da4dde77e53e24b75d78dd"
|
"reference": "8bf495c89b4ce1456da1133adc285003e544dd48"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
"cocur/slugify": "^4.3",
|
||||||
"phpmailer/phpmailer": "^6.8",
|
"phpmailer/phpmailer": "^6.8",
|
||||||
"symfony/console": "^5.4",
|
"symfony/console": "^5.4",
|
||||||
"vlucas/phpdotenv": "^5.5"
|
"vlucas/phpdotenv": "^5.5"
|
||||||
@@ -33,7 +108,7 @@
|
|||||||
"GNU GPL 3.0"
|
"GNU GPL 3.0"
|
||||||
],
|
],
|
||||||
"description": "Lightweight web framework",
|
"description": "Lightweight web framework",
|
||||||
"time": "2023-05-01T17:08:22+00:00"
|
"time": "2023-07-08T12:38:40+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "firebase/php-jwt",
|
"name": "firebase/php-jwt",
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use RVR\PersistentData\Model\Community;
|
||||||
|
use SokoWeb\Database\Query\Select;
|
||||||
|
|
||||||
|
$select = new Select(Container::$dbConnection);
|
||||||
|
$communities = Container::$persistentDataManager->selectMultipleFromDb($select, Community::class);
|
||||||
|
|
||||||
|
foreach ($communities as $community) {
|
||||||
|
$community->generateSlug();
|
||||||
|
Container::$persistentDataManager->saveToDb($community);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
ALTER TABLE `communities`
|
||||||
|
ADD `slug` varchar(255) CHARACTER SET ascii COLLATE ascii_bin DEFAULT NULL AFTER `id`,
|
||||||
|
ADD UNIQUE `slug` (`slug`);
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
CREATE TABLE `events` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`slug` varchar(255) CHARACTER SET ascii COLLATE ascii_bin DEFAULT NULL,
|
||||||
|
`community_id` int(10) unsigned NOT NULL,
|
||||||
|
`start` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||||
|
`end` timestamp NOT NULL DEFAULT current_timestamp(),
|
||||||
|
`title` varchar(255) NOT NULL,
|
||||||
|
`description` text NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `community_id` (`community_id`),
|
||||||
|
UNIQUE KEY `slug` (`slug`),
|
||||||
|
CONSTRAINT `events_community_id` FOREIGN KEY (`community_id`) REFERENCES `communities` (`id`)
|
||||||
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
ALTER TABLE `transactions`
|
||||||
|
ADD `event_id` int(10) unsigned NULL AFTER `community_id`,
|
||||||
|
ADD KEY `event_id` (`event_id`),
|
||||||
|
ADD CONSTRAINT `transactions_event_id` FOREIGN KEY (`event_id`) REFERENCES `events` (`id`);
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
CREATE TABLE `transaction_payees` (
|
||||||
|
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
`transaction_id` int(10) unsigned NOT NULL,
|
||||||
|
`user_id` int(10) unsigned DEFAULT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `unique_user_for_transaction` (`transaction_id`, `user_id`),
|
||||||
|
KEY `transaction_id` (`transaction_id`),
|
||||||
|
KEY `user_id` (`user_id`),
|
||||||
|
CONSTRAINT `transaction_payees_transaction_id` FOREIGN KEY (`transaction_id`) REFERENCES `transactions` (`id`),
|
||||||
|
CONSTRAINT `transaction_payees_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
|
||||||
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
Hi,
|
|
||||||
<br><br>
|
|
||||||
You recently signed up on {{APP_NAME}} with this Google account ({{EMAIL}}).
|
|
||||||
<br><br>
|
|
||||||
Have fun on {{APP_NAME}}!
|
|
||||||
<br><br>
|
|
||||||
Regards,<br>
|
|
||||||
{{APP_NAME}}<br>
|
|
||||||
<a href="{{BASE_URL}}" title="{{APP_NAME}}">{{BASE_URL}}</a>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
Hi,
|
|
||||||
<br><br>
|
|
||||||
You recently signed up on {{APP_NAME}} with this email address ({{EMAIL}}).
|
|
||||||
To activate your account, please click on the following link:<br>
|
|
||||||
<a href="{{ACTIVATE_LINK}}" title="Account activation">{{ACTIVATE_LINK}}</a>
|
|
||||||
<br><br>
|
|
||||||
You can activate your account until {{ACTIVATABLE_UNTIL}}.
|
|
||||||
If you don't activate your account, your email address will be permanently deleted after this point of time.
|
|
||||||
<br><br>
|
|
||||||
If you did not sign up on {{APP_NAME}} or changed your mind, no further action is required.
|
|
||||||
However if you want to immediately delete your email address, please click on the following link:<br>
|
|
||||||
<a href="{{CANCEL_LINK}}" title="Sign up cancellation">{{CANCEL_LINK}}</a>
|
|
||||||
<br><br>
|
|
||||||
Have fun on {{APP_NAME}}!
|
|
||||||
<br><br>
|
|
||||||
Regards,<br>
|
|
||||||
{{APP_NAME}}<br>
|
|
||||||
<a href="{{BASE_URL}}" title="{{APP_NAME}}">{{BASE_URL}}</a>
|
|
||||||
@@ -108,6 +108,10 @@ p.small, span.small, td.small {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.big, span.big, td.big {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
.red {
|
.red {
|
||||||
color: #a80908;
|
color: #a80908;
|
||||||
}
|
}
|
||||||
@@ -255,11 +259,11 @@ button.red:enabled:hover, button.red:enabled:focus, a.button.red:hover, a.button
|
|||||||
}
|
}
|
||||||
|
|
||||||
button.yellow, a.button.yellow {
|
button.yellow, a.button.yellow {
|
||||||
background-color: #e8a349;
|
background-color: #daa520;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.yellow:enabled:hover, button.yellow:enabled:focus, a.button.yellow:hover, a.button.yellow:focus {
|
button.yellow:enabled:hover, button.yellow:enabled:focus, a.button.yellow:hover, a.button.yellow:focus {
|
||||||
background-color: #c37713;
|
background-color: #b8860b;
|
||||||
}
|
}
|
||||||
|
|
||||||
button.green, a.button.green {
|
button.green, a.button.green {
|
||||||
@@ -397,16 +401,20 @@ header>p {
|
|||||||
}
|
}
|
||||||
|
|
||||||
header>p>span {
|
header>p>span {
|
||||||
padding-left: 6px;
|
padding-left: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
header>p>span>a:link, header>p>span>a:visited {
|
header>p>span>a:link, header>p>span>a:visited {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
header>p>span>a:hover, header>p>span>a:focus {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
header>p>span:not(:last-child) {
|
header>p>span:not(:last-child) {
|
||||||
border-right: solid white 1px;
|
border-right: solid white 1px;
|
||||||
padding-right: 6px;
|
padding-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
@@ -528,6 +536,20 @@ p.paginateContainer > *:not(:last-child) {
|
|||||||
border-right: solid #869ab9 1px;
|
border-right: solid #869ab9 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.formLabel {
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.label {
|
||||||
|
border-radius: 3px;
|
||||||
|
background-color: #555555;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 2px 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 424px) {
|
@media screen and (max-width: 424px) {
|
||||||
div.gridContainer {
|
div.gridContainer {
|
||||||
grid-template-columns: auto;
|
grid-template-columns: auto;
|
||||||
|
|||||||
@@ -59,11 +59,10 @@ var Account = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
document.getElementById('authenticateWithGoogleButton').onclick = function () {
|
var authenticateWithGoogleButton = document.getElementById('authenticateWithGoogleButton');
|
||||||
Account.openGoogleAuthenticate();
|
if (authenticateWithGoogleButton) {
|
||||||
};
|
authenticateWithGoogleButton.onclick = function () {
|
||||||
|
Account.openGoogleAuthenticate();
|
||||||
document.getElementsByTagName('form')[0].onreset = function () {
|
};
|
||||||
Account.resetGoogleAuthentication();
|
}
|
||||||
};
|
|
||||||
})();
|
})();
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
(function () {
|
(function () {
|
||||||
const element = document.getElementById('newMember').elements['user_id'];
|
const element = document.getElementById('newMember').elements['user_id'];
|
||||||
const select = new TomSelect(element, {
|
const select = new TomSelect(element, {
|
||||||
placeholder: 'User',
|
|
||||||
valueField: 'value',
|
valueField: 'value',
|
||||||
labelField: 'label',
|
labelField: 'label',
|
||||||
searchField: 'label',
|
searchField: 'label',
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
(function () {
|
||||||
|
const element = document.getElementById('transactionForm').elements['event_id'];
|
||||||
|
const select = new TomSelect(element, {
|
||||||
|
valueField: 'value',
|
||||||
|
labelField: 'label',
|
||||||
|
searchField: 'label',
|
||||||
|
loadThrottle: 300,
|
||||||
|
load: function (query, callback) {
|
||||||
|
var self = this;
|
||||||
|
RVR.httpRequest('GET', searchEventUrl.replace('QUERY', encodeURIComponent(query)), function () {
|
||||||
|
self.clearOptions();
|
||||||
|
callback(this.response.results);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
select.on('change', function (value) {
|
||||||
|
this.clearOptions();
|
||||||
|
});
|
||||||
|
|
||||||
|
select.on('blur', function (value) {
|
||||||
|
this.clearOptions();
|
||||||
|
});
|
||||||
|
|
||||||
|
select.on('type', function (value) {
|
||||||
|
if (value === '') {
|
||||||
|
this.clearOptions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})();
|
||||||
@@ -64,6 +64,9 @@ var RVR = {
|
|||||||
|
|
||||||
formError.style.display = 'block';
|
formError.style.display = 'block';
|
||||||
formError.innerHTML = this.response.error.errorText;
|
formError.innerHTML = this.response.error.errorText;
|
||||||
|
if (typeof grecaptcha !== 'undefined') {
|
||||||
|
grecaptcha.reset();
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -97,7 +100,7 @@ var RVR = {
|
|||||||
RVR.showModalWithContent('Confirmation', this.dataset.confirmation, [
|
RVR.showModalWithContent('Confirmation', this.dataset.confirmation, [
|
||||||
{
|
{
|
||||||
type: 'button',
|
type: 'button',
|
||||||
text: self.textContent,
|
html: this.dataset.confirmationButton ? this.dataset.confirmationButton : this.innerHTML,
|
||||||
classNames: ['red'],
|
classNames: ['red'],
|
||||||
onclick: function() {
|
onclick: function() {
|
||||||
var event = new Event('submit', {'bubbles': true, 'cancelable': true});
|
var event = new Event('submit', {'bubbles': true, 'cancelable': true});
|
||||||
@@ -147,7 +150,11 @@ var RVR = {
|
|||||||
|
|
||||||
button.classList.add('marginTop');
|
button.classList.add('marginTop');
|
||||||
button.classList.add('marginRight');
|
button.classList.add('marginRight');
|
||||||
button.textContent = extraButton.text;
|
if (typeof extraButton.html !== 'undefined') {
|
||||||
|
button.innerHTML = extraButton.html;
|
||||||
|
} else {
|
||||||
|
button.textContent = extraButton.text;
|
||||||
|
}
|
||||||
|
|
||||||
if (extraButton.type === 'a') {
|
if (extraButton.type === 'a') {
|
||||||
button.href = extraButton.href;
|
button.href = extraButton.href;
|
||||||
|
|||||||
Generated
+5
@@ -2,6 +2,11 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-free": {
|
||||||
|
"version": "6.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.4.0.tgz",
|
||||||
|
"integrity": "sha512-0NyytTlPJwB/BF5LtRV8rrABDbe3TdTXqNB3PdZ+UUUZAEIrdOJdmABqKjt4AXwIoJNaRVVZEXxpNrqvE1GAYQ=="
|
||||||
|
},
|
||||||
"@orchidjs/sifter": {
|
"@orchidjs/sifter": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/@orchidjs/sifter/-/sifter-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/@orchidjs/sifter/-/sifter-1.0.3.tgz",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@fortawesome/fontawesome-free": "^6.4.0",
|
||||||
"leaflet": "^1.6.0",
|
"leaflet": "^1.6.0",
|
||||||
"leaflet.markercluster": "^1.4.1",
|
"leaflet.markercluster": "^1.4.1",
|
||||||
"tom-select": "^2.2.2"
|
"tom-select": "^2.2.2"
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use RVR\Repository\CommunityRepository;
|
|||||||
use RVR\Repository\CommunityMemberRepository;
|
use RVR\Repository\CommunityMemberRepository;
|
||||||
use RVR\Repository\CurrencyExchangeRateRepository;
|
use RVR\Repository\CurrencyExchangeRateRepository;
|
||||||
use RVR\Repository\CurrencyRepository;
|
use RVR\Repository\CurrencyRepository;
|
||||||
|
use RVR\Repository\EventRepository;
|
||||||
use RVR\Repository\TransactionRepository;
|
use RVR\Repository\TransactionRepository;
|
||||||
use RVR\Repository\UserRepository;
|
use RVR\Repository\UserRepository;
|
||||||
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
|
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
|
||||||
@@ -32,6 +33,8 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
private TransactionRepository $transactionRepository;
|
private TransactionRepository $transactionRepository;
|
||||||
|
|
||||||
|
private EventRepository $eventRepository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->userRepository = new UserRepository();
|
$this->userRepository = new UserRepository();
|
||||||
@@ -40,6 +43,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
$this->currencyRepository = new CurrencyRepository();
|
$this->currencyRepository = new CurrencyRepository();
|
||||||
$this->currencyExchangeRatesRepository = new CurrencyExchangeRateRepository();
|
$this->currencyExchangeRatesRepository = new CurrencyExchangeRateRepository();
|
||||||
$this->transactionRepository = new TransactionRepository();
|
$this->transactionRepository = new TransactionRepository();
|
||||||
|
$this->eventRepository = new EventRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAuthenticationRequired(): bool
|
public function isAuthenticationRequired(): bool
|
||||||
@@ -49,45 +53,34 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function getCommunityHome(): ?IContent
|
public function getCommunityHome(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), false, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), false, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
\Container::$persistentDataManager->loadRelationsFromDb($community, false, ['main_currency']);
|
\Container::$persistentDataManager->loadRelationsFromDb($community, false, ['main_currency']);
|
||||||
|
|
||||||
$balanceCalculator = new BalanceCalculator($community);
|
/**
|
||||||
$debts = $balanceCalculator->calculate();
|
* @var User $user
|
||||||
$debtItems = [];
|
*/
|
||||||
$debtBalance = 0.0;
|
$user = \Container::$request->user();
|
||||||
$outstandingItems = [];
|
$balanceCalculator = new BalanceCalculator($community, $user);
|
||||||
$outstandingBalance = 0.0;
|
$balance = $balanceCalculator->calculate();
|
||||||
foreach ($debts as $debt) {
|
|
||||||
if ($debt['payer']->getId() === \Container::$request->user()->getUniqueId()) {
|
|
||||||
$debtBalance += $debt['amount'];
|
|
||||||
$debtItems[] = $debt;
|
|
||||||
}
|
|
||||||
if ($debt['payee']->getId() === \Container::$request->user()->getUniqueId()) {
|
|
||||||
$outstandingBalance += $debt['amount'];
|
|
||||||
$outstandingItems[] = $debt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$balance = $outstandingBalance - $debtBalance;
|
|
||||||
|
|
||||||
return new HtmlContent('communities/community', [
|
return new HtmlContent('communities/community', [
|
||||||
'community' => $community,
|
'community' => $community,
|
||||||
'upcomingEvents' => [],
|
'upcomingAndRecentEvents' => iterator_to_array($this->eventRepository->getUpcomingAndRecentByCommunity($community, new DateTime(), 30, 3)),
|
||||||
'debtItems' => $debtItems,
|
'debtItems' => $balance['debtItems'],
|
||||||
'debtBalance' => $debtBalance,
|
'debtBalance' => $balance['debtBalance'],
|
||||||
'outstandingItems' => $outstandingItems,
|
'outstandingItems' => $balance['outstandingItems'],
|
||||||
'outstandingBalance' => $outstandingBalance,
|
'outstandingBalance' => $balance['outstandingBalance'],
|
||||||
'balance' => $balance,
|
'balance' => $balance['absoluteBalance'],
|
||||||
'editPermission' => $ownCommunityMember->getOwner()
|
'editPermission' => $ownCommunityMember->getOwner()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCommunitySettings(): ?IContent
|
public function getCommunitySettings(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), false, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), false, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,7 +99,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function getCommunityEdit(): ?IContent
|
public function getCommunityEdit(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,9 +117,9 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$communityId = \Container::$request->query('communityId');
|
$communitySlug = \Container::$request->query('communitySlug');
|
||||||
if ($communityId){
|
if ($communitySlug){
|
||||||
if (!$this->checkPermission($communityId, true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission($communitySlug, true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -145,7 +138,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
$community->setName($name);
|
$community->setName($name);
|
||||||
\Container::$persistentDataManager->saveToDb($community);
|
\Container::$persistentDataManager->saveToDb($community);
|
||||||
|
|
||||||
if (!$communityId) {
|
if (!$communitySlug) {
|
||||||
/**
|
/**
|
||||||
* @var User $user
|
* @var User $user
|
||||||
*/
|
*/
|
||||||
@@ -168,13 +161,50 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
}
|
}
|
||||||
|
|
||||||
return new JsonContent([
|
return new JsonContent([
|
||||||
'redirect' => ['target' => \Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()])]
|
'redirect' => ['target' => \Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()])]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function deleteCommunity(): ?IContent
|
||||||
|
{
|
||||||
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->transactionRepository->countAllByCommunity($community) > 0) {
|
||||||
|
return new JsonContent([
|
||||||
|
'error' => ['errorText' => 'There are transactions for this community!']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->eventRepository->countAllByCommunity($community) > 0) {
|
||||||
|
return new JsonContent([
|
||||||
|
'error' => ['errorText' => 'There are events for this community!']
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->communityMemberRepository->getAllByCommunity($community) as $communityMember) {
|
||||||
|
\Container::$persistentDataManager->deleteFromDb($communityMember);
|
||||||
|
}
|
||||||
|
|
||||||
|
$community->setMainCurrencyId(null);
|
||||||
|
\Container::$persistentDataManager->saveToDb($community);
|
||||||
|
|
||||||
|
foreach ($this->currencyRepository->getAllByCommunity($community) as $currency) {
|
||||||
|
foreach ($this->currencyExchangeRatesRepository->getAllByCurrency($currency) as $currencyExchangeRate) {
|
||||||
|
\Container::$persistentDataManager->deleteFromDb($currencyExchangeRate);
|
||||||
|
}
|
||||||
|
\Container::$persistentDataManager->deleteFromDb($currency);
|
||||||
|
}
|
||||||
|
|
||||||
|
\Container::$persistentDataManager->deleteFromDb($community);
|
||||||
|
|
||||||
|
return new JsonContent(['success' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
public function getMembersEdit(): ?IContent
|
public function getMembersEdit(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +216,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function saveMember(): ?IContent
|
public function saveMember(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +255,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function deleteMember(): ?IContent
|
public function deleteMember(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +280,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function getCurrenciesEdit(): ?IContent
|
public function getCurrenciesEdit(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +292,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function saveCurrency(): ?IContent
|
public function saveCurrency(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +328,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function deleteCurrency(): ?IContent
|
public function deleteCurrency(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +354,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function getCurrencyExchangeRates(): ?IContent
|
public function getCurrencyExchangeRates(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,7 +375,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function saveCurrencyExchangeRate(): ?IContent
|
public function saveCurrencyExchangeRate(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -378,7 +408,7 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
|
|
||||||
public function deleteCurrencyExchangeRate(): ?IContent
|
public function deleteCurrencyExchangeRate(): ?IContent
|
||||||
{
|
{
|
||||||
if (!$this->checkPermission(\Container::$request->query('communityId'), true, $community, $ownCommunityMember)) {
|
if (!$this->checkPermission(\Container::$request->query('communitySlug'), true, $community, $ownCommunityMember)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,12 +445,12 @@ class CommunityController implements IAuthenticationRequired
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function checkPermission(
|
private function checkPermission(
|
||||||
int $communityId,
|
string $communitySlug,
|
||||||
bool $needToBeOwner,
|
bool $needToBeOwner,
|
||||||
?Community &$community,
|
?Community &$community,
|
||||||
?CommunityMember &$ownCommunityMember): bool
|
?CommunityMember &$ownCommunityMember): bool
|
||||||
{
|
{
|
||||||
$community = $this->communityRepository->getById($communityId);
|
$community = $this->communityRepository->getBySlug($communitySlug);
|
||||||
if ($community === null) {
|
if ($community === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,193 @@
|
|||||||
|
<?php namespace RVR\Controller;
|
||||||
|
|
||||||
|
use Container;
|
||||||
|
use DateTime;
|
||||||
|
use RVR\Finance\BalanceCalculator;
|
||||||
|
use RVR\Finance\ExchangeRateCalculator;
|
||||||
|
use RVR\PersistentData\Model\Community;
|
||||||
|
use RVR\PersistentData\Model\CommunityMember;
|
||||||
|
use RVR\PersistentData\Model\Event;
|
||||||
|
use RVR\PersistentData\Model\User;
|
||||||
|
use RVR\Repository\CommunityMemberRepository;
|
||||||
|
use RVR\Repository\CommunityRepository;
|
||||||
|
use RVR\Repository\EventRepository;
|
||||||
|
use RVR\Repository\TransactionRepository;
|
||||||
|
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
|
||||||
|
use SokoWeb\Interfaces\Authorization\ISecured;
|
||||||
|
use SokoWeb\Interfaces\Response\IContent;
|
||||||
|
use SokoWeb\Response\HtmlContent;
|
||||||
|
use SokoWeb\Response\JsonContent;
|
||||||
|
|
||||||
|
class EventController implements IAuthenticationRequired, ISecured
|
||||||
|
{
|
||||||
|
private CommunityRepository $communityRepository;
|
||||||
|
|
||||||
|
private CommunityMemberRepository $communityMemberRepository;
|
||||||
|
|
||||||
|
private EventRepository $eventRepository;
|
||||||
|
|
||||||
|
private TransactionRepository $transactionRepository;
|
||||||
|
|
||||||
|
private ?Community $community;
|
||||||
|
|
||||||
|
private ?CommunityMember $ownCommunityMember;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->communityRepository = new CommunityRepository();
|
||||||
|
$this->communityMemberRepository = new CommunityMemberRepository();
|
||||||
|
$this->eventRepository = new EventRepository();
|
||||||
|
$this->transactionRepository = new TransactionRepository();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isAuthenticationRequired(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
$communitySlug = \Container::$request->query('communitySlug');
|
||||||
|
$this->community = $this->communityRepository->getBySlug($communitySlug);
|
||||||
|
if ($this->community === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var User $user
|
||||||
|
*/
|
||||||
|
$user = \Container::$request->user();
|
||||||
|
$this->ownCommunityMember = $this->communityMemberRepository->getByCommunityAndUser($this->community, $user);
|
||||||
|
if ($this->ownCommunityMember === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEvents(): IContent
|
||||||
|
{
|
||||||
|
$itemsPerPage = 10;
|
||||||
|
$numberOfEvents = $this->eventRepository->countAllByCommunity($this->community);
|
||||||
|
$currentPage = Container::$request->query('page') ?: 1;
|
||||||
|
$events = $this->eventRepository->getPagedByCommunity(
|
||||||
|
$this->community,
|
||||||
|
$currentPage,
|
||||||
|
$itemsPerPage
|
||||||
|
);
|
||||||
|
|
||||||
|
return new HtmlContent('events/events', [
|
||||||
|
'community' => $this->community,
|
||||||
|
'pages' => ceil($numberOfEvents / $itemsPerPage),
|
||||||
|
'currentPage' => $currentPage,
|
||||||
|
'numberOfEvents' => $numberOfEvents,
|
||||||
|
'events' => $events
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function searchEvent(): IContent
|
||||||
|
{
|
||||||
|
$events = iterator_to_array($this->eventRepository->searchByTitle($this->community, Container::$request->query('q')));
|
||||||
|
$results = [];
|
||||||
|
foreach ($events as $event) {
|
||||||
|
$results[] = ['value' => $event->getId(), 'label' => $event->getTitle()];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JsonContent([
|
||||||
|
'results' => $results
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEvent(): ?IContent
|
||||||
|
{
|
||||||
|
$event = $this->eventRepository->getBySlug(Container::$request->query('eventSlug'));
|
||||||
|
if (!$event) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Container::$persistentDataManager->loadRelationsFromDb($this->community, true, ['main_currency']);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var User $user
|
||||||
|
*/
|
||||||
|
$user = \Container::$request->user();
|
||||||
|
$balanceCalculator = new BalanceCalculator($this->community, $user, $event);
|
||||||
|
$balance = $balanceCalculator->calculate();
|
||||||
|
|
||||||
|
return new HtmlContent('events/event', [
|
||||||
|
'community' => $this->community,
|
||||||
|
'event' => $event,
|
||||||
|
'totalCost' => $this->sumTransactions($event),
|
||||||
|
'debtItems' => $balance['debtItems'],
|
||||||
|
'debtBalance' => $balance['debtBalance'],
|
||||||
|
'outstandingItems' => $balance['outstandingItems'],
|
||||||
|
'outstandingBalance' => $balance['outstandingBalance'],
|
||||||
|
'balance' => $balance['absoluteBalance'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEventEdit(): ?IContent
|
||||||
|
{
|
||||||
|
$eventSlug = Container::$request->query('eventSlug');
|
||||||
|
if ($eventSlug) {
|
||||||
|
$event = $this->eventRepository->getBySlug($eventSlug);
|
||||||
|
if ($event === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$event = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HtmlContent('events/event_edit', [
|
||||||
|
'community' => $this->community,
|
||||||
|
'event' => $event
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveEvent(): ?IContent
|
||||||
|
{
|
||||||
|
$eventSlug = Container::$request->query('eventSlug');
|
||||||
|
if ($eventSlug) {
|
||||||
|
$event = $this->eventRepository->getBySlug($eventSlug);
|
||||||
|
} else {
|
||||||
|
$event = new Event();
|
||||||
|
$event->setCommunity($this->community);
|
||||||
|
}
|
||||||
|
|
||||||
|
$event->setTitle(Container::$request->post('title'));
|
||||||
|
$event->setDescription(Container::$request->post('description'));
|
||||||
|
$event->setStartDate(new DateTime(Container::$request->post('start')));
|
||||||
|
$event->setEndDate(new DateTime(Container::$request->post('end')));
|
||||||
|
Container::$persistentDataManager->saveToDb($event);
|
||||||
|
|
||||||
|
return new JsonContent([
|
||||||
|
'redirect' => ['target' => \Container::$routeCollection->getRoute('community.event')->generateLink(['communitySlug' => $this->community->getSlug(), 'eventSlug' => $event->getSlug()])]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteEvent(): IContent
|
||||||
|
{
|
||||||
|
$event = $this->eventRepository->getBySlug(Container::$request->query('eventSlug'));
|
||||||
|
|
||||||
|
foreach ($this->transactionRepository->getAllByEvent($event) as $transaction) {
|
||||||
|
$transaction->setEventId(null);
|
||||||
|
Container::$persistentDataManager->saveToDb($transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
Container::$persistentDataManager->deleteFromDb($event);
|
||||||
|
|
||||||
|
return new JsonContent(['success' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sumTransactions(Event $event): float
|
||||||
|
{
|
||||||
|
$exchangeRateCalculator = new ExchangeRateCalculator($this->community->getMainCurrency());
|
||||||
|
$transactions = $this->transactionRepository->getAllByEvent($event, true, ['currency']);
|
||||||
|
$sum = 0.0;
|
||||||
|
|
||||||
|
foreach ($transactions as $transaction) {
|
||||||
|
$sum += $exchangeRateCalculator->calculate($transaction->getSum(), $transaction->getCurrency(), $transaction->getTimeDate());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
<?php namespace RVR\Controller;
|
<?php namespace RVR\Controller;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
use RVR\PersistentData\Model\Community;
|
use RVR\PersistentData\Model\Community;
|
||||||
use RVR\PersistentData\Model\User;
|
use RVR\PersistentData\Model\User;
|
||||||
use RVR\Repository\CommunityMemberRepository;
|
use RVR\Repository\CommunityMemberRepository;
|
||||||
|
use RVR\Repository\EventRepository;
|
||||||
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
|
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
|
||||||
use SokoWeb\Interfaces\Response\IContent;
|
use SokoWeb\Interfaces\Response\IContent;
|
||||||
use SokoWeb\Response\HtmlContent;
|
use SokoWeb\Response\HtmlContent;
|
||||||
@@ -11,9 +13,12 @@ class HomeController implements IAuthenticationRequired
|
|||||||
{
|
{
|
||||||
private CommunityMemberRepository $communityMemberRepository;
|
private CommunityMemberRepository $communityMemberRepository;
|
||||||
|
|
||||||
|
private EventRepository $eventRepository;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->communityMemberRepository = new CommunityMemberRepository();
|
$this->communityMemberRepository = new CommunityMemberRepository();
|
||||||
|
$this->eventRepository = new EventRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAuthenticationRequired(): bool
|
public function isAuthenticationRequired(): bool
|
||||||
@@ -39,7 +44,7 @@ class HomeController implements IAuthenticationRequired
|
|||||||
|
|
||||||
return new HtmlContent('home', [
|
return new HtmlContent('home', [
|
||||||
'communities' => $communities,
|
'communities' => $communities,
|
||||||
'upcomingEvents' => []
|
'upcomingAndRecentEvents' => iterator_to_array($this->eventRepository->getUpcomingAndRecentByUser($user, new DateTime(), 30, 3, true, ['community']))
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ class LoginController
|
|||||||
if ($user === null) {
|
if ($user === null) {
|
||||||
return new JsonContent([
|
return new JsonContent([
|
||||||
'error' => [
|
'error' => [
|
||||||
'errorText' => 'No user found with the given email address / username.'
|
'errorText' => 'No user found with the given email address.'
|
||||||
]
|
]
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@@ -281,7 +281,7 @@ class LoginController
|
|||||||
$mail = new Mail();
|
$mail = new Mail();
|
||||||
$mail->addRecipient($email);
|
$mail->addRecipient($email);
|
||||||
$mail->setSubject($_ENV['APP_NAME'] . ' - Password reset');
|
$mail->setSubject($_ENV['APP_NAME'] . ' - Password reset');
|
||||||
$mail->setBodyFromTemplate('password.reset', [
|
$mail->setBodyFromTemplate('password-reset', [
|
||||||
'EMAIL' => $email,
|
'EMAIL' => $email,
|
||||||
'RESET_LINK' => \Container::$request->getBase() .
|
'RESET_LINK' => \Container::$request->getBase() .
|
||||||
\Container::$routeCollection->getRoute('password.reset')->generateLink(['token' => $token]),
|
\Container::$routeCollection->getRoute('password.reset')->generateLink(['token' => $token]),
|
||||||
|
|||||||
@@ -6,11 +6,14 @@ use RVR\Finance\ExchangeRateCalculator;
|
|||||||
use RVR\PersistentData\Model\Community;
|
use RVR\PersistentData\Model\Community;
|
||||||
use RVR\PersistentData\Model\CommunityMember;
|
use RVR\PersistentData\Model\CommunityMember;
|
||||||
use RVR\PersistentData\Model\Transaction;
|
use RVR\PersistentData\Model\Transaction;
|
||||||
|
use RVR\PersistentData\Model\TransactionPayee;
|
||||||
use RVR\PersistentData\Model\User;
|
use RVR\PersistentData\Model\User;
|
||||||
use RVR\Repository\CommunityMemberRepository;
|
use RVR\Repository\CommunityMemberRepository;
|
||||||
use RVR\Repository\CommunityRepository;
|
use RVR\Repository\CommunityRepository;
|
||||||
use RVR\Repository\CurrencyRepository;
|
use RVR\Repository\CurrencyRepository;
|
||||||
use RVR\Repository\TransactionRepository;
|
use RVR\Repository\TransactionRepository;
|
||||||
|
use RVR\Repository\TransactionPayeeRepository;
|
||||||
|
use RVR\Repository\EventRepository;
|
||||||
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
|
use SokoWeb\Interfaces\Authentication\IAuthenticationRequired;
|
||||||
use SokoWeb\Interfaces\Authorization\ISecured;
|
use SokoWeb\Interfaces\Authorization\ISecured;
|
||||||
use SokoWeb\Interfaces\Response\IContent;
|
use SokoWeb\Interfaces\Response\IContent;
|
||||||
@@ -27,9 +30,13 @@ class TransactionController implements IAuthenticationRequired, ISecured
|
|||||||
|
|
||||||
private TransactionRepository $transactionRepository;
|
private TransactionRepository $transactionRepository;
|
||||||
|
|
||||||
private Community $community;
|
private TransactionPayeeRepository $transactionPayeeRepository;
|
||||||
|
|
||||||
private CommunityMember $ownCommunityMember;
|
private EventRepository $eventRepository;
|
||||||
|
|
||||||
|
private ?Community $community;
|
||||||
|
|
||||||
|
private ?CommunityMember $ownCommunityMember;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -37,6 +44,8 @@ class TransactionController implements IAuthenticationRequired, ISecured
|
|||||||
$this->communityMemberRepository = new CommunityMemberRepository();
|
$this->communityMemberRepository = new CommunityMemberRepository();
|
||||||
$this->currencyRepository = new CurrencyRepository();
|
$this->currencyRepository = new CurrencyRepository();
|
||||||
$this->transactionRepository = new TransactionRepository();
|
$this->transactionRepository = new TransactionRepository();
|
||||||
|
$this->transactionPayeeRepository = new TransactionPayeeRepository();
|
||||||
|
$this->eventRepository = new EventRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAuthenticationRequired(): bool
|
public function isAuthenticationRequired(): bool
|
||||||
@@ -46,8 +55,8 @@ class TransactionController implements IAuthenticationRequired, ISecured
|
|||||||
|
|
||||||
public function authorize(): bool
|
public function authorize(): bool
|
||||||
{
|
{
|
||||||
$communityId = \Container::$request->query('communityId');
|
$communitySlug = \Container::$request->query('communitySlug');
|
||||||
$this->community = $this->communityRepository->getById($communityId);
|
$this->community = $this->communityRepository->getBySlug($communitySlug);
|
||||||
if ($this->community === null) {
|
if ($this->community === null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -69,25 +78,46 @@ class TransactionController implements IAuthenticationRequired, ISecured
|
|||||||
Container::$persistentDataManager->loadRelationsFromDb($this->community, true, ['main_currency']);
|
Container::$persistentDataManager->loadRelationsFromDb($this->community, true, ['main_currency']);
|
||||||
$exchangeRateCalculator = new ExchangeRateCalculator($this->community->getMainCurrency());
|
$exchangeRateCalculator = new ExchangeRateCalculator($this->community->getMainCurrency());
|
||||||
|
|
||||||
|
$eventSlug = Container::$request->query('event');
|
||||||
|
if ($eventSlug) {
|
||||||
|
$event = $this->eventRepository->getBySlug($eventSlug);
|
||||||
|
} else {
|
||||||
|
$event = null;
|
||||||
|
}
|
||||||
|
|
||||||
$itemsPerPage = 50;
|
$itemsPerPage = 50;
|
||||||
$numberOfTransactions = $this->transactionRepository->countAllByCommunity($this->community);
|
$numberOfTransactions = $event ?
|
||||||
$pages = ceil($numberOfTransactions / $itemsPerPage);
|
$this->transactionRepository->countAllByEvent($event) :
|
||||||
$currentPage = Container::$request->query('page') ?: 0;
|
$this->transactionRepository->countAllByCommunity($this->community);
|
||||||
$transactions = $this->transactionRepository->getPagedByCommunity(
|
$currentPage = Container::$request->query('page') ?: 1;
|
||||||
$this->community,
|
$transactions = $event ?
|
||||||
$currentPage * $itemsPerPage,
|
$this->transactionRepository->getPagedByEvent(
|
||||||
$itemsPerPage,
|
$event,
|
||||||
true,
|
$currentPage,
|
||||||
['currency', 'payer_user', 'payee_user']
|
$itemsPerPage,
|
||||||
);
|
true,
|
||||||
|
['currency', 'payer_user']
|
||||||
|
) :
|
||||||
|
$this->transactionRepository->getPagedByCommunity(
|
||||||
|
$this->community,
|
||||||
|
$currentPage,
|
||||||
|
$itemsPerPage,
|
||||||
|
true,
|
||||||
|
['event', 'currency', 'payer_user']
|
||||||
|
);
|
||||||
|
|
||||||
|
$transactions = iterator_to_array($transactions);
|
||||||
|
Container::$persistentDataManager->loadMultiRelationsFromDb($transactions, 'payees', true, ['user']);
|
||||||
|
|
||||||
return new HtmlContent('communities/transactions', [
|
return new HtmlContent('communities/transactions', [
|
||||||
'community' => $this->community,
|
'community' => $this->community,
|
||||||
|
'event' => $event,
|
||||||
'exchangeRateCalculator' => $exchangeRateCalculator,
|
'exchangeRateCalculator' => $exchangeRateCalculator,
|
||||||
'pages' => $pages,
|
'pages' => ceil($numberOfTransactions / $itemsPerPage),
|
||||||
'currentPage' => $currentPage,
|
'currentPage' => $currentPage,
|
||||||
'numberOfTransactions' => $numberOfTransactions,
|
'numberOfTransactions' => $numberOfTransactions,
|
||||||
'transactions' => $transactions
|
'transactions' => $transactions,
|
||||||
|
'members' => $this->getMembers($this->community)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,13 +129,28 @@ class TransactionController implements IAuthenticationRequired, ISecured
|
|||||||
if ($transaction === null) {
|
if ($transaction === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
Container::$persistentDataManager->loadRelationsFromDb($transaction, false, ['event']);
|
||||||
|
$event = $transaction->getEvent();
|
||||||
|
$payeeUserIds = [];
|
||||||
|
foreach ($this->transactionPayeeRepository->getAllByTransaction($transaction) as $payee) {
|
||||||
|
$payeeUserIds[] = $payee->getUserId();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$transaction = null;
|
$transaction = null;
|
||||||
|
$eventSlug = Container::$request->query('event');
|
||||||
|
if ($eventSlug) {
|
||||||
|
$event = $this->eventRepository->getBySlug($eventSlug);
|
||||||
|
} else {
|
||||||
|
$event = null;
|
||||||
|
}
|
||||||
|
$payeeUserIds = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
return new HtmlContent('communities/transaction_edit', [
|
return new HtmlContent('communities/transaction_edit', [
|
||||||
'community' => $this->community,
|
'community' => $this->community,
|
||||||
'transaction' => $transaction,
|
'transaction' => $transaction,
|
||||||
|
'payeeUserIds' => $payeeUserIds,
|
||||||
|
'event' => $event,
|
||||||
'members' => $this->getMembers($this->community),
|
'members' => $this->getMembers($this->community),
|
||||||
'currencies' => $this->getCurrencies($this->community)
|
'currencies' => $this->getCurrencies($this->community)
|
||||||
]);
|
]);
|
||||||
@@ -121,20 +166,51 @@ class TransactionController implements IAuthenticationRequired, ISecured
|
|||||||
$transaction->setCommunity($this->community);
|
$transaction->setCommunity($this->community);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$transaction->setEventId(Container::$request->post('event_id') ?: null);
|
||||||
$transaction->setCurrencyId(Container::$request->post('currency_id'));
|
$transaction->setCurrencyId(Container::$request->post('currency_id'));
|
||||||
$transaction->setPayerUserId(Container::$request->post('payer_user_id'));
|
$transaction->setPayerUserId(Container::$request->post('payer_user_id'));
|
||||||
$transaction->setPayeeUserId(Container::$request->post('payee_user_id') ?: null);
|
|
||||||
$transaction->setDescription(Container::$request->post('description'));
|
$transaction->setDescription(Container::$request->post('description'));
|
||||||
$transaction->setSum(Container::$request->post('sum'));
|
$transaction->setSum(Container::$request->post('sum'));
|
||||||
$transaction->setTimeDate(new DateTime(Container::$request->post('time')));
|
$transaction->setTimeDate(new DateTime(Container::$request->post('time')));
|
||||||
Container::$persistentDataManager->saveToDb($transaction);
|
Container::$persistentDataManager->saveToDb($transaction);
|
||||||
|
|
||||||
|
$payeeUserIds = array_unique(Container::$request->post('payee_user_ids'));
|
||||||
|
if (count($payeeUserIds) === $this->communityMemberRepository->countAllByCommunity($this->community)) {
|
||||||
|
$payeeUserIds = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$currentPayees = [];
|
||||||
|
foreach ($payeeUserIds as $payeeUserId) {
|
||||||
|
$payee = new TransactionPayee();
|
||||||
|
$payee->setTransaction($transaction);
|
||||||
|
$payee->setUserId((int)$payeeUserId);
|
||||||
|
$currentPayees[(int)$payeeUserId] = $payee;
|
||||||
|
}
|
||||||
|
$existingPayees = [];
|
||||||
|
if ($transactionId) {
|
||||||
|
foreach ($this->transactionPayeeRepository->getAllByTransaction($transaction) as $payee) {
|
||||||
|
$existingPayees[$payee->getUserId()] = $payee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (array_diff_key($currentPayees, $existingPayees) as $newPayee) {
|
||||||
|
Container::$persistentDataManager->saveToDb($newPayee);
|
||||||
|
}
|
||||||
|
foreach (array_diff_key($existingPayees, $currentPayees) as $deletedPayee) {
|
||||||
|
Container::$persistentDataManager->deleteFromDb($deletedPayee);
|
||||||
|
}
|
||||||
|
|
||||||
return new JsonContent(['success' => true]);
|
return new JsonContent(['success' => true]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteTransaction(): IContent
|
public function deleteTransaction(): IContent
|
||||||
{
|
{
|
||||||
$transaction = $this->transactionRepository->getById(Container::$request->query('transactionId'));
|
$transaction = $this->transactionRepository->getById(Container::$request->query('transactionId'));
|
||||||
|
|
||||||
|
foreach ($this->transactionPayeeRepository->getAllByTransaction($transaction) as $payee) {
|
||||||
|
Container::$persistentDataManager->deleteFromDb($payee);
|
||||||
|
}
|
||||||
|
|
||||||
Container::$persistentDataManager->deleteFromDb($transaction);
|
Container::$persistentDataManager->deleteFromDb($transaction);
|
||||||
|
|
||||||
return new JsonContent(['success' => true]);
|
return new JsonContent(['success' => true]);
|
||||||
@@ -143,7 +219,7 @@ class TransactionController implements IAuthenticationRequired, ISecured
|
|||||||
private function getMembers(Community $community): array
|
private function getMembers(Community $community): array
|
||||||
{
|
{
|
||||||
$members = iterator_to_array($this->communityMemberRepository->getAllByCommunity($community, true, ['user']));
|
$members = iterator_to_array($this->communityMemberRepository->getAllByCommunity($community, true, ['user']));
|
||||||
usort($members, function($a, $b) {
|
usort($members, function ($a, $b) {
|
||||||
return strnatcmp($a->getUser()->getDisplayName(), $b->getUser()->getDisplayName());
|
return strnatcmp($a->getUser()->getDisplayName(), $b->getUser()->getDisplayName());
|
||||||
});
|
});
|
||||||
return $members;
|
return $members;
|
||||||
@@ -152,10 +228,10 @@ class TransactionController implements IAuthenticationRequired, ISecured
|
|||||||
private function getCurrencies(Community $community): array
|
private function getCurrencies(Community $community): array
|
||||||
{
|
{
|
||||||
$currencies = iterator_to_array($this->currencyRepository->getAllByCommunity($community));
|
$currencies = iterator_to_array($this->currencyRepository->getAllByCommunity($community));
|
||||||
usort($currencies, function($a, $b) {
|
usort($currencies, function ($a, $b) {
|
||||||
return strnatcmp($a->getCode(), $b->getCode());
|
return strnatcmp($a->getCode(), $b->getCode());
|
||||||
});
|
});
|
||||||
usort($currencies, function($a, $b) use ($community) {
|
usort($currencies, function ($a, $b) use ($community) {
|
||||||
return (int)($b->getId() === $community->getMainCurrencyId()) - (int)($a->getId() === $community->getMainCurrencyId());
|
return (int)($b->getId() === $community->getMainCurrencyId()) - (int)($a->getId() === $community->getMainCurrencyId());
|
||||||
});
|
});
|
||||||
return $currencies;
|
return $currencies;
|
||||||
|
|||||||
@@ -37,6 +37,130 @@ class UserController implements IAuthenticationRequired
|
|||||||
return new HtmlContent('account/account', ['user' => $user->toArray()]);
|
return new HtmlContent('account/account', ['user' => $user->toArray()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getGoogleConnectRedirect(): IRedirect
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var User $user
|
||||||
|
*/
|
||||||
|
$user = \Container::$request->user();
|
||||||
|
|
||||||
|
$state = bin2hex(random_bytes(16));
|
||||||
|
$nonce = bin2hex(random_bytes(16));
|
||||||
|
|
||||||
|
\Container::$request->session()->set('oauth_state', $state);
|
||||||
|
\Container::$request->session()->set('oauth_nonce', $nonce);
|
||||||
|
|
||||||
|
$oAuth = new GoogleOAuth(new Request());
|
||||||
|
|
||||||
|
$url = $oAuth->getDialogUrl(
|
||||||
|
$state,
|
||||||
|
\Container::$request->getBase() . \Container::$routeCollection->getRoute('account.googleConnect-confirm')->generateLink(),
|
||||||
|
$nonce,
|
||||||
|
$user->getEmail()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new Redirect($url, IRedirect::TEMPORARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGoogleConnectConfirm(): IContent
|
||||||
|
{
|
||||||
|
$defaultError = 'Authentication with Google failed. Please <a href="' . \Container::$routeCollection->getRoute('account.googleConnect')->generateLink() . '" title="Connect with Google">try again</a>!';
|
||||||
|
|
||||||
|
if (\Container::$request->query('state') !== \Container::$request->session()->get('oauth_state')) {
|
||||||
|
return new HtmlContent('account/google_connect', ['success' => false, 'error' => $defaultError]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$oAuth = new GoogleOAuth(new Request());
|
||||||
|
$tokenData = $oAuth->getToken(
|
||||||
|
\Container::$request->query('code'),
|
||||||
|
\Container::$request->getBase() . \Container::$routeCollection->getRoute('account.googleConnect-confirm')->generateLink()
|
||||||
|
);
|
||||||
|
if (!isset($tokenData['id_token'])) {
|
||||||
|
return new HtmlContent('account/google_connect', ['success' => false, 'error' => $defaultError]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$jwtParser = new JwtParser($tokenData['id_token']);
|
||||||
|
$idToken = $jwtParser->getPayload();
|
||||||
|
if ($idToken['nonce'] !== \Container::$request->session()->get('oauth_nonce')) {
|
||||||
|
return new HtmlContent('account/google_connect', ['success' => false, 'error' => $defaultError]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$anotherUser = $this->userRepository->getByGoogleSub($idToken['sub']);
|
||||||
|
if ($anotherUser !== null) {
|
||||||
|
return new HtmlContent('account/google_connect', [
|
||||||
|
'success' => false,
|
||||||
|
'error' => 'This Google account is linked to another account.'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
\Container::$request->session()->set('google_user_data', $idToken);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var User $user
|
||||||
|
*/
|
||||||
|
$user = \Container::$request->user();
|
||||||
|
|
||||||
|
return new HtmlContent('account/google_connect', [
|
||||||
|
'success' => true,
|
||||||
|
'googleAccount' => $idToken['email'],
|
||||||
|
'userEmail' => $user->getEmail()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function connectGoogle(): IContent
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var User $user
|
||||||
|
*/
|
||||||
|
$user = \Container::$request->user();
|
||||||
|
if (!$user->checkPassword(\Container::$request->post('password'))) {
|
||||||
|
return new JsonContent([
|
||||||
|
'error' => [
|
||||||
|
'errorText' => 'The given password is wrong.'
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$googleUserData = \Container::$request->session()->get('google_user_data');
|
||||||
|
$user->setGoogleSub($googleUserData['sub']);
|
||||||
|
\Container::$persistentDataManager->saveToDb($user);
|
||||||
|
|
||||||
|
return new JsonContent(['success' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGoogleDisconnectConfirm(): IContent
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var User $user
|
||||||
|
*/
|
||||||
|
$user = \Container::$request->user();
|
||||||
|
|
||||||
|
return new HtmlContent('account/google_disconnect', [
|
||||||
|
'success' => true,
|
||||||
|
'userEmail' => $user->getEmail()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function disconnectGoogle(): IContent
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var User $user
|
||||||
|
*/
|
||||||
|
$user = \Container::$request->user();
|
||||||
|
if (!$user->checkPassword(\Container::$request->post('password'))) {
|
||||||
|
return new JsonContent([
|
||||||
|
'error' => [
|
||||||
|
'errorText' => 'The given password is wrong.'
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->setGoogleSub(null);
|
||||||
|
\Container::$persistentDataManager->saveToDb($user);
|
||||||
|
|
||||||
|
return new JsonContent(['success' => true]);
|
||||||
|
}
|
||||||
|
|
||||||
public function getGoogleAuthenticateRedirect(): IRedirect
|
public function getGoogleAuthenticateRedirect(): IRedirect
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<?php namespace RVR\Finance;
|
<?php namespace RVR\Finance;
|
||||||
|
|
||||||
|
use Container;
|
||||||
use RVR\PersistentData\Model\Community;
|
use RVR\PersistentData\Model\Community;
|
||||||
|
use RVR\PersistentData\Model\Event;
|
||||||
|
use RVR\PersistentData\Model\User;
|
||||||
use RVR\Repository\CommunityMemberRepository;
|
use RVR\Repository\CommunityMemberRepository;
|
||||||
use RVR\Repository\TransactionRepository;
|
use RVR\Repository\TransactionRepository;
|
||||||
|
|
||||||
@@ -8,6 +11,10 @@ class BalanceCalculator
|
|||||||
{
|
{
|
||||||
private Community $community;
|
private Community $community;
|
||||||
|
|
||||||
|
private User $user;
|
||||||
|
|
||||||
|
private ?Event $event;
|
||||||
|
|
||||||
private TransactionRepository $transactionRepository;
|
private TransactionRepository $transactionRepository;
|
||||||
|
|
||||||
private CommunityMemberRepository $communityMemberRepository;
|
private CommunityMemberRepository $communityMemberRepository;
|
||||||
@@ -18,9 +25,13 @@ class BalanceCalculator
|
|||||||
|
|
||||||
private array $payments;
|
private array $payments;
|
||||||
|
|
||||||
public function __construct(Community $community)
|
private array $actualDebts;
|
||||||
|
|
||||||
|
public function __construct(Community $community, User $user, ?Event $event = null)
|
||||||
{
|
{
|
||||||
$this->community = $community;
|
$this->community = $community;
|
||||||
|
$this->user = $user;
|
||||||
|
$this->event = $event;
|
||||||
$this->transactionRepository = new TransactionRepository();
|
$this->transactionRepository = new TransactionRepository();
|
||||||
$this->communityMemberRepository = new CommunityMemberRepository();
|
$this->communityMemberRepository = new CommunityMemberRepository();
|
||||||
$this->exchangeRateCalculator = new ExchangeRateCalculator($this->community->getMainCurrency());
|
$this->exchangeRateCalculator = new ExchangeRateCalculator($this->community->getMainCurrency());
|
||||||
@@ -31,7 +42,8 @@ class BalanceCalculator
|
|||||||
$this->collectMembers();
|
$this->collectMembers();
|
||||||
$this->createPaymentsMatrix();
|
$this->createPaymentsMatrix();
|
||||||
$this->sumTransactions();
|
$this->sumTransactions();
|
||||||
return $this->calculateActualDebts();
|
$this->calculateActualDebts();
|
||||||
|
return $this->calculateBalanceForUser();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function collectMembers(): void
|
private function collectMembers(): void
|
||||||
@@ -56,13 +68,22 @@ class BalanceCalculator
|
|||||||
private function sumTransactions(): void
|
private function sumTransactions(): void
|
||||||
{
|
{
|
||||||
$membersCount = count($this->members);
|
$membersCount = count($this->members);
|
||||||
$transactions = $this->transactionRepository->getAllByCommunity($this->community, true, ['currency']);
|
if ($this->event !== null) {
|
||||||
|
$transactions = iterator_to_array($this->transactionRepository->getAllByEvent($this->event, true, ['currency']));
|
||||||
|
} else {
|
||||||
|
$transactions = iterator_to_array($this->transactionRepository->getAllByCommunity($this->community, true, ['currency']));
|
||||||
|
}
|
||||||
|
Container::$persistentDataManager->loadMultiRelationsFromDb($transactions, 'payees');
|
||||||
|
|
||||||
foreach ($transactions as $transaction) {
|
foreach ($transactions as $transaction) {
|
||||||
$sum = $this->exchangeRateCalculator->calculate($transaction->getSum(), $transaction->getCurrency(), $transaction->getTimeDate());
|
$sum = $this->exchangeRateCalculator->calculate($transaction->getSum(), $transaction->getCurrency(), $transaction->getTimeDate());
|
||||||
|
$payees = $transaction->getPayees();
|
||||||
|
$payeeCount = count($payees);
|
||||||
|
|
||||||
if ($transaction->getPayeeUserId()) {
|
if ($payeeCount > 0) {
|
||||||
$this->payments[$transaction->getPayerUserId()][$transaction->getPayeeUserId()] += $sum;
|
foreach ($payees as $payee) {
|
||||||
|
$this->payments[$transaction->getPayerUserId()][$payee->getUserId()] += $sum / $payeeCount;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
foreach ($this->members as $payeeUserId => $member) {
|
foreach ($this->members as $payeeUserId => $member) {
|
||||||
$this->payments[$transaction->getPayerUserId()][$payeeUserId] += $sum / $membersCount;
|
$this->payments[$transaction->getPayerUserId()][$payeeUserId] += $sum / $membersCount;
|
||||||
@@ -71,20 +92,45 @@ class BalanceCalculator
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function calculateActualDebts(): array
|
private function calculateActualDebts(): void
|
||||||
{
|
{
|
||||||
$actualDebts = [];
|
$this->actualDebts = [];
|
||||||
|
|
||||||
foreach ($this->payments as $payerUserId => $paymentsOfPayer) {
|
foreach ($this->payments as $payerUserId => $paymentsOfPayer) {
|
||||||
foreach ($paymentsOfPayer as $payeeUserId => $sum) {
|
foreach ($paymentsOfPayer as $payeeUserId => $sum) {
|
||||||
$actualDebt = $this->payments[$payeeUserId][$payerUserId] - $sum;
|
$actualDebt = $this->payments[$payeeUserId][$payerUserId] - $sum;
|
||||||
|
|
||||||
if (round($actualDebt, $this->community->getMainCurrency()->getRoundDigits()) > 0.0) {
|
if (round($actualDebt, $this->community->getMainCurrency()->getRoundDigits()) > 0.0) {
|
||||||
$actualDebts[] = ['payer' => $this->members[$payerUserId], 'payee' => $this->members[$payeeUserId], 'amount' => $actualDebt];
|
$this->actualDebts[] = ['payer' => $this->members[$payerUserId], 'payee' => $this->members[$payeeUserId], 'amount' => $actualDebt];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $actualDebts;
|
private function calculateBalanceForUser(): array
|
||||||
|
{
|
||||||
|
$debtItems = [];
|
||||||
|
$debtBalance = 0.0;
|
||||||
|
$outstandingItems = [];
|
||||||
|
$outstandingBalance = 0.0;
|
||||||
|
foreach ($this->actualDebts as $debt) {
|
||||||
|
if ($debt['payer']->getId() === $this->user->getId()) {
|
||||||
|
$debtBalance += $debt['amount'];
|
||||||
|
$debtItems[] = $debt;
|
||||||
|
}
|
||||||
|
if ($debt['payee']->getId() === $this->user->getId()) {
|
||||||
|
$outstandingBalance += $debt['amount'];
|
||||||
|
$outstandingItems[] = $debt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$absoluteBalance = $outstandingBalance - $debtBalance;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'absoluteBalance' => $absoluteBalance,
|
||||||
|
'debtItems' => $debtItems,
|
||||||
|
'debtBalance' => $debtBalance,
|
||||||
|
'outstandingItems' => $outstandingItems,
|
||||||
|
'outstandingBalance' => $outstandingBalance
|
||||||
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ class ExchangeRateCalculator
|
|||||||
|
|
||||||
$currentExchangeRate = null;
|
$currentExchangeRate = null;
|
||||||
foreach ($this->exchangeRates[$currency->getId()] as $exchangeRate) {
|
foreach ($this->exchangeRates[$currency->getId()] as $exchangeRate) {
|
||||||
if ($exchangeRate->getValidFrom() > $time) {
|
if ($exchangeRate->getValidFromDate() > $time) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$currentExchangeRate = $exchangeRate;
|
$currentExchangeRate = $exchangeRate;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<?php namespace RVR\PersistentData\Model;
|
<?php namespace RVR\PersistentData\Model;
|
||||||
|
|
||||||
use DateTime;
|
use DateTime;
|
||||||
use SokoWeb\PersistentData\Model\Model;
|
use SokoWeb\PersistentData\Model\ModelWithSlug;
|
||||||
|
|
||||||
class Community extends Model
|
class Community extends ModelWithSlug
|
||||||
{
|
{
|
||||||
protected static string $table = 'communities';
|
protected static string $table = 'communities';
|
||||||
|
|
||||||
@@ -11,6 +11,8 @@ class Community extends Model
|
|||||||
|
|
||||||
protected static array $relations = ['main_currency' => Currency::class];
|
protected static array $relations = ['main_currency' => Currency::class];
|
||||||
|
|
||||||
|
protected static string $slugSource = 'name';
|
||||||
|
|
||||||
private string $name = '';
|
private string $name = '';
|
||||||
|
|
||||||
private string $currency = '';
|
private string $currency = '';
|
||||||
@@ -31,12 +33,12 @@ class Community extends Model
|
|||||||
$this->currency = $currency;
|
$this->currency = $currency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setMainCurrency(Currency $mainCurrency): void
|
public function setMainCurrency(?Currency $mainCurrency): void
|
||||||
{
|
{
|
||||||
$this->mainCurrency = $mainCurrency;
|
$this->mainCurrency = $mainCurrency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setMainCurrencyId(int $mainCurrencyId): void
|
public function setMainCurrencyId(?int $mainCurrencyId): void
|
||||||
{
|
{
|
||||||
$this->mainCurrencyId = $mainCurrencyId;
|
$this->mainCurrencyId = $mainCurrencyId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<?php namespace RVR\PersistentData\Model;
|
||||||
|
|
||||||
|
use DateTime;
|
||||||
|
use SokoWeb\PersistentData\Model\ModelWithSlug;
|
||||||
|
|
||||||
|
class Event extends ModelWithSlug
|
||||||
|
{
|
||||||
|
protected static string $table = 'events';
|
||||||
|
|
||||||
|
protected static array $fields = ['community_id', 'start', 'end', 'title', 'description'];
|
||||||
|
|
||||||
|
protected static array $relations = ['community' => Community::class];
|
||||||
|
|
||||||
|
protected static string $slugSource = 'title';
|
||||||
|
|
||||||
|
private ?Community $community = null;
|
||||||
|
|
||||||
|
private int $communityId;
|
||||||
|
|
||||||
|
private DateTime $start;
|
||||||
|
|
||||||
|
private DateTime $end;
|
||||||
|
|
||||||
|
private string $title = '';
|
||||||
|
|
||||||
|
private string $description = '';
|
||||||
|
|
||||||
|
public function setCommunity(Community $community): void
|
||||||
|
{
|
||||||
|
$this->community = $community;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCommunityId(int $communityId): void
|
||||||
|
{
|
||||||
|
$this->communityId = $communityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStartDate(DateTime $start): void
|
||||||
|
{
|
||||||
|
$this->start = $start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setStart(string $start): void
|
||||||
|
{
|
||||||
|
$this->start = new DateTime($start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEndDate(DateTime $end): void
|
||||||
|
{
|
||||||
|
$this->end = $end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEnd(string $end): void
|
||||||
|
{
|
||||||
|
$this->end = new DateTime($end);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTitle(string $title): void
|
||||||
|
{
|
||||||
|
$this->title = $title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDescription(string $description): void
|
||||||
|
{
|
||||||
|
$this->description = $description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommunity(): ?Community
|
||||||
|
{
|
||||||
|
return $this->community;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCommunityId(): int
|
||||||
|
{
|
||||||
|
return $this->communityId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStartDate(): DateTime
|
||||||
|
{
|
||||||
|
return $this->start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStart(): string
|
||||||
|
{
|
||||||
|
return $this->start->format('Y-m-d H:i:s');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEndDate(): DateTime
|
||||||
|
{
|
||||||
|
return $this->end;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEnd(): string
|
||||||
|
{
|
||||||
|
return $this->end->format('Y-m-d H:i:s');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle(): string
|
||||||
|
{
|
||||||
|
return $this->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return $this->description;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,19 +7,28 @@ class Transaction extends Model
|
|||||||
{
|
{
|
||||||
protected static string $table = 'transactions';
|
protected static string $table = 'transactions';
|
||||||
|
|
||||||
protected static array $fields = ['community_id', 'currency_id', 'payer_user_id', 'payee_user_id', 'description', 'sum', 'time'];
|
protected static array $fields = ['community_id', 'event_id', 'currency_id', 'payer_user_id', 'payee_user_id', 'description', 'sum', 'time'];
|
||||||
|
|
||||||
protected static array $relations = [
|
protected static array $relations = [
|
||||||
'community' => Community::class,
|
'community' => Community::class,
|
||||||
|
'event' => Event::class,
|
||||||
'currency' => Currency::class,
|
'currency' => Currency::class,
|
||||||
'payer_user' => User::class,
|
'payer_user' => User::class,
|
||||||
'payee_user' => User::class
|
'payee_user' => User::class
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected static array $multiRelations = [
|
||||||
|
'payees' => [TransactionPayee::class, 'transaction']
|
||||||
|
];
|
||||||
|
|
||||||
private ?Community $community = null;
|
private ?Community $community = null;
|
||||||
|
|
||||||
private int $communityId;
|
private int $communityId;
|
||||||
|
|
||||||
|
private ?Event $event = null;
|
||||||
|
|
||||||
|
private ?int $eventId = null;
|
||||||
|
|
||||||
private ?Currency $currency = null;
|
private ?Currency $currency = null;
|
||||||
|
|
||||||
private int $currencyId;
|
private int $currencyId;
|
||||||
@@ -32,6 +41,8 @@ class Transaction extends Model
|
|||||||
|
|
||||||
private ?int $payeeUserId = null;
|
private ?int $payeeUserId = null;
|
||||||
|
|
||||||
|
private ?array $payees = null;
|
||||||
|
|
||||||
private string $description = '';
|
private string $description = '';
|
||||||
|
|
||||||
private float $sum = 0.0;
|
private float $sum = 0.0;
|
||||||
@@ -48,6 +59,16 @@ class Transaction extends Model
|
|||||||
$this->communityId = $communityId;
|
$this->communityId = $communityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setEvent(?Event $event): void
|
||||||
|
{
|
||||||
|
$this->event = $event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setEventId(?int $eventId): void
|
||||||
|
{
|
||||||
|
$this->eventId = $eventId;
|
||||||
|
}
|
||||||
|
|
||||||
public function setCurrency(Currency $currency): void
|
public function setCurrency(Currency $currency): void
|
||||||
{
|
{
|
||||||
$this->currency = $currency;
|
$this->currency = $currency;
|
||||||
@@ -78,6 +99,11 @@ class Transaction extends Model
|
|||||||
$this->payeeUserId = $payeeUserId;
|
$this->payeeUserId = $payeeUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setPayees(array $payees): void
|
||||||
|
{
|
||||||
|
$this->payees = $payees;
|
||||||
|
}
|
||||||
|
|
||||||
public function setDescription(string $description): void
|
public function setDescription(string $description): void
|
||||||
{
|
{
|
||||||
$this->description = $description;
|
$this->description = $description;
|
||||||
@@ -108,6 +134,16 @@ class Transaction extends Model
|
|||||||
return $this->communityId;
|
return $this->communityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEvent(): ?Event
|
||||||
|
{
|
||||||
|
return $this->event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEventId(): ?int
|
||||||
|
{
|
||||||
|
return $this->eventId;
|
||||||
|
}
|
||||||
|
|
||||||
public function getCurrency(): ?Currency
|
public function getCurrency(): ?Currency
|
||||||
{
|
{
|
||||||
return $this->currency;
|
return $this->currency;
|
||||||
@@ -138,6 +174,11 @@ class Transaction extends Model
|
|||||||
return $this->payeeUserId;
|
return $this->payeeUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPayees(): ?array
|
||||||
|
{
|
||||||
|
return $this->payees;
|
||||||
|
}
|
||||||
|
|
||||||
public function getDescription(): string
|
public function getDescription(): string
|
||||||
{
|
{
|
||||||
return $this->description;
|
return $this->description;
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
<?php namespace RVR\PersistentData\Model;
|
||||||
|
|
||||||
|
use SokoWeb\PersistentData\Model\Model;
|
||||||
|
|
||||||
|
class TransactionPayee extends Model
|
||||||
|
{
|
||||||
|
protected static string $table = 'transaction_payees';
|
||||||
|
|
||||||
|
protected static array $fields = ['transaction_id', 'user_id'];
|
||||||
|
|
||||||
|
protected static array $relations = ['transaction' => Transaction::class, 'user' => User::class];
|
||||||
|
|
||||||
|
private ?Transaction $transaction = null;
|
||||||
|
|
||||||
|
private ?int $transactionId = null;
|
||||||
|
|
||||||
|
private ?User $user = null;
|
||||||
|
|
||||||
|
private ?int $userId = null;
|
||||||
|
|
||||||
|
public function setTransaction(Transaction $transaction): void
|
||||||
|
{
|
||||||
|
$this->transaction = $transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setTransactionId(int $transactionId): void
|
||||||
|
{
|
||||||
|
$this->transactionId = $transactionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(User $user): void
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUserId(int $userId): void
|
||||||
|
{
|
||||||
|
$this->userId = $userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTransaction(): ?Transaction
|
||||||
|
{
|
||||||
|
return $this->transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTransactionId(): ?int
|
||||||
|
{
|
||||||
|
return $this->transactionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser(): ?User
|
||||||
|
{
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUserId(): ?int
|
||||||
|
{
|
||||||
|
return $this->userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,12 +15,16 @@ class CommunityMemberRepository
|
|||||||
|
|
||||||
public function getAllByCommunity(Community $community, bool $useRelations = false, array $withRelations = []): Generator
|
public function getAllByCommunity(Community $community, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
{
|
{
|
||||||
$select = new Select(\Container::$dbConnection);
|
$select = $this->selectAllByCommunity($community);
|
||||||
$select->where('community_id', '=', $community->getId());
|
|
||||||
|
|
||||||
yield from \Container::$persistentDataManager->selectMultipleFromDb($select, CommunityMember::class, $useRelations, $withRelations);
|
yield from \Container::$persistentDataManager->selectMultipleFromDb($select, CommunityMember::class, $useRelations, $withRelations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function countAllByCommunity(Community $community): int
|
||||||
|
{
|
||||||
|
return $this->selectAllByCommunity($community)->count();
|
||||||
|
}
|
||||||
|
|
||||||
public function getAllByUser(User $user, bool $useRelations = false, array $withRelations = []): Generator
|
public function getAllByUser(User $user, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
{
|
{
|
||||||
$select = new Select(\Container::$dbConnection);
|
$select = new Select(\Container::$dbConnection);
|
||||||
@@ -37,4 +41,11 @@ class CommunityMemberRepository
|
|||||||
|
|
||||||
return \Container::$persistentDataManager->selectFromDb($select, CommunityMember::class);
|
return \Container::$persistentDataManager->selectFromDb($select, CommunityMember::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function selectAllByCommunity(Community $community): Select
|
||||||
|
{
|
||||||
|
$select = new Select(\Container::$dbConnection, CommunityMember::getTable());
|
||||||
|
$select->where('community_id', '=', $community->getId());
|
||||||
|
return $select;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,4 +8,9 @@ class CommunityRepository
|
|||||||
{
|
{
|
||||||
return \Container::$persistentDataManager->selectFromDbById($id, Community::class);
|
return \Container::$persistentDataManager->selectFromDbById($id, Community::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getBySlug(string $slug): ?Community
|
||||||
|
{
|
||||||
|
return \Container::$persistentDataManager->selectFromDbBySlug($slug, Community::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<?php namespace RVR\Repository;
|
||||||
|
|
||||||
|
use Container;
|
||||||
|
use DateTime;
|
||||||
|
use DateInterval;
|
||||||
|
use Generator;
|
||||||
|
use RVR\PersistentData\Model\Community;
|
||||||
|
use RVR\PersistentData\Model\Event;
|
||||||
|
use RVR\PersistentData\Model\User;
|
||||||
|
use SokoWeb\Database\Query\Select;
|
||||||
|
|
||||||
|
class EventRepository
|
||||||
|
{
|
||||||
|
public function getById(int $id): ?Event
|
||||||
|
{
|
||||||
|
return Container::$persistentDataManager->selectFromDbById($id, Event::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBySlug(string $slug): ?Event
|
||||||
|
{
|
||||||
|
return \Container::$persistentDataManager->selectFromDbBySlug($slug, Event::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllByCommunity(Community $community, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
|
{
|
||||||
|
$select = $this->selectAllByCommunity($community);
|
||||||
|
|
||||||
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Event::class, $useRelations, $withRelations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function countAllByCommunity(Community $community): int
|
||||||
|
{
|
||||||
|
return $this->selectAllByCommunity($community)->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUpcomingAndRecentByCommunity(Community $community, DateTime $from, int $days, int $limit, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
|
{
|
||||||
|
$select = $this->selectAllByCommunity($community);
|
||||||
|
$this->selectUpcomingAndRecent($select, $from, $days);
|
||||||
|
$select->orderBy('start', 'DESC');
|
||||||
|
$select->limit($limit, 0);
|
||||||
|
|
||||||
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Event::class, $useRelations, $withRelations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUpcomingAndRecentByUser(User $user, DateTime $from, int $days, int $limit, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
|
{
|
||||||
|
$select = $this->selectAllByUser($user);
|
||||||
|
$this->selectUpcomingAndRecent($select, $from, $days);
|
||||||
|
$select->orderBy('start', 'DESC');
|
||||||
|
$select->limit($limit, 0);
|
||||||
|
|
||||||
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Event::class, $useRelations, $withRelations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPagedByCommunity(Community $community, int $page, int $itemsPerPage, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
|
{
|
||||||
|
$select = $this->selectAllByCommunity($community);
|
||||||
|
$select->orderBy('start', 'DESC');
|
||||||
|
$select->paginate($page, $itemsPerPage);
|
||||||
|
|
||||||
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Event::class, $useRelations, $withRelations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function searchByTitle(Community $community, string $title): Generator
|
||||||
|
{
|
||||||
|
$select = $this->selectAllByCommunity($community);
|
||||||
|
$select->where('title', 'LIKE', '%' . $title . '%');
|
||||||
|
$select->orderBy('start', 'DESC');
|
||||||
|
$select->limit(10);
|
||||||
|
|
||||||
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Event::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function selectAllByCommunity(Community $community)
|
||||||
|
{
|
||||||
|
$select = new Select(Container::$dbConnection, Event::getTable());
|
||||||
|
$select->where('community_id', '=', $community->getId());
|
||||||
|
return $select;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function selectAllByUser(User $user)
|
||||||
|
{
|
||||||
|
$select = new Select(Container::$dbConnection, Event::getTable());
|
||||||
|
$select->innerJoin('communities', ['communities', 'id'], '=', ['events', 'community_id']);
|
||||||
|
$select->innerJoin('community_members', ['communities', 'id'], '=', ['community_members', 'community_id']);
|
||||||
|
$select->where(['community_members', 'user_id'], '=', $user->getId());
|
||||||
|
return $select;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function selectUpcomingAndRecent(Select $select, DateTime $from, int $days)
|
||||||
|
{
|
||||||
|
$select->where(function (Select $select) use ($from, $days) {
|
||||||
|
$select->where('start', '<', (clone $from)->add(DateInterval::createFromDateString("$days days"))->format('Y-m-d H:i:s'));
|
||||||
|
$select->orWhere('end', '>', (clone $from)->sub(DateInterval::createFromDateString("$days days"))->format('Y-m-d H:i:s'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<?php namespace RVR\Repository;
|
||||||
|
|
||||||
|
use Container;
|
||||||
|
use Generator;
|
||||||
|
use RVR\PersistentData\Model\Transaction;
|
||||||
|
use RVR\PersistentData\Model\TransactionPayee;
|
||||||
|
use SokoWeb\Database\Query\Select;
|
||||||
|
|
||||||
|
class TransactionPayeeRepository
|
||||||
|
{
|
||||||
|
public function getById(int $id): ?TransactionPayee
|
||||||
|
{
|
||||||
|
return Container::$persistentDataManager->selectFromDbById($id, TransactionPayee::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllByTransaction(Transaction $transaction, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
|
{
|
||||||
|
$select = new Select(Container::$dbConnection);
|
||||||
|
$select->where('transaction_id', '=', $transaction->getId());
|
||||||
|
|
||||||
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, TransactionPayee::class, $useRelations, $withRelations);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ use Container;
|
|||||||
use Generator;
|
use Generator;
|
||||||
use RVR\PersistentData\Model\Community;
|
use RVR\PersistentData\Model\Community;
|
||||||
use RVR\PersistentData\Model\Currency;
|
use RVR\PersistentData\Model\Currency;
|
||||||
|
use RVR\PersistentData\Model\Event;
|
||||||
use RVR\PersistentData\Model\Transaction;
|
use RVR\PersistentData\Model\Transaction;
|
||||||
use RVR\PersistentData\Model\User;
|
use RVR\PersistentData\Model\User;
|
||||||
use SokoWeb\Database\Query\Select;
|
use SokoWeb\Database\Query\Select;
|
||||||
@@ -22,11 +23,23 @@ class TransactionRepository
|
|||||||
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Transaction::class, $useRelations, $withRelations);
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Transaction::class, $useRelations, $withRelations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAllByEvent(Event $event, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
|
{
|
||||||
|
$select = $this->selectAllByEvent($event);
|
||||||
|
|
||||||
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Transaction::class, $useRelations, $withRelations);
|
||||||
|
}
|
||||||
|
|
||||||
public function countAllByCommunity(Community $community): int
|
public function countAllByCommunity(Community $community): int
|
||||||
{
|
{
|
||||||
return $this->selectAllByCommunity($community)->count();
|
return $this->selectAllByCommunity($community)->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function countAllByEvent(Event $event): int
|
||||||
|
{
|
||||||
|
return $this->selectAllByEvent($event)->count();
|
||||||
|
}
|
||||||
|
|
||||||
public function isAnyForUser(User $user): bool
|
public function isAnyForUser(User $user): bool
|
||||||
{
|
{
|
||||||
$select = new Select(Container::$dbConnection, Transaction::getTable());
|
$select = new Select(Container::$dbConnection, Transaction::getTable());
|
||||||
@@ -53,12 +66,20 @@ class TransactionRepository
|
|||||||
return $select->count() > 0;
|
return $select->count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPagedByCommunity(Community $community, int $start, int $limit, bool $useRelations = false, array $withRelations = []): Generator
|
public function getPagedByCommunity(Community $community, int $page, int $itemsPerPage, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
{
|
{
|
||||||
$select = new Select(Container::$dbConnection);
|
$select = $this->selectAllByCommunity($community);
|
||||||
$select->where('community_id', '=', $community->getId());
|
|
||||||
$select->orderBy('time', 'DESC');
|
$select->orderBy('time', 'DESC');
|
||||||
$select->limit($limit, $start);
|
$select->paginate($page, $itemsPerPage);
|
||||||
|
|
||||||
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Transaction::class, $useRelations, $withRelations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPagedByEvent(Event $event, int $page, int $itemsPerPage, bool $useRelations = false, array $withRelations = []): Generator
|
||||||
|
{
|
||||||
|
$select = $this->selectAllByEvent($event);
|
||||||
|
$select->orderBy('time', 'DESC');
|
||||||
|
$select->paginate($page, $itemsPerPage);
|
||||||
|
|
||||||
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Transaction::class, $useRelations, $withRelations);
|
yield from Container::$persistentDataManager->selectMultipleFromDb($select, Transaction::class, $useRelations, $withRelations);
|
||||||
}
|
}
|
||||||
@@ -69,4 +90,11 @@ class TransactionRepository
|
|||||||
$select->where('community_id', '=', $community->getId());
|
$select->where('community_id', '=', $community->getId());
|
||||||
return $select;
|
return $select;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function selectAllByEvent(Event $event)
|
||||||
|
{
|
||||||
|
$select = new Select(Container::$dbConnection, Transaction::getTable());
|
||||||
|
$select->where('event_id', '=', $event->getId());
|
||||||
|
return $select;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+33
-13
@@ -9,32 +9,52 @@
|
|||||||
<?php if ($user['password'] !== null && $user['google_sub'] !== null): ?>
|
<?php if ($user['password'] !== null && $user['google_sub'] !== null): ?>
|
||||||
<p class="justify small">Please confirm your identity with your password or with Google to modify your account.</p>
|
<p class="justify small">Please confirm your identity with your password or with Google to modify your account.</p>
|
||||||
<div class="inputWithButton">
|
<div class="inputWithButton">
|
||||||
<input type="password" class="text" name="password" placeholder="Current password" required minlength="6" autofocus><!--
|
<input type="password" class="text" name="password" autocomplete="current-password" required minlength="6" autofocus><!--
|
||||||
--><button id="authenticateWithGoogleButton" class="yellow" type="button">Google</button>
|
--><button id="authenticateWithGoogleButton" class="yellow" type="button"><i class="fa-brands fa-google"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<?php elseif ($user['password'] !== null): ?>
|
<?php elseif ($user['password'] !== null): ?>
|
||||||
<p class="justify small">Please confirm your identity with your password to modify your account.</p>
|
<p class="justify small">Please confirm your identity with your password to modify your account.</p>
|
||||||
<input type="password" class="text big fullWidth" name="password" placeholder="Current password" required minlength="6" autofocus>
|
<input type="password" class="text big fullWidth" name="password" autocomplete="current-password" required minlength="6" autofocus>
|
||||||
<?php elseif ($user['google_sub'] !== null): ?>
|
<?php elseif ($user['google_sub'] !== null): ?>
|
||||||
<p class="justify small">Please confirm your identity with Google to modify your account.</p>
|
<p class="justify small">Please confirm your identity with Google to modify your account.</p>
|
||||||
<div class="inputWithButton">
|
<div class="inputWithButton">
|
||||||
<input type="text" class="text" name="password" placeholder="Authenticate with Google..." disabled><!--
|
<input type="text" class="text" name="password" placeholder="Authenticate with Google..." disabled><!--
|
||||||
--><button id="authenticateWithGoogleButton" class="yellow" type="button">Google</button>
|
--><button id="authenticateWithGoogleButton" class="yellow" type="button"><i class="fa-brands fa-google"></i></button>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<hr>
|
<hr>
|
||||||
<input type="email" class="text big fullWidth" name="email" placeholder="Email address" value="<?= $user['email'] ?>">
|
<p class="formLabel">Email address</p>
|
||||||
<input type="text" class="text big fullWidth marginTop" name="username" placeholder="Username" value="<?= $user['username'] ?>">
|
<input type="email" class="text big fullWidth" name="email" autocomplete="username" value="<?= $user['email'] ?>">
|
||||||
<input type="password" class="text big fullWidth marginTop" name="password_new" placeholder="New password" minlength="6">
|
<p class="formLabel marginTop">Username</p>
|
||||||
<input type="password" class="text big fullWidth marginTop" name="password_new_confirm" placeholder="New password confirmation" minlength="6">
|
<input type="text" class="text big fullWidth" name="username" value="<?= $user['username'] ?>">
|
||||||
|
<p class="formLabel marginTop">New password</p>
|
||||||
|
<input type="password" class="text big fullWidth" name="password_new" autocomplete="new-password" minlength="6">
|
||||||
|
<p class="formLabel marginTop">New password confirmation</p>
|
||||||
|
<input type="password" class="text big fullWidth" name="password_new_confirm" autocomplete="new-password" minlength="6">
|
||||||
<hr>
|
<hr>
|
||||||
<input type="text" class="text big fullWidth marginTop" name="full_name" placeholder="Full name" value="<?= $user['full_name'] ?>" disabled>
|
<p class="formLabel marginTop">Full name</p>
|
||||||
<input type="text" class="text big fullWidth marginTop" name="nickname" placeholder="Nickname" value="<?= $user['nickname'] ?>">
|
<input type="text" class="text big fullWidth" name="full_name" value="<?= $user['full_name'] ?>" disabled>
|
||||||
<input type="text" class="text big fullWidth marginTop" name="phone" placeholder="Phone" value="<?= $user['phone'] ?>">
|
<p class="formLabel marginTop marginTop">Nickname</p>
|
||||||
<input type="text" class="text big fullWidth marginTop" name="id_number" placeholder="ID number" value="<?= $user['id_number'] ?>">
|
<input type="text" class="text big fullWidth" name="nickname" value="<?= $user['nickname'] ?>">
|
||||||
|
<p class="formLabel marginTop marginTop">Phone</p>
|
||||||
|
<input type="text" class="text big fullWidth" name="phone" value="<?= $user['phone'] ?>">
|
||||||
|
<p class="formLabel marginTop marginTop">ID number</p>
|
||||||
|
<input type="text" class="text big fullWidth" name="id_number" value="<?= $user['id_number'] ?>">
|
||||||
<p id="accountFormError" class="formError justify marginTop"></p>
|
<p id="accountFormError" class="formError justify marginTop"></p>
|
||||||
<div class="right marginTop">
|
<div class="right marginTop">
|
||||||
<button type="submit" name="submit_button" disabled>Save</button>
|
<button type="submit" name="submit_button" disabled><i class="fa-regular fa-floppy-disk"></i> Save</button>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="center">
|
||||||
|
<?php if ($user['google_sub'] === null): ?>
|
||||||
|
<a class="button yellow" href="<?= Container::$routeCollection->getRoute('account.googleConnect')->generateLink() ?>" title="Connect with Google"><i class="fa-solid fa-link"></i> Connect with Google</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php if ($user['password'] !== null): ?>
|
||||||
|
<a class="button yellow" href="<?= Container::$routeCollection->getRoute('account.googleDisconnect')->generateLink() ?>" title="Disconnect from Google"><i class="fa-solid fa-link-slash"></i> Disconnect from Google</a>
|
||||||
|
<?php else: ?>
|
||||||
|
<p class="bold small">Your account does not have a password. Please set a password if you want to disconnect your account from Google.</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
@extends(templates/layout_normal)
|
||||||
|
|
||||||
|
@section(main)
|
||||||
|
<h2>Connect with Google</h2>
|
||||||
|
<div class="box compactBox">
|
||||||
|
<?php if (!$success): ?>
|
||||||
|
<p class="error justify"><?= $error ?></p>
|
||||||
|
<?php else: ?>
|
||||||
|
<form id="connectGoogleForm" action="<?= Container::$routeCollection->getRoute('account.googleConnect-action')->generateLink() ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('account')->generateLink() ?>">
|
||||||
|
<p class="justify marginBottom">Your account will be connected with the following Google account: <b><?= $googleAccount ?></b></p>
|
||||||
|
<input type="email" style="display: none;" name="email" autocomplete="username" value="<?= $userEmail ?>">
|
||||||
|
<p class="formLabel marginTop">Password</p>
|
||||||
|
<input type="password" class="text big fullWidth" name="password" autocomplete="current-password" required minlength="6" autofocus>
|
||||||
|
<p class="formError justify marginTop"></p>
|
||||||
|
<div class="right marginTop">
|
||||||
|
<button class="marginRight" type="submit" name="submit"><i class="fa-solid fa-link"></i> Connect</button><!--
|
||||||
|
--><a class="button gray" href="<?= Container::$routeCollection->getRoute('account')->generateLink() ?>" title="Back to account">Cancel</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
@extends(templates/layout_normal)
|
||||||
|
|
||||||
|
@section(main)
|
||||||
|
<h2>Disconnect from Google</h2>
|
||||||
|
<div class="box compactBox">
|
||||||
|
<form id="connectGoogleForm" action="<?= Container::$routeCollection->getRoute('account.googleDisconnect-action')->generateLink() ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('account')->generateLink() ?>">
|
||||||
|
<p class="justify marginBottom">Your account will be disconnected from the currently set Google account.</p>
|
||||||
|
<input type="email" style="display: none;" name="email" autocomplete="username" value="<?= $userEmail ?>">
|
||||||
|
<p class="formLabel marginTop">Password</p>
|
||||||
|
<input type="password" class="text big fullWidth" name="password" autocomplete="current-password" required minlength="6" autofocus>
|
||||||
|
<p class="formError justify marginTop"></p>
|
||||||
|
<div class="right marginTop">
|
||||||
|
<button class="red marginRight" type="submit" name="submit"><i class="fa-solid fa-link-slash"></i> Disconnect</button><!--
|
||||||
|
--><a class="button gray" href="<?= Container::$routeCollection->getRoute('account')->generateLink() ?>" title="Back to account">Cancel</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
@@ -4,22 +4,26 @@
|
|||||||
<h2>
|
<h2>
|
||||||
<?= $community->getName() ?>
|
<?= $community->getName() ?>
|
||||||
<?php if ($editPermission): ?>
|
<?php if ($editPermission): ?>
|
||||||
<span class="small">[<a href="<?= Container::$routeCollection->getRoute('community.edit')->generateLink(['communityId' => $community->getId()]) ?>">edit</a>]</span>
|
<span class="small">[<a href="<?= Container::$routeCollection->getRoute('community.edit')->generateLink(['communitySlug' => $community->getSlug()]) ?>">edit</a>]</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p class="marginTop"><a href="<?= Container::$routeCollection->getRoute('community.settings')->generateLink(['communityId' => $community->getId()]) ?>">Settings</a></p>
|
<p class="marginTop"><a href="<?= Container::$routeCollection->getRoute('community.settings')->generateLink(['communitySlug' => $community->getSlug()]) ?>">Settings</a></p>
|
||||||
|
|
||||||
<div class="gridContainer marginTop">
|
<div class="gridContainer marginTop">
|
||||||
<div>
|
<div>
|
||||||
<h3 class="marginBottom">Upcoming events</h3>
|
<h3 class="marginBottom">Upcoming and recent events</h3>
|
||||||
<?php if (count($upcomingEvents) > 0): ?>
|
<?php if (count($upcomingAndRecentEvents) > 0): ?>
|
||||||
<?php foreach ($upcomingEvents as $event): ?>
|
<?php foreach ($upcomingAndRecentEvents as $event): ?>
|
||||||
<!-- todo -->
|
<p>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.event')->generateLink(['communitySlug' => $community->getSlug(), 'eventSlug' => $event->getSlug()]) ?>"><?= $event->getTitle() ?></a>
|
||||||
|
<span class="small"><?= $event->getStartDate()->format('Y-m-d') ?> – <?= $event->getEndDate()->format('Y-m-d') ?></span>
|
||||||
|
</p>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<p>There is no upcoming event.</p>
|
<p>There is no event to show.</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<p class="marginTop"><a href="<?= Container::$routeCollection->getRoute('community.events')->generateLink(['communitySlug' => $community->getSlug()]) ?>">All events</a> | <a href="<?= Container::$routeCollection->getRoute('community.events.new')->generateLink(['communitySlug' => $community->getSlug()]) ?>">New event</a></p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<?php
|
<?php
|
||||||
@@ -27,7 +31,7 @@
|
|||||||
$mainCurrencyRoundDigits = $community->getMainCurrency()->getRoundDigits();
|
$mainCurrencyRoundDigits = $community->getMainCurrency()->getRoundDigits();
|
||||||
?>
|
?>
|
||||||
<h3 class="marginBottom">Finances</h3>
|
<h3 class="marginBottom">Finances</h3>
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId()]) ?>">Transactions</a>
|
<p><a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communitySlug' => $community->getSlug()]) ?>">Transactions</a> | <a href="<?= Container::$routeCollection->getRoute('community.transactions.new')->generateLink(['communitySlug' => $community->getSlug()]) ?>">New transaction</a></p>
|
||||||
<table class="fullWidth marginTop">
|
<table class="fullWidth marginTop">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="bold">You owe</td>
|
<td class="bold">You owe</td>
|
||||||
|
|||||||
@@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
@section(main)
|
@section(main)
|
||||||
<h2>
|
<h2>
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()]) ?>"><?= $community->getName() ?></a> »
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.settings')->generateLink(['communityId' => $community->getId()]) ?>">Settings</a> »
|
<a href="<?= Container::$routeCollection->getRoute('community.settings')->generateLink(['communitySlug' => $community->getSlug()]) ?>">Settings</a> »
|
||||||
Edit currencies
|
Edit currencies
|
||||||
</h2>
|
</h2>
|
||||||
<div class="box compactBox">
|
<div class="box compactBox">
|
||||||
<table class="fullWidth">
|
<table class="fullWidth">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: calc(100% / 3); text-align: left;">Currency</th>
|
<th style="width: calc(100% / 3); text-align: left;">Code</th>
|
||||||
<th style="width: calc(100% / 3); text-align: left;">Round digits</th>
|
<th style="width: calc(100% / 3); text-align: left;">Round digits</th>
|
||||||
<th style="width: calc(100% / 3);"></th>
|
<th style="width: calc(100% / 3);"></th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -18,31 +18,31 @@
|
|||||||
<?php foreach ($currencies as $currency): ?>
|
<?php foreach ($currencies as $currency): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<form id="editCurrency_<?= $currency->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.currencies.edit-action')->generateLink(['communityId' => $community->getId(), 'currency_id' => $currency->getId()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="code,round_digits"></form>
|
<form id="editCurrency_<?= $currency->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.currencies.edit-action')->generateLink(['communitySlug' => $community->getSlug(), 'currency_id' => $currency->getId()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="code,round_digits"></form>
|
||||||
<form id="deleteCurrency_<?= $currency->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.currencies.delete-action')->generateLink(['communityId' => $community->getId(), 'currency_id' => $currency->getId()]) ?>" method="post" data-reload-on-success="true"></form>
|
<form id="deleteCurrency_<?= $currency->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.currencies.delete-action')->generateLink(['communitySlug' => $community->getSlug(), 'currency_id' => $currency->getId()]) ?>" method="post" data-reload-on-success="true"></form>
|
||||||
<input type="text" form="editCurrency_<?= $currency->getId() ?>" class="text fullWidth" name="code" value="<?= $currency->getCode() ?>" maxlength="3" required>
|
<input type="text" form="editCurrency_<?= $currency->getId() ?>" class="text fullWidth" name="code" value="<?= $currency->getCode() ?>" maxlength="3" required>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="number" form="editCurrency_<?= $currency->getId() ?>" class="text fullWidth" name="round_digits" value="<?= $currency->getRoundDigits() ?>" min="0" max="9" required>
|
<input type="number" form="editCurrency_<?= $currency->getId() ?>" class="text fullWidth" name="round_digits" value="<?= $currency->getRoundDigits() ?>" min="0" max="9" required>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: right; font-size: 0;">
|
<td style="text-align: right; font-size: 0;">
|
||||||
<button type="submit" form="editCurrency_<?= $currency->getId() ?>" name="submit_button" class="small" disabled>Save</button>
|
<button type="submit" form="editCurrency_<?= $currency->getId() ?>" name="submit_button" class="small" disabled><i class="fa-regular fa-floppy-disk"></i></button>
|
||||||
<?php if ($currency->getId() !== $community->getMainCurrencyId()): ?>
|
<?php if ($currency->getId() !== $community->getMainCurrencyId()): ?>
|
||||||
<button type="submit" form="deleteCurrency_<?= $currency->getId() ?>" name="submit_button" data-confirmation="Are you sure you want to delete this currency?" class="small red marginLeft">Delete</button>
|
<button type="submit" form="deleteCurrency_<?= $currency->getId() ?>" name="submit_button" data-confirmation="Are you sure you want to delete this currency?" data-confirmation-button='<i class="fa-regular fa-trash-can"></i> Delete' class="small red marginLeft"><i class="fa-regular fa-trash-can"></i></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<form id="newCurrency" action="<?= Container::$routeCollection->getRoute('community.currencies.new-action')->generateLink(['communityId' => $community->getId()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="code,round_digits"></form>
|
<form id="newCurrency" action="<?= Container::$routeCollection->getRoute('community.currencies.new-action')->generateLink(['communitySlug' => $community->getSlug()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="code,round_digits"></form>
|
||||||
<input type="text" form="newCurrency" class="text fullWidth" name="code" placeholder="Currency" maxlength="3" required>
|
<input type="text" form="newCurrency" class="text fullWidth" name="code" maxlength="3" required>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="number" form="newCurrency" class="text fullWidth" name="round_digits" placeholder="Round digits" min="0" max="9" required>
|
<input type="number" form="newCurrency" class="text fullWidth" name="round_digits" min="0" max="9" required>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: right;">
|
<td style="text-align: right;">
|
||||||
<button type="submit" form="newCurrency" name="submit_button" class="small" disabled>Add</button>
|
<button type="submit" form="newCurrency" name="submit_button" class="small" disabled><i class="fa-regular fa-plus"></i></button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
@section(main)
|
@section(main)
|
||||||
<h2>
|
<h2>
|
||||||
<?php if (isset($community)): ?>
|
<?php if (isset($community)): ?>
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()]) ?>"><?= $community->getName() ?></a> »
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
Edit
|
Edit
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
New community
|
New community
|
||||||
@@ -12,19 +12,28 @@
|
|||||||
<div class="box compactBox">
|
<div class="box compactBox">
|
||||||
<?php
|
<?php
|
||||||
$formAction = isset($community) ?
|
$formAction = isset($community) ?
|
||||||
Container::$routeCollection->getRoute('community.edit-action')->generateLink(['communityId' => $community->getId()]) :
|
Container::$routeCollection->getRoute('community.edit-action')->generateLink(['communitySlug' => $community->getSlug()]) :
|
||||||
Container::$routeCollection->getRoute('community.new-action')->generateLink();
|
Container::$routeCollection->getRoute('community.new-action')->generateLink();
|
||||||
?>
|
?>
|
||||||
<form id="communityForm" action="<?= $formAction ?>" method="post" data-redirect-on-success="true">
|
<form id="communityForm" action="<?= $formAction ?>" method="post" data-redirect-on-success="true">
|
||||||
<input type="text" class="text big fullWidth" name="name" placeholder="Name" value="<?= isset($community) ? $community->getName() : '' ?>" required>
|
<p class="formLabel">Name</p>
|
||||||
|
<input type="text" class="text big fullWidth" name="name" value="<?= isset($community) ? $community->getName() : '' ?>" required>
|
||||||
<?php if (!isset($community)): ?>
|
<?php if (!isset($community)): ?>
|
||||||
<input type="text" class="text big fullWidth marginTop" name="main_currency_code" placeholder="Main currency" maxlength="3" required>
|
<p class="formLabel marginTop">Main currency code</p>
|
||||||
<input type="number" class="text big fullWidth marginTop" name="main_currency_round_digits" placeholder="Main currency round digits" min="0" max="9" required>
|
<input type="text" class="text big fullWidth" name="main_currency_code" maxlength="3" required>
|
||||||
|
<p class="formLabel marginTop">Main currency round digits</p>
|
||||||
|
<input type="number" class="text big fullWidth" name="main_currency_round_digits" min="0" max="9" required>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<p id="communityFormError" class="formError justify marginTop"></p>
|
<p id="communityFormError" class="formError justify marginTop"></p>
|
||||||
<div class="right marginTop">
|
<div class="right marginTop" style="font-size: 0;">
|
||||||
<button type="submit" name="submit_button"><?= isset($community) ? 'Save' : 'Create' ?></button>
|
<button type="submit" name="submit_button"><?= isset($community) ? '<i class="fa-regular fa-floppy-disk"></i> Save' : '<i class="fa-regular fa-plus"></i> Create' ?></button>
|
||||||
|
<?php if (isset($community)): ?>
|
||||||
|
<button type="submit" form="deleteCommunity" name="submit_button" data-confirmation="Are you sure you want to delete this community?" class="red marginLeft"><i class="fa-regular fa-trash-can"></i> Delete</button>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<?php if (isset($community)): ?>
|
||||||
|
<form id="deleteCommunity" action="<?= Container::$routeCollection->getRoute('community.delete-action')->generateLink(['communitySlug' => $community->getSlug()]) ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('home')->generateLink() ?>"></form>
|
||||||
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
@@ -1,20 +1,20 @@
|
|||||||
@css(/static/node_modules/tom-select/dist/css/tom-select.min.css)
|
@css(node_modules/tom-select/dist/css/tom-select.min.css)
|
||||||
@js(/static/node_modules/tom-select/dist/js/tom-select.base.min.js)
|
@js(node_modules/tom-select/dist/js/tom-select.base.min.js)
|
||||||
@js(js/communities/community_members.js)
|
@js(js/communities/community_members.js)
|
||||||
|
|
||||||
@extends(templates/layout_normal)
|
@extends(templates/layout_normal)
|
||||||
|
|
||||||
@section(main)
|
@section(main)
|
||||||
<h2>
|
<h2>
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()]) ?>"><?= $community->getName() ?></a> »
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.settings')->generateLink(['communityId' => $community->getId()]) ?>">Settings</a> »
|
<a href="<?= Container::$routeCollection->getRoute('community.settings')->generateLink(['communitySlug' => $community->getSlug()]) ?>">Settings</a> »
|
||||||
Edit members
|
Edit members
|
||||||
</h2>
|
</h2>
|
||||||
<div class="box compactBox">
|
<div class="box compactBox">
|
||||||
<table class="fullWidth">
|
<table class="fullWidth">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 50%;"></th>
|
<th style="width: 50%;">User</th>
|
||||||
<th style="width: 25%; text-align: center;">Owner</th>
|
<th style="width: 25%; text-align: center;">Owner</th>
|
||||||
<th style="width: 25%;"></th>
|
<th style="width: 25%;"></th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -23,8 +23,8 @@
|
|||||||
<?php $editable = $member->getUserId() !== Container::$request->user()->getUniqueId(); ?>
|
<?php $editable = $member->getUserId() !== Container::$request->user()->getUniqueId(); ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<form id="editMember_<?= $member->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.members.edit-action')->generateLink(['communityId' => $community->getId(), 'community_member_id' => $member->getId()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="owner"></form>
|
<form id="editMember_<?= $member->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.members.edit-action')->generateLink(['communitySlug' => $community->getSlug(), 'community_member_id' => $member->getId()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="owner"></form>
|
||||||
<form id="deleteMember_<?= $member->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.members.delete-action')->generateLink(['communityId' => $community->getId(), 'community_member_id' => $member->getId()]) ?>" method="post" data-reload-on-success="true"></form>
|
<form id="deleteMember_<?= $member->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.members.delete-action')->generateLink(['communitySlug' => $community->getSlug(), 'community_member_id' => $member->getId()]) ?>" method="post" data-reload-on-success="true"></form>
|
||||||
<?= $member->getUser()->getDisplayName() ?>
|
<?= $member->getUser()->getDisplayName() ?>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: center;">
|
<td style="text-align: center;">
|
||||||
@@ -32,22 +32,22 @@
|
|||||||
</td>
|
</td>
|
||||||
<td style="text-align: right;">
|
<td style="text-align: right;">
|
||||||
<?php if ($editable): ?>
|
<?php if ($editable): ?>
|
||||||
<button type="submit" form="editMember_<?= $member->getId() ?>" name="submit_button" class="small marginRight" disabled>Save</button><!--
|
<button type="submit" form="editMember_<?= $member->getId() ?>" name="submit_button" class="small marginRight" disabled><i class="fa-regular fa-floppy-disk"></i></button><!--
|
||||||
--><button type="submit" form="deleteMember_<?= $member->getId() ?>" name="submit_button" data-confirmation="Are you sure you want to delete this member?" class="small red">Delete</button>
|
--><button type="submit" form="deleteMember_<?= $member->getId() ?>" name="submit_button" data-confirmation="Are you sure you want to delete this member?" data-confirmation-button='<i class="fa-regular fa-trash-can"></i> Delete' class="small red"><i class="fa-regular fa-trash-can"></i></button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<form id="newMember" action="<?= Container::$routeCollection->getRoute('community.members.new-action')->generateLink(['communityId' => $community->getId()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="user_id"></form>
|
<form id="newMember" action="<?= Container::$routeCollection->getRoute('community.members.new-action')->generateLink(['communitySlug' => $community->getSlug()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="user_id"></form>
|
||||||
<select type="text" form="newMember" name="user_id">
|
<select form="newMember" name="user_id" required></select>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: center;">
|
<td style="text-align: center;">
|
||||||
<input type="checkbox" form="newMember" name="owner" />
|
<input type="checkbox" form="newMember" name="owner" />
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: right;">
|
<td style="text-align: right;">
|
||||||
<button type="submit" form="newMember" name="submit_button" class="small" disabled>Add</button>
|
<button type="submit" form="newMember" name="submit_button" class="small" disabled><i class="fa-regular fa-plus"></i></button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
@section(main)
|
@section(main)
|
||||||
<h2>
|
<h2>
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()]) ?>"><?= $community->getName() ?></a> »
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
Settings
|
Settings
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<h3 class="marginBottom">
|
<h3 class="marginBottom">
|
||||||
Members
|
Members
|
||||||
<?php if ($editPermission): ?>
|
<?php if ($editPermission): ?>
|
||||||
<span class="small">[<a href="<?= Container::$routeCollection->getRoute('community.members')->generateLink(['communityId' => $community->getId()]) ?>">edit</a>]</span>
|
<span class="small">[<a href="<?= Container::$routeCollection->getRoute('community.members')->generateLink(['communitySlug' => $community->getSlug()]) ?>">edit</a>]</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</h3>
|
</h3>
|
||||||
<?php foreach ($members as $member): ?>
|
<?php foreach ($members as $member): ?>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<h3 class="marginBottom">
|
<h3 class="marginBottom">
|
||||||
Currencies
|
Currencies
|
||||||
<?php if ($editPermission): ?>
|
<?php if ($editPermission): ?>
|
||||||
<span class="small">[<a href="<?= Container::$routeCollection->getRoute('community.currencies')->generateLink(['communityId' => $community->getId()]) ?>">edit</a>]</span>
|
<span class="small">[<a href="<?= Container::$routeCollection->getRoute('community.currencies')->generateLink(['communitySlug' => $community->getSlug()]) ?>">edit</a>]</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</h3>
|
</h3>
|
||||||
<?php foreach ($currencies as $currency): ?>
|
<?php foreach ($currencies as $currency): ?>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<?php if ($currency->getId() === $community->getMainCurrencyId()): ?>
|
<?php if ($currency->getId() === $community->getMainCurrencyId()): ?>
|
||||||
<b><?= $currency->getCode() ?></b>
|
<b><?= $currency->getCode() ?></b>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.currencyExchangeRates')->generateLink(['communityId' => $community->getId(), 'code' => $currency->getCode()]) ?>"><?= $currency->getCode() ?></a>
|
<a href="<?= Container::$routeCollection->getRoute('community.currencyExchangeRates')->generateLink(['communitySlug' => $community->getSlug(), 'code' => $currency->getCode()]) ?>"><?= $currency->getCode() ?></a>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</p>
|
</p>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
@section(main)
|
@section(main)
|
||||||
<h2>
|
<h2>
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()]) ?>"><?= $community->getName() ?></a> »
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.settings')->generateLink(['communityId' => $community->getId()]) ?>">Settings</a> »
|
<a href="<?= Container::$routeCollection->getRoute('community.settings')->generateLink(['communitySlug' => $community->getSlug()]) ?>">Settings</a> »
|
||||||
Exchange rates for <?= $currency->getCode() ?>
|
Exchange rates for <?= $currency->getCode() ?>
|
||||||
</h2>
|
</h2>
|
||||||
<div class="box compactBox">
|
<div class="box compactBox">
|
||||||
@@ -24,16 +24,16 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<?php if ($editPermission): ?>
|
<?php if ($editPermission): ?>
|
||||||
<td>
|
<td>
|
||||||
<form id="editExchangeRate_<?= $currencyExchangeRate->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.currencyExchangeRates.edit-action')->generateLink(['communityId' => $community->getId(), 'code' => $currency->getCode(), 'currency_exchange_rate_id' => $currencyExchangeRate->getId()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="exchange_rate,valid_from"></form>
|
<form id="editExchangeRate_<?= $currencyExchangeRate->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.currencyExchangeRates.edit-action')->generateLink(['communitySlug' => $community->getSlug(), 'code' => $currency->getCode(), 'currency_exchange_rate_id' => $currencyExchangeRate->getId()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="exchange_rate,valid_from"></form>
|
||||||
<form id="deleteCurrency_<?= $currencyExchangeRate->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.currencyExchangeRates.delete-action')->generateLink(['communityId' => $community->getId(), 'code' => $currency->getCode(), 'currency_exchange_rate_id' => $currencyExchangeRate->getId()]) ?>" method="post" data-reload-on-success="true"></form>
|
<form id="deleteCurrency_<?= $currencyExchangeRate->getId() ?>" action="<?= Container::$routeCollection->getRoute('community.currencyExchangeRates.delete-action')->generateLink(['communitySlug' => $community->getSlug(), 'code' => $currency->getCode(), 'currency_exchange_rate_id' => $currencyExchangeRate->getId()]) ?>" method="post" data-reload-on-success="true"></form>
|
||||||
<input type="number" form="editExchangeRate_<?= $currencyExchangeRate->getId() ?>" class="text fullWidth" name="exchange_rate" value="<?= $currencyExchangeRate->getExchangeRate() ?>" min="0" step="0.000000001" required>
|
<input type="number" form="editExchangeRate_<?= $currencyExchangeRate->getId() ?>" class="text fullWidth" name="exchange_rate" value="<?= $currencyExchangeRate->getExchangeRate() ?>" min="0" step="0.000000001" required>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="datetime-local" form="editExchangeRate_<?= $currencyExchangeRate->getId() ?>" class="text fullWidth" name="valid_from" value="<?= $currencyExchangeRate->getValidFromDate()->format('Y-m-d\TH:i') ?>" required>
|
<input type="datetime-local" form="editExchangeRate_<?= $currencyExchangeRate->getId() ?>" class="text fullWidth" name="valid_from" value="<?= $currencyExchangeRate->getValidFromDate()->format('Y-m-d\TH:i') ?>" required>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: right;">
|
<td style="text-align: right;">
|
||||||
<button type="submit" form="editExchangeRate_<?= $currencyExchangeRate->getId() ?>" name="submit_button" class="small marginRight" disabled>Save</button><!--
|
<button type="submit" form="editExchangeRate_<?= $currencyExchangeRate->getId() ?>" name="submit_button" class="small marginRight" disabled><i class="fa-regular fa-floppy-disk"></i></button><!--
|
||||||
--><button type="submit" form="deleteCurrency_<?= $currencyExchangeRate->getId() ?>" name="submit_button" data-confirmation="Are you sure you want to delete this exchange rate?" class="small red">Delete</button>
|
--><button type="submit" form="deleteCurrency_<?= $currencyExchangeRate->getId() ?>" name="submit_button" data-confirmation="Are you sure you want to delete this exchange rate?" data-confirmation-button='<i class="fa-regular fa-trash-can"></i> Delete' class="small red"><i class="fa-regular fa-trash-can"></i></button>
|
||||||
</td>
|
</td>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<td><?= $currencyExchangeRate->getExchangeRate() ?></td>
|
<td><?= $currencyExchangeRate->getExchangeRate() ?></td>
|
||||||
@@ -44,14 +44,14 @@
|
|||||||
<?php if ($editPermission): ?>
|
<?php if ($editPermission): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<form id="newExchangeRate" action="<?= Container::$routeCollection->getRoute('community.currencyExchangeRates.new-action')->generateLink(['communityId' => $community->getId(), 'code' => $currency->getCode()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="exchange_rate,valid_from"></form>
|
<form id="newExchangeRate" action="<?= Container::$routeCollection->getRoute('community.currencyExchangeRates.new-action')->generateLink(['communitySlug' => $community->getSlug(), 'code' => $currency->getCode()]) ?>" method="post" data-reload-on-success="true" data-observe-inputs="exchange_rate,valid_from"></form>
|
||||||
<input type="number" form="newExchangeRate" class="text fullWidth" name="exchange_rate" placeholder="Exchange rate" min="0" step="0.000000001" required>
|
<input type="number" form="newExchangeRate" class="text fullWidth" name="exchange_rate" min="0" step="0.000000001" required>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input type="datetime-local" form="newExchangeRate" class="text fullWidth" name="valid_from" placeholder="Valid from" required>
|
<input type="datetime-local" form="newExchangeRate" class="text fullWidth" name="valid_from" required>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: right;">
|
<td style="text-align: right;">
|
||||||
<button type="submit" form="newExchangeRate" name="submit_button" class="small" disabled>Add</button>
|
<button type="submit" form="newExchangeRate" name="submit_button" class="small" disabled><i class="fa-regular fa-plus"></i></button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
|
@css(node_modules/tom-select/dist/css/tom-select.min.css)
|
||||||
|
@js(node_modules/tom-select/dist/js/tom-select.base.min.js)
|
||||||
|
@js(js/communities/transaction.js)
|
||||||
|
|
||||||
@extends(templates/layout_normal)
|
@extends(templates/layout_normal)
|
||||||
|
|
||||||
@section(main)
|
@section(main)
|
||||||
<h2>
|
<h2>
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()]) ?>"><?= $community->getName() ?></a> »
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId()]) ?>">Transactions</a> »
|
<?php if (isset($event)): ?>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.events')->generateLink(['communitySlug' => $community->getSlug()]) ?>">Events</a> »
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.event')->generateLink(['communitySlug' => $community->getSlug(), 'eventSlug' => $event->getSlug()]) ?>"><?= $event->getTitle() ?></a> »
|
||||||
|
<?php endif; ?>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communitySlug' => $community->getSlug(), 'event' => isset($event) ? $event->getSlug() : null]) ?>">Transactions</a> »
|
||||||
<?php if (isset($transaction)): ?>
|
<?php if (isset($transaction)): ?>
|
||||||
Edit transaction
|
Edit transaction
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
@@ -13,41 +21,62 @@
|
|||||||
<div class="box compactBox">
|
<div class="box compactBox">
|
||||||
<?php
|
<?php
|
||||||
$formAction = isset($transaction) ?
|
$formAction = isset($transaction) ?
|
||||||
Container::$routeCollection->getRoute('community.transactions.edit-action')->generateLink(['communityId' => $community->getId(), 'transactionId' => $transaction->getId()]) :
|
Container::$routeCollection->getRoute('community.transactions.edit-action')->generateLink(['communitySlug' => $community->getSlug(), 'transactionId' => $transaction->getId()]) :
|
||||||
Container::$routeCollection->getRoute('community.transactions.new-action')->generateLink(['communityId' => $community->getId()]);
|
Container::$routeCollection->getRoute('community.transactions.new-action')->generateLink(['communitySlug' => $community->getSlug()]);
|
||||||
?>
|
?>
|
||||||
<form id="transactionForm" action="<?= $formAction ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId()]) ?>">
|
<form id="transactionForm" action="<?= $formAction ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communitySlug' => $community->getSlug(), 'event' => isset($event) ? $event->getSlug() : null]) ?>">
|
||||||
|
<p class="formLabel">Event</p>
|
||||||
|
<select name="event_id">
|
||||||
|
<option value="">[none]</option>
|
||||||
|
<?php if (isset($event)): ?>
|
||||||
|
<option value="<?= $event->getId() ?>" selected><?= $event->getTitle() ?></option>
|
||||||
|
<?php endif; ?>
|
||||||
|
</select>
|
||||||
|
<p class="formLabel marginTop">Payer</p>
|
||||||
<select class="big fullWidth" name="payer_user_id" required>
|
<select class="big fullWidth" name="payer_user_id" required>
|
||||||
<option value="" hidden>[Payer]</option>
|
<option value="" hidden></option>
|
||||||
<?php foreach ($members as $member): ?>
|
<?php foreach ($members as $member): ?>
|
||||||
<option value="<?= $member->getUser()->getId() ?>" <?= isset($transaction) && $transaction->getPayerUserId() === $member->getUser()->getId() ? 'selected' : '' ?>><?= $member->getUser()->getDisplayName() ?></option>
|
<option value="<?= $member->getUser()->getId() ?>" <?= isset($transaction) && $transaction->getPayerUserId() === $member->getUser()->getId() ? 'selected' : '' ?>><?= $member->getUser()->getDisplayName() ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
<select class="big fullWidth marginTop" name="payee_user_id">
|
<p class="formLabel marginTop">Payee(s)</p>
|
||||||
<option value="">[Payee]</option>
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); grid-gap: 10px;">
|
||||||
<?php foreach ($members as $member): ?>
|
<?php foreach ($members as $member): ?>
|
||||||
<option value="<?= $member->getUser()->getId() ?>" <?= isset($transaction) && $transaction->getPayeeUserId() === $member->getUser()->getId() ? 'selected' : '' ?>><?= $member->getUser()->getDisplayName() ?></option>
|
<div style="text-align: center;">
|
||||||
|
<input id="payee_<?= $member->getUserId() ?>" type="checkbox" name="payee_user_ids[]" value="<?= $member->getUserId() ?>" <?= !isset($transaction) || count($payeeUserIds) === 0 || in_array($member->getUserId(), $payeeUserIds) ? 'checked' : '' ?>><!--
|
||||||
|
--><label for="payee_<?= $member->getUserId() ?>"><?= $member->getUser()->getDisplayName() ?></label>
|
||||||
|
</div>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</div>
|
||||||
<input type="text" class="text big fullWidth marginTop" name="description" placeholder="Description" value="<?= isset($transaction) ? $transaction->getDescription() : '' ?>" required>
|
<p class="formLabel marginTop">Description</p>
|
||||||
<input type="number" class="text big fullWidth marginTop" name="sum" placeholder="Sum" value="<?= isset($transaction) ? $transaction->getSum() : '' ?>" min="0" step="0.000000001" required>
|
<input type="text" class="text big fullWidth" name="description" value="<?= isset($transaction) ? $transaction->getDescription() : '' ?>" required>
|
||||||
<select class="big fullWidth marginTop" name="currency_id" required>
|
<p class="formLabel marginTop">Sum</p>
|
||||||
<option value="" hidden>[Currency]</option>
|
<input type="number" class="text big fullWidth" name="sum" value="<?= isset($transaction) ? $transaction->getSum() : '' ?>" min="0" step="0.000000001" required>
|
||||||
|
<p class="formLabel marginTop">Currency</p>
|
||||||
|
<select class="big fullWidth" name="currency_id" required>
|
||||||
|
<option value="" hidden></option>
|
||||||
<?php foreach ($currencies as $currency): ?>
|
<?php foreach ($currencies as $currency): ?>
|
||||||
<option value="<?= $currency->getId() ?>" <?= isset($transaction) && $transaction->getCurrencyId() === $currency->getId() ? 'selected' : '' ?>><?= $currency->getCode() ?></option>
|
<option value="<?= $currency->getId() ?>" <?= isset($transaction) && $transaction->getCurrencyId() === $currency->getId() ? 'selected' : '' ?>><?= $currency->getCode() ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</select>
|
</select>
|
||||||
<input type="datetime-local" class="text big fullWidth marginTop" name="time" placeholder="Time" value="<?= isset($transaction) ? $transaction->getTimeDate()->format('Y-m-d\TH:i') : (new DateTime())->format('Y-m-d\TH:i') ?>" required>
|
<p class="formLabel marginTop">Time</p>
|
||||||
|
<input type="datetime-local" class="text big fullWidth" name="time" value="<?= isset($transaction) ? $transaction->getTimeDate()->format('Y-m-d\TH:i') : (new DateTime())->format('Y-m-d\TH:i') ?>" required>
|
||||||
<p class="formError justify marginTop"></p>
|
<p class="formError justify marginTop"></p>
|
||||||
<div class="right marginTop" style="font-size: 0;">
|
<div class="right marginTop" style="font-size: 0;">
|
||||||
|
<button type="submit" name="submit_button"><?= isset($transaction) ? '<i class="fa-regular fa-floppy-disk"></i> Save' : '<i class="fa-regular fa-plus"></i> Create' ?></button>
|
||||||
<?php if (isset($transaction)): ?>
|
<?php if (isset($transaction)): ?>
|
||||||
<button type="submit" form="deleteTransaction" name="submit_button" data-confirmation="Are you sure you want to delete this transaction?" class="red marginRight">Delete</button>
|
<button type="submit" form="deleteTransaction" name="submit_button" data-confirmation="Are you sure you want to delete this transaction?" class="red marginLeft"><i class="fa-regular fa-trash-can"></i> Delete</button>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<button type="submit" name="submit_button"><?= isset($transaction) ? 'Save' : 'Create' ?></button>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<?php if (isset($transaction)): ?>
|
<?php if (isset($transaction)): ?>
|
||||||
<form id="deleteTransaction" action="<?= Container::$routeCollection->getRoute('community.transactions.delete-action')->generateLink(['communityId' => $community->getId(), 'transactionId' => $transaction->getId()]) ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId()]) ?>"></form>
|
<form id="deleteTransaction" action="<?= Container::$routeCollection->getRoute('community.transactions.delete-action')->generateLink(['communitySlug' => $community->getSlug(), 'transactionId' => $transaction->getId()]) ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communitySlug' => $community->getSlug()]) ?>"></form>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@section(pageScript)
|
||||||
|
<script>
|
||||||
|
var searchEventUrl = '<?= Container::$routeCollection->getRoute('community.events.search')->generateLink(['communitySlug' => $community->getSlug(), 'q' => 'QUERY']) ?>';
|
||||||
|
</script>
|
||||||
|
@endsection
|
||||||
@@ -2,35 +2,57 @@
|
|||||||
|
|
||||||
@section(main)
|
@section(main)
|
||||||
<h2>
|
<h2>
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()]) ?>"><?= $community->getName() ?></a> »
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
|
<?php if (isset($event)): ?>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.events')->generateLink(['communitySlug' => $community->getSlug()]) ?>">Events</a> »
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.event')->generateLink(['communitySlug' => $community->getSlug(), 'eventSlug' => $event->getSlug()]) ?>"><?= $event->getTitle() ?></a> »
|
||||||
|
<?php endif; ?>
|
||||||
Transactions
|
Transactions
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p class="marginTop"><a href="<?= Container::$routeCollection->getRoute('community.transactions.new')->generateLink(['communityId' => $community->getId()]) ?>">New transaction</a></p>
|
<p class="marginTop"><a href="<?= Container::$routeCollection->getRoute('community.transactions.new')->generateLink(['communitySlug' => $community->getSlug(), 'event' => isset($event) ? $event->getSlug() : null]) ?>">New transaction</a></p>
|
||||||
|
|
||||||
<?php if ($numberOfTransactions > 0): ?>
|
<?php if ($numberOfTransactions > 0): ?>
|
||||||
|
<?php
|
||||||
|
$paginationRouteId = 'community.transactions';
|
||||||
|
$paginationRouteParams = ['communitySlug' => $community->getSlug()];
|
||||||
|
?>
|
||||||
|
|
||||||
<?php if ($pages > 1): ?>
|
<?php if ($pages > 1): ?>
|
||||||
<p class="paginateContainer marginTop">
|
@include(templates/pagination)
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => 0]) ?>">«</a>
|
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => max(0, $currentPage - 1)]) ?>">‹</a>
|
|
||||||
<?php for ($i = 0; $i < $pages; $i++): ?>
|
|
||||||
<?php if ($currentPage == $i): ?>
|
|
||||||
<span class="selected"><?= $i + 1 ?></span>
|
|
||||||
<?php else: ?>
|
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => $i]) ?>"><?= $i + 1 ?></a>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endfor; ?>
|
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => min($pages - 1, $currentPage + 1)]) ?>">›</a>
|
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => $pages - 1]) ?>">»</a>
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php foreach ($transactions as $transaction): ?>
|
<?php foreach ($transactions as $transaction): ?>
|
||||||
<a class="block" href="<?= Container::$routeCollection->getRoute('community.transactions.edit')->generateLink(['communityId' => $community->getId(), 'transactionId' => $transaction->getId()]) ?>">
|
<a class="block" href="<?= Container::$routeCollection->getRoute('community.transactions.edit')->generateLink(['communitySlug' => $community->getSlug(), 'transactionId' => $transaction->getId()]) ?>">
|
||||||
<div class="box transaction">
|
<div class="box transaction">
|
||||||
<div>
|
<div>
|
||||||
|
<?php if ($transaction->getEvent()): ?>
|
||||||
|
<p><span class="label"><?= $transaction->getEvent()->getTitle() ?></span></p>
|
||||||
|
<?php endif; ?>
|
||||||
<p style="font-weight: bold;"><?= $transaction->getDescription() ?></p>
|
<p style="font-weight: bold;"><?= $transaction->getDescription() ?></p>
|
||||||
<p class="small"><?= $transaction->getPayerUser()->getDisplayName() ?> ► <?= $transaction->getPayeeUser() ? $transaction->getPayeeUser()->getDisplayName() : '[common]' ?></p>
|
<p class="small">
|
||||||
|
<?= $transaction->getPayerUser()->getDisplayName() ?>
|
||||||
|
<i class="fa-solid fa-caret-right"></i>
|
||||||
|
<?php foreach ($members as $member): ?>
|
||||||
|
<?php
|
||||||
|
if (count($transaction->getPayees()) > 0) {
|
||||||
|
$found = false;
|
||||||
|
foreach ($transaction->getPayees() as $payee) {
|
||||||
|
if ($member->getUserId() === $payee->getUserId()) {
|
||||||
|
$found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$found = true;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<?php if ($found): ?>
|
||||||
|
<?= $member->getUser()->getDisplayName() ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<span class="gray" style="text-decoration: line-through;"><?= $member->getUser()->getDisplayName() ?></span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</p>
|
||||||
<p class="small"><?= $transaction->getTimeDate()->format('Y-m-d H:i') ?></p>
|
<p class="small"><?= $transaction->getTimeDate()->format('Y-m-d H:i') ?></p>
|
||||||
</div>
|
</div>
|
||||||
<div style="text-align: right;">
|
<div style="text-align: right;">
|
||||||
@@ -44,22 +66,10 @@
|
|||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
<?php if ($pages > 1): ?>
|
<?php if ($pages > 1): ?>
|
||||||
<p class="paginateContainer marginTop">
|
@include(templates/pagination)
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => 0]) ?>">«</a>
|
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => max(0, $currentPage - 1)]) ?>">‹</a>
|
|
||||||
<?php for ($i = 0; $i < $pages; $i++): ?>
|
|
||||||
<?php if ($currentPage == $i): ?>
|
|
||||||
<span class="selected"><?= $i + 1 ?></span>
|
|
||||||
<?php else: ?>
|
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => $i]) ?>"><?= $i + 1 ?></a>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endfor; ?>
|
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => min($pages - 1, $currentPage + 1)]) ?>">›</a>
|
|
||||||
<a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communityId' => $community->getId(), 'page' => $pages - 1]) ?>">»</a>
|
|
||||||
</p>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<p class="marginTop"><a href="<?= Container::$routeCollection->getRoute('community.transactions.new')->generateLink(['communityId' => $community->getId()]) ?>">New transaction</a></p>
|
<p class="marginTop"><a href="<?= Container::$routeCollection->getRoute('community.transactions.new')->generateLink(['communitySlug' => $community->getSlug(), 'event' => isset($event) ? $event->getSlug() : null]) ?>">New transaction</a></p>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<p>There are no transactions yet.</p>
|
<p>There are no transactions yet.</p>
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
@extends(templates/layout_normal)
|
||||||
|
|
||||||
|
@section(main)
|
||||||
|
<h2>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.events')->generateLink(['communitySlug' => $community->getSlug()]) ?>">Events</a> »
|
||||||
|
<?= $event->getTitle() ?>
|
||||||
|
<span class="small">[<a href="<?= Container::$routeCollection->getRoute('community.event.edit')->generateLink(['communitySlug' => $community->getSlug(), 'eventSlug' => $event->getSlug()]) ?>">edit</a>]</span>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="gridContainer marginTop">
|
||||||
|
<div>
|
||||||
|
<?php
|
||||||
|
$mainCurrencyCode = $community->getMainCurrency()->getCode();
|
||||||
|
$mainCurrencyRoundDigits = $community->getMainCurrency()->getRoundDigits();
|
||||||
|
?>
|
||||||
|
<h3 class="marginBottom">Finances</h3>
|
||||||
|
<p><a href="<?= Container::$routeCollection->getRoute('community.transactions')->generateLink(['communitySlug' => $community->getSlug(), 'event' => $event->getSlug()]) ?>">Transactions</a> | <a href="<?= Container::$routeCollection->getRoute('community.transactions.new')->generateLink(['communitySlug' => $community->getSlug(), 'event' => $event->getSlug()]) ?>">New transaction</a></p>
|
||||||
|
<table class="fullWidth marginTop">
|
||||||
|
<tr>
|
||||||
|
<td class="bold">Total cost</td>
|
||||||
|
<td class="mono" style="text-align: right;"><?= number_format($totalCost, $mainCurrencyRoundDigits) ?> <?= $mainCurrencyCode ?></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<table class="fullWidth marginTop">
|
||||||
|
<tr>
|
||||||
|
<td class="bold">You owe*</td>
|
||||||
|
<td class="mono red" style="text-align: right;"><?= number_format($debtBalance, $mainCurrencyRoundDigits) ?> <?= $mainCurrencyCode ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php foreach ($debtItems as $item): ?>
|
||||||
|
<tr>
|
||||||
|
<td class="small"><?= $item['payee']->getUser()->getDisplayName() ?></td>
|
||||||
|
<td class="small mono red" style="text-align: right;"><?= number_format($item['amount'], $mainCurrencyRoundDigits) ?> <?= $mainCurrencyCode ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<tr>
|
||||||
|
<td class="bold">You're owed*</td>
|
||||||
|
<td class="mono green" style="text-align: right;"><?= number_format($outstandingBalance, $mainCurrencyRoundDigits) ?> <?= $mainCurrencyCode ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php foreach ($outstandingItems as $item): ?>
|
||||||
|
<tr>
|
||||||
|
<td class="small"><?= $item['payer']->getUser()->getDisplayName() ?></td>
|
||||||
|
<td class="small mono green" style="text-align: right;"><?= number_format($item['amount'], $mainCurrencyRoundDigits) ?> <?= $mainCurrencyCode ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<tr>
|
||||||
|
<td class="bold">Your balance*</td>
|
||||||
|
<td class="mono <?= $balance < 0 ? 'red' : ($balance > 0 ? 'green' : '') ?>" style="text-align: right;;"><?= number_format($balance, $mainCurrencyRoundDigits) ?> <?= $mainCurrencyCode ?></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<p class="small right">* Virtual balance only for this event. Check <a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>">community</a> finances for your real balance.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
@extends(templates/layout_normal)
|
||||||
|
|
||||||
|
@section(main)
|
||||||
|
<h2>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.events')->generateLink(['communitySlug' => $community->getSlug()]) ?>">Events</a> »
|
||||||
|
<?php if (isset($event)): ?>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.event')->generateLink(['communitySlug' => $community->getSlug(), 'eventSlug' => $event->getSlug()]) ?>"><?= $event->getTitle() ?></a> » Edit event
|
||||||
|
<?php else: ?>
|
||||||
|
New event
|
||||||
|
<?php endif; ?>
|
||||||
|
</h2>
|
||||||
|
<div class="box compactBox">
|
||||||
|
<?php
|
||||||
|
$formAction = isset($event) ?
|
||||||
|
Container::$routeCollection->getRoute('community.event.edit-action')->generateLink(['communitySlug' => $community->getSlug(), 'eventSlug' => $event->getSlug()]) :
|
||||||
|
Container::$routeCollection->getRoute('community.events.new-action')->generateLink(['communitySlug' => $community->getSlug()]);
|
||||||
|
?>
|
||||||
|
<form id="eventForm" action="<?= $formAction ?>" method="post" data-redirect-on-success="true">
|
||||||
|
<p class="formLabel">Title</p>
|
||||||
|
<input type="text" class="text big fullWidth" name="title" value="<?= isset($event) ? $event->getTitle() : '' ?>" required>
|
||||||
|
<p class="formLabel marginTop">Description</p>
|
||||||
|
<textarea class="text big fullWidth" name="description" rows="3"><?= isset($event) ? $event->getDescription() : '' ?></textarea>
|
||||||
|
<p class="formLabel marginTop">Start</p>
|
||||||
|
<input type="datetime-local" class="text big fullWidth" name="start" value="<?= isset($event) ? $event->getStartDate()->format('Y-m-d\TH:i') : '' ?>" required>
|
||||||
|
<p class="formLabel marginTop">End</p>
|
||||||
|
<input type="datetime-local" class="text big fullWidth" name="end" value="<?= isset($event) ? $event->getEndDate()->format('Y-m-d\TH:i') : '' ?>" required>
|
||||||
|
<p class="formError justify marginTop"></p>
|
||||||
|
<div class="right marginTop" style="font-size: 0;">
|
||||||
|
<button type="submit" name="submit_button"><?= isset($event) ? '<i class="fa-regular fa-floppy-disk"></i> Save' : '<i class="fa-regular fa-plus"></i> Create' ?></button>
|
||||||
|
<?php if (isset($event)): ?>
|
||||||
|
<button type="submit" form="deleteEvent" name="submit_button" data-confirmation="Are you sure you want to delete this event? All linked transactions will be unlinked!" class="red marginLeft"><i class="fa-regular fa-trash-can"></i> Delete</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<?php if (isset($event)): ?>
|
||||||
|
<form id="deleteEvent" action="<?= Container::$routeCollection->getRoute('community.event.delete-action')->generateLink(['communitySlug' => $community->getSlug(), 'eventSlug' => $event->getSlug()]) ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('community.events')->generateLink(['communitySlug' => $community->getSlug()]) ?>"></form>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
@extends(templates/layout_normal)
|
||||||
|
|
||||||
|
@section(main)
|
||||||
|
<h2>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a> »
|
||||||
|
Events
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p class="marginTop"><a href="<?= Container::$routeCollection->getRoute('community.events.new')->generateLink(['communitySlug' => $community->getSlug()]) ?>">New event</a></p>
|
||||||
|
|
||||||
|
<?php if ($numberOfEvents > 0): ?>
|
||||||
|
<?php
|
||||||
|
$paginationRouteId = 'community.events';
|
||||||
|
$paginationRouteParams = ['communitySlug' => $community->getSlug()];
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php if ($pages > 1): ?>
|
||||||
|
@include(templates/pagination)
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php foreach ($events as $event): ?>
|
||||||
|
<a class="block" href="<?= Container::$routeCollection->getRoute('community.event')->generateLink(['communitySlug' => $community->getSlug(), 'eventSlug' => $event->getSlug()]) ?>">
|
||||||
|
<div class="box">
|
||||||
|
<p style="font-weight: bold;"><?= $event->getTitle() ?></p>
|
||||||
|
<p class="small"><?= $event->getStartDate()->format('Y-m-d') ?> – <?= $event->getEndDate()->format('Y-m-d') ?></p>
|
||||||
|
<p class="small"><?= $event->getDescription() ?></p>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
<?php if ($pages > 1): ?>
|
||||||
|
@include(templates/pagination)
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<p class="marginTop"><a href="<?= Container::$routeCollection->getRoute('community.events.new')->generateLink(['communitySlug' => $community->getSlug()]) ?>">New event</a></p>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="box">
|
||||||
|
<p>There are no events yet.</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
@endsection
|
||||||
+12
-6
@@ -9,20 +9,26 @@
|
|||||||
</h3>
|
</h3>
|
||||||
<?php if (count($communities) > 0): ?>
|
<?php if (count($communities) > 0): ?>
|
||||||
<?php foreach ($communities as $community): ?>
|
<?php foreach ($communities as $community): ?>
|
||||||
<p><a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()]) ?>"><?= $community->getName() ?></a></p>
|
<p><a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $community->getSlug()]) ?>"><?= $community->getName() ?></a></p>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<p>You have no community.</p>
|
<p>You have no community.</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<h3 class="marginBottom">Upcoming events</h3>
|
<h3 class="marginBottom">Upcoming and recent events</h3>
|
||||||
<?php if (count($upcomingEvents) > 0): ?>
|
<?php if (count($upcomingAndRecentEvents) > 0): ?>
|
||||||
<?php foreach ($upcomingEvents as $event): ?>
|
<?php foreach ($upcomingAndRecentEvents as $event): ?>
|
||||||
<!-- todo -->
|
<p>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute('community.event')->generateLink(['communitySlug' => $event->getCommunity()->getSlug(), 'eventSlug' => $event->getSlug()]) ?>"><?= $event->getTitle() ?></a>
|
||||||
|
<span class="small">
|
||||||
|
(<a href="<?= Container::$routeCollection->getRoute('community')->generateLink(['communitySlug' => $event->getCommunity()->getSlug()]) ?>"><?= $event->getCommunity()->getName() ?></a>)
|
||||||
|
<?= $event->getStartDate()->format('Y-m-d') ?> – <?= $event->getEndDate()->format('Y-m-d') ?>
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
<p>There is no upcoming event.</p>
|
<p>There is no event to show.</p>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
@extends(templates/layout_normal)
|
@extends(templates/layout_normal)
|
||||||
|
|
||||||
@section(main)
|
@section(main)
|
||||||
<h2>Login up with Google</h2>
|
<h2>Login with Google</h2>
|
||||||
<div class="box compactBox">
|
<div class="box compactBox">
|
||||||
<p class="error justify"><?= $error ?></p>
|
<p class="error justify"><?= $error ?></p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,16 +4,18 @@
|
|||||||
<h2>Login</h2>
|
<h2>Login</h2>
|
||||||
<div class="box compactBox">
|
<div class="box compactBox">
|
||||||
<form id="loginForm" action="<?= Container::$routeCollection->getRoute('login-action')->generateLink() ?>" method="post" data-redirect-on-success="<?= $redirectUrl ?>">
|
<form id="loginForm" action="<?= Container::$routeCollection->getRoute('login-action')->generateLink() ?>" method="post" data-redirect-on-success="<?= $redirectUrl ?>">
|
||||||
<input type="text" class="text big fullWidth" name="email" placeholder="Email address / Username" required autofocus>
|
<p class="formLabel">Email address / Username</p>
|
||||||
<input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password" required minlength="6">
|
<input type="text" class="text big fullWidth" name="email" autocomplete="username" required autofocus>
|
||||||
|
<p class="formLabel marginTop">Password</p>
|
||||||
|
<input type="password" class="text big fullWidth" name="password" autocomplete="current-password" required minlength="6">
|
||||||
<p id="loginFormError" class="formError justify marginTop"></p>
|
<p id="loginFormError" class="formError justify marginTop"></p>
|
||||||
<div class="right marginTop">
|
<div class="right marginTop">
|
||||||
<button type="submit">Login</button>
|
<button type="submit"><i class="fa-solid fa-arrow-right-to-bracket"></i> Login</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="center marginTop"><a href="<?= Container::$routeCollection->getRoute('password.requestReset')->generateLink() ?>" title="Request password reset">Forgot your password?</a></p>
|
<p class="center marginTop"><a href="<?= Container::$routeCollection->getRoute('password.requestReset')->generateLink() ?>" title="Request password reset">Forgot your password?</a></p>
|
||||||
<hr>
|
<hr>
|
||||||
<div class="center">
|
<div class="center">
|
||||||
<a class="button yellow" href="<?= Container::$routeCollection->getRoute('login.google')->generateLink() ?>" title="Login with Google">Login with Google</a>
|
<a class="button yellow" href="<?= Container::$routeCollection->getRoute('login.google')->generateLink() ?>" title="Login with Google"><i class="fa-brands fa-google"></i> Login with Google</a>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
<h2>Request password reset</h2>
|
<h2>Request password reset</h2>
|
||||||
<div class="box compactBox">
|
<div class="box compactBox">
|
||||||
<form id="passwordResetForm" action="<?= Container::$routeCollection->getRoute('password.requestReset-action')->generateLink() ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('password.requestReset.success')->generateLink() ?>">
|
<form id="passwordResetForm" action="<?= Container::$routeCollection->getRoute('password.requestReset-action')->generateLink() ?>" method="post" data-redirect-on-success="<?= Container::$routeCollection->getRoute('password.requestReset.success')->generateLink() ?>">
|
||||||
<input type="email" class="text big fullWidth" name="email" placeholder="Email address" value="<?= isset($email) ? $email : '' ?>" required autofocus>
|
<p class="formLabel">Email address</p>
|
||||||
|
<input type="email" class="text big fullWidth" name="email" value="<?= isset($email) ? $email : '' ?>" required autofocus>
|
||||||
<?php if (!empty($_ENV['RECAPTCHA_SITEKEY'])): ?>
|
<?php if (!empty($_ENV['RECAPTCHA_SITEKEY'])): ?>
|
||||||
<div class="marginTop">
|
<div class="marginTop">
|
||||||
<div class="g-recaptcha" data-sitekey="<?= $_ENV['RECAPTCHA_SITEKEY'] ?>"></div>
|
<div class="g-recaptcha" data-sitekey="<?= $_ENV['RECAPTCHA_SITEKEY'] ?>"></div>
|
||||||
@@ -14,7 +15,7 @@
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<p id="passwordResetFormError" class="formError justify marginTop"></p>
|
<p id="passwordResetFormError" class="formError justify marginTop"></p>
|
||||||
<div class="right marginTop">
|
<div class="right marginTop">
|
||||||
<button type="submit">Continue</button>
|
<button type="submit"><i class="fa-solid fa-key"></i> Reset password</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,12 +5,15 @@
|
|||||||
<div class="box compactBox">
|
<div class="box compactBox">
|
||||||
<?php if ($success) : ?>
|
<?php if ($success) : ?>
|
||||||
<form id="resetPasswordForm" action="<?= Container::$routeCollection->getRoute('password.reset-action')->generateLink(['token' => $token]) ?>"" method="post" data-redirect-on-success="<?= $redirectUrl ?>">
|
<form id="resetPasswordForm" action="<?= Container::$routeCollection->getRoute('password.reset-action')->generateLink(['token' => $token]) ?>"" method="post" data-redirect-on-success="<?= $redirectUrl ?>">
|
||||||
<input type="email" class="text big fullWidth" name="email" placeholder="Email address" value="<?= $email ?>" disabled>
|
<p class="formLabel">Email address</p>
|
||||||
<input type="password" class="text big fullWidth marginTop" name="password" placeholder="Password" required minlength="6" autofocus>
|
<input type="text" class="text big fullWidth" name="email" autocomplete="username" value="<?= $email ?>" disabled>
|
||||||
<input type="password" class="text big fullWidth marginTop" name="password_confirm" placeholder="Password confirmation" required minlength="6">
|
<p class="formLabel marginTop">Password</p>
|
||||||
|
<input type="password" class="text big fullWidth" name="password" autocomplete="new-password" required minlength="6" autofocus>
|
||||||
|
<p class="formLabel marginTop">Password confirmation</p>
|
||||||
|
<input type="password" class="text big fullWidth" name="password_confirm" autocomplete="new-password" required minlength="6">
|
||||||
<p id="resetPasswordFormError" class="formError justify marginTop"></p>
|
<p id="resetPasswordFormError" class="formError justify marginTop"></p>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<button class="marginTop" type="submit">Reset password</button>
|
<button class="marginTop" type="submit"><i class="fa-solid fa-key"></i> Reset password</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
|
|||||||
@@ -10,14 +10,12 @@
|
|||||||
</h1>
|
</h1>
|
||||||
<p>
|
<p>
|
||||||
<?php if (Container::$request->user()) : ?>
|
<?php if (Container::$request->user()) : ?>
|
||||||
<span><a href="<?= Container::$routeCollection->getRoute('account')->generateLink() ?>" title="Account">
|
<span><a href="<?= Container::$routeCollection->getRoute('account')->generateLink() ?>" title="Account"><!--
|
||||||
<?php /* Copyright (c) 2019 The Bootstrap Authors. License can be found in 'USED_SOFTWARE' in section 'Bootstrap Icons'. */ ?>
|
--><i class="fa-regular fa-user"></i> <?= Container::$request->user()->getDisplayName() ?><!--
|
||||||
<svg class="inline" width="1em" height="1em" viewBox="0 0 16 16" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
--></a></span><!--
|
||||||
<path fill-rule="evenodd" d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
|
--><span><a href="<?= Container::$routeCollection->getRoute('logout')->generateLink() ?>" title="Logout"><!--
|
||||||
</svg><!--
|
--><i class="fa-solid fa-arrow-right-from-bracket"></i> Logout</a><!--
|
||||||
--><?= Container::$request->user()->getDisplayName() ?><!--
|
--></span>
|
||||||
--></a></span><!--
|
|
||||||
--><span><a href="<?= Container::$routeCollection->getRoute('logout')->generateLink() ?>" title="Logout">Logout</a></span>
|
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<p class="paginateContainer marginTop">
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute($paginationRouteId)->generateLink(array_merge($paginationRouteParams, ['page' => 1])) ?>">«</a>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute($paginationRouteId)->generateLink(array_merge($paginationRouteParams, ['page' => max(1, $currentPage - 1)])) ?>">‹</a>
|
||||||
|
<?php
|
||||||
|
$maxPages = 7;
|
||||||
|
if ($pages <= $maxPages) {
|
||||||
|
$start = 1;
|
||||||
|
$end = $pages;
|
||||||
|
} else {
|
||||||
|
$maxAdditionalPages = $maxPages - 1;
|
||||||
|
$maxAdditionalPagesHalf = ceil($maxAdditionalPages / 2);
|
||||||
|
$start = $currentPage - $maxAdditionalPagesHalf > 1 ?
|
||||||
|
($currentPage - $maxAdditionalPagesHalf < $pages - $maxAdditionalPages ?
|
||||||
|
$currentPage - $maxAdditionalPagesHalf :
|
||||||
|
$pages - $maxAdditionalPages) :
|
||||||
|
1;
|
||||||
|
$end = $start + $maxAdditionalPages < $pages ?
|
||||||
|
$start + $maxAdditionalPages :
|
||||||
|
$pages;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<?php for ($i = $start; $i <= $end; $i++): ?>
|
||||||
|
<?php if ($currentPage == $i): ?>
|
||||||
|
<span class="selected"><?= $i ?></span>
|
||||||
|
<?php else: ?>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute($paginationRouteId)->generateLink(array_merge($paginationRouteParams, ['page' => $i])) ?>"><?= $i ?></a>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endfor; ?>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute($paginationRouteId)->generateLink(array_merge($paginationRouteParams, ['page' => min($pages, $currentPage + 1)])) ?>">›</a>
|
||||||
|
<a href="<?= Container::$routeCollection->getRoute($paginationRouteId)->generateLink(array_merge($paginationRouteParams, ['page' => $pages])) ?>">»</a>
|
||||||
|
</p>
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<meta name="description" content="<?= $_ENV['APP_NAME'] ?>">
|
<meta name="description" content="<?= $_ENV['APP_NAME'] ?>">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="theme-color" content="#212f4d">
|
<meta name="theme-color" content="#212f4d">
|
||||||
<title><?= $_ENV['APP_NAME'] ?></title>
|
<title><?= isset($title) ? $title . ' – ' : '' ?><?= $_ENV['APP_NAME'] ?></title>
|
||||||
<?php if (preg_match('/^(http(s)?:)?\/\//', $_ENV['STATIC_ROOT']) === 1): ?>
|
<?php if (preg_match('/^(http(s)?:)?\/\//', $_ENV['STATIC_ROOT']) === 1): ?>
|
||||||
<link href="<?= $_ENV['STATIC_ROOT'] ?>" rel="preconnect">
|
<link href="<?= $_ENV['STATIC_ROOT'] ?>" rel="preconnect">
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
@@ -18,6 +18,10 @@
|
|||||||
<link href="https://fonts.googleapis.com/css2?family=Oxygen:wght@400;700&display=block" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Oxygen:wght@400;700&display=block" rel="stylesheet">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Oxygen+Mono:wght@400&display=block" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Oxygen+Mono:wght@400&display=block" rel="stylesheet">
|
||||||
<link href="<?= $_ENV['STATIC_ROOT'] ?>/css/rvr.css?rev=<?= REVISION ?>" rel="stylesheet">
|
<link href="<?= $_ENV['STATIC_ROOT'] ?>/css/rvr.css?rev=<?= REVISION ?>" rel="stylesheet">
|
||||||
|
<link href="<?= $_ENV['STATIC_ROOT'] ?>/node_modules/@fortawesome/fontawesome-free/css/fontawesome.min.css?rev=<?= REVISION ?>" rel="stylesheet">
|
||||||
|
<link href="<?= $_ENV['STATIC_ROOT'] ?>/node_modules/@fortawesome/fontawesome-free/css/solid.min.css?rev=<?= REVISION ?>" rel="stylesheet">
|
||||||
|
<link href="<?= $_ENV['STATIC_ROOT'] ?>/node_modules/@fortawesome/fontawesome-free/css/regular.min.css?rev=<?= REVISION ?>" rel="stylesheet">
|
||||||
|
<link href="<?= $_ENV['STATIC_ROOT'] ?>/node_modules/@fortawesome/fontawesome-free/css/brands.min.css?rev=<?= REVISION ?>" rel="stylesheet">
|
||||||
@yields('externalCss')
|
@yields('externalCss')
|
||||||
@yields('inlineCss')
|
@yields('inlineCss')
|
||||||
<link rel="icon" type="image/png" sizes="192x192" href="<?= $_ENV['STATIC_ROOT'] ?>/img/favicon/192x192.png?rev=<?= REVISION ?>">
|
<link rel="icon" type="image/png" sizes="192x192" href="<?= $_ENV['STATIC_ROOT'] ?>/img/favicon/192x192.png?rev=<?= REVISION ?>">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use SokoWeb\Response\HttpResponse;
|
|||||||
use SokoWeb\Routing\RouteCollection;
|
use SokoWeb\Routing\RouteCollection;
|
||||||
use SokoWeb\Session\DatabaseSessionHandler;
|
use SokoWeb\Session\DatabaseSessionHandler;
|
||||||
use SokoWeb\Request\Request;
|
use SokoWeb\Request\Request;
|
||||||
|
use SokoWeb\Request\Session;
|
||||||
use RVR\Controller\HomeController;
|
use RVR\Controller\HomeController;
|
||||||
use RVR\Controller\LoginController;
|
use RVR\Controller\LoginController;
|
||||||
use RVR\Controller\OAuthAuthController;
|
use RVR\Controller\OAuthAuthController;
|
||||||
@@ -12,6 +13,7 @@ use RVR\Controller\UserController;
|
|||||||
use RVR\Controller\UserSearchController;
|
use RVR\Controller\UserSearchController;
|
||||||
use RVR\Controller\CommunityController;
|
use RVR\Controller\CommunityController;
|
||||||
use RVR\Controller\TransactionController;
|
use RVR\Controller\TransactionController;
|
||||||
|
use RVR\Controller\EventController;
|
||||||
use RVR\Repository\UserRepository;
|
use RVR\Repository\UserRepository;
|
||||||
|
|
||||||
require 'app.php';
|
require 'app.php';
|
||||||
@@ -51,6 +53,11 @@ Container::$routeCollection->get('logout', 'logout', [LoginController::class, 'l
|
|||||||
Container::$routeCollection->group('account', function (RouteCollection $routeCollection) {
|
Container::$routeCollection->group('account', function (RouteCollection $routeCollection) {
|
||||||
$routeCollection->get('account', '', [UserController::class, 'getAccount']);
|
$routeCollection->get('account', '', [UserController::class, 'getAccount']);
|
||||||
$routeCollection->post('account-action', '', [UserController::class, 'saveAccount']);
|
$routeCollection->post('account-action', '', [UserController::class, 'saveAccount']);
|
||||||
|
$routeCollection->get('account.googleConnect', 'googleConnect', [UserController::class, 'getGoogleConnectRedirect']);
|
||||||
|
$routeCollection->get('account.googleConnect-confirm', 'googleConnect/code', [UserController::class, 'getGoogleConnectConfirm']);
|
||||||
|
$routeCollection->post('account.googleConnect-action', 'googleConnect', [UserController::class, 'connectGoogle']);
|
||||||
|
$routeCollection->get('account.googleDisconnect', 'googleDisconnect', [UserController::class, 'getGoogleDisconnectConfirm']);
|
||||||
|
$routeCollection->post('account.googleDisconnect-action', 'googleDisconnect', [UserController::class, 'disconnectGoogle']);
|
||||||
$routeCollection->get('account.googleAuthenticate', 'googleAuthenticate', [UserController::class, 'getGoogleAuthenticateRedirect']);
|
$routeCollection->get('account.googleAuthenticate', 'googleAuthenticate', [UserController::class, 'getGoogleAuthenticateRedirect']);
|
||||||
$routeCollection->get('account.googleAuthenticate-action', 'googleAuthenticate/code', [UserController::class, 'authenticateWithGoogle']);
|
$routeCollection->get('account.googleAuthenticate-action', 'googleAuthenticate/code', [UserController::class, 'authenticateWithGoogle']);
|
||||||
});
|
});
|
||||||
@@ -58,11 +65,12 @@ Container::$routeCollection->get('searchUser', 'searchUser', [UserSearchControll
|
|||||||
Container::$routeCollection->group('communities', function (RouteCollection $routeCollection) {
|
Container::$routeCollection->group('communities', function (RouteCollection $routeCollection) {
|
||||||
$routeCollection->get('community.new', 'new', [CommunityController::class, 'getCommunityNew']);
|
$routeCollection->get('community.new', 'new', [CommunityController::class, 'getCommunityNew']);
|
||||||
$routeCollection->post('community.new-action', 'new', [CommunityController::class, 'saveCommunity']);
|
$routeCollection->post('community.new-action', 'new', [CommunityController::class, 'saveCommunity']);
|
||||||
$routeCollection->group('{communityId}', function (RouteCollection $routeCollection) {
|
$routeCollection->group('{communitySlug}', function (RouteCollection $routeCollection) {
|
||||||
$routeCollection->get('community', '', [CommunityController::class, 'getCommunityHome']);
|
$routeCollection->get('community', '', [CommunityController::class, 'getCommunityHome']);
|
||||||
$routeCollection->get('community.settings', 'settings', [CommunityController::class, 'getCommunitySettings']);
|
$routeCollection->get('community.settings', 'settings', [CommunityController::class, 'getCommunitySettings']);
|
||||||
$routeCollection->get('community.edit', 'edit', [CommunityController::class, 'getCommunityEdit']);
|
$routeCollection->get('community.edit', 'edit', [CommunityController::class, 'getCommunityEdit']);
|
||||||
$routeCollection->post('community.edit-action', 'edit', [CommunityController::class, 'saveCommunity']);
|
$routeCollection->post('community.edit-action', 'edit', [CommunityController::class, 'saveCommunity']);
|
||||||
|
$routeCollection->post('community.delete-action', 'delete', [CommunityController::class, 'deleteCommunity']);
|
||||||
$routeCollection->get('community.members', 'members', [CommunityController::class, 'getMembersEdit']);
|
$routeCollection->get('community.members', 'members', [CommunityController::class, 'getMembersEdit']);
|
||||||
$routeCollection->post('community.members.new-action', 'members/new', [CommunityController::class, 'saveMember']);
|
$routeCollection->post('community.members.new-action', 'members/new', [CommunityController::class, 'saveMember']);
|
||||||
$routeCollection->post('community.members.edit-action', 'members/edit', [CommunityController::class, 'saveMember']);
|
$routeCollection->post('community.members.edit-action', 'members/edit', [CommunityController::class, 'saveMember']);
|
||||||
@@ -85,36 +93,42 @@ Container::$routeCollection->group('communities', function (RouteCollection $rou
|
|||||||
$routeCollection->post('community.transactions.edit-action', '{transactionId}', [TransactionController::class, 'saveTransaction']);
|
$routeCollection->post('community.transactions.edit-action', '{transactionId}', [TransactionController::class, 'saveTransaction']);
|
||||||
$routeCollection->post('community.transactions.delete-action', '{transactionId}/delete', [TransactionController::class, 'deleteTransaction']);
|
$routeCollection->post('community.transactions.delete-action', '{transactionId}/delete', [TransactionController::class, 'deleteTransaction']);
|
||||||
});
|
});
|
||||||
|
$routeCollection->group('events', function (RouteCollection $routeCollection) {
|
||||||
|
$routeCollection->get('community.events', '', [EventController::class, 'getEvents']);
|
||||||
|
$routeCollection->get('community.events.new', 'new', [EventController::class, 'getEventEdit']);
|
||||||
|
$routeCollection->post('community.events.new-action', 'new', [EventController::class, 'saveEvent']);
|
||||||
|
$routeCollection->get('community.events.search', 'search', [EventController::class, 'searchEvent']);
|
||||||
|
$routeCollection->group('{eventSlug}', function (RouteCollection $routeCollection) {
|
||||||
|
$routeCollection->get('community.event', '', [EventController::class, 'getEvent']);
|
||||||
|
$routeCollection->get('community.event.edit', 'edit', [EventController::class, 'getEventEdit']);
|
||||||
|
$routeCollection->post('community.event.edit-action', 'edit', [EventController::class, 'saveEvent']);
|
||||||
|
$routeCollection->post('community.event.delete-action', 'delete', [EventController::class, 'deleteEvent']);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Container::$sessionHandler = new DatabaseSessionHandler(Container::$dbConnection);
|
Container::$sessionHandler = new DatabaseSessionHandler(
|
||||||
|
Container::$dbConnection,
|
||||||
|
'sessions',
|
||||||
|
new DateTime('-7 days')
|
||||||
|
);
|
||||||
|
|
||||||
session_set_save_handler(Container::$sessionHandler, true);
|
session_set_save_handler(Container::$sessionHandler, true);
|
||||||
session_start([
|
session_start([
|
||||||
'gc_probability' => 0, // old sessions are deleted by MaintainDatabaseCommand
|
'gc_probability' => 0, // old sessions are deleted by MaintainDatabaseCommand
|
||||||
'cookie_lifetime' => 604800,
|
'cookie_lifetime' => 0,
|
||||||
'cookie_path' => '/',
|
'cookie_path' => '/',
|
||||||
'cookie_httponly' => true,
|
'cookie_httponly' => true,
|
||||||
'cookie_samesite' => 'Lax'
|
'cookie_samesite' => 'Lax'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if (isset($_COOKIE[session_name()])) {
|
|
||||||
// extend session cookie lifetime is cookie already exists
|
|
||||||
setcookie(session_name(), session_id(), [
|
|
||||||
'expires' => time() + 604800,
|
|
||||||
'path' => '/',
|
|
||||||
'httponly' => true,
|
|
||||||
'samesite' => 'Lax'
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Container::$request = new Request(
|
Container::$request = new Request(
|
||||||
$_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'],
|
$_SERVER['REQUEST_SCHEME'] . '://' . $_SERVER['HTTP_HOST'],
|
||||||
$_GET,
|
$_GET,
|
||||||
$_POST,
|
$_POST,
|
||||||
getallheaders(),
|
getallheaders(),
|
||||||
$_SESSION,
|
new Session($_SESSION),
|
||||||
new UserRepository()
|
new UserRepository()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user