1841 lines
89 KiB
PHP
1841 lines
89 KiB
PHP
<?php
|
|
|
|
use humhub\modules\animal_management\models\Animal;
|
|
use humhub\modules\animal_management\helpers\DateDisplayHelper;
|
|
use humhub\modules\animal_management\models\AnimalGalleryItem;
|
|
use humhub\modules\animal_management\models\AnimalMedicalVisit;
|
|
use humhub\modules\animal_management\models\AnimalProgressUpdate;
|
|
use humhub\modules\animal_management\models\AnimalTransfer;
|
|
use humhub\modules\animal_management\models\AnimalTransferEvent;
|
|
use humhub\modules\animal_management\events\AnimalTileRenderEvent;
|
|
use humhub\modules\gallery\assets\Assets as GalleryAssets;
|
|
use humhub\modules\space\models\Space;
|
|
use yii\base\Event;
|
|
use yii\helpers\Html;
|
|
use yii\helpers\Json;
|
|
|
|
/* @var Space $space */
|
|
/* @var Animal $animal */
|
|
/* @var bool $canManage */
|
|
/* @var AnimalMedicalVisit[] $medicalVisits */
|
|
/* @var AnimalProgressUpdate[] $progressUpdates */
|
|
/* @var AnimalTransfer[] $transfers */
|
|
/* @var AnimalTransferEvent[] $transferEvents */
|
|
/* @var AnimalGalleryItem[] $galleryItems */
|
|
/* @var array $customFieldValues */
|
|
/* @var string $animalCoverImageUrl */
|
|
/* @var string $animalProfileImageUrl */
|
|
/* @var array $detailHeroFields */
|
|
/* @var string $layoutMode */
|
|
|
|
$openMedicalEditId = (int)Yii::$app->request->get('inlineMedicalEdit', 0);
|
|
$openProgressEditId = (int)Yii::$app->request->get('inlineProgressEdit', 0);
|
|
|
|
$layoutMode = isset($layoutMode) ? trim((string)$layoutMode) : 'default';
|
|
$isTabletLayout = $layoutMode === 'tablet';
|
|
|
|
$medicalVisitsUrl = $space->createUrl('/animal_management/animals/medical-visits', ['id' => (int)$animal->id]);
|
|
$progressUpdatesUrl = $space->createUrl('/animal_management/animals/progress-updates', ['id' => (int)$animal->id]);
|
|
$transferRequestUrl = $space->createUrl('/animal_management/animals/transfer', ['id' => (int)$animal->id]);
|
|
$tabletBackUrl = $space->createUrl('/animal_management/animals/index', ['view' => 'tablet']);
|
|
|
|
$transferById = [];
|
|
foreach ($transfers as $transfer) {
|
|
if ($transfer instanceof AnimalTransfer) {
|
|
$transferById[(int)$transfer->id] = $transfer;
|
|
}
|
|
}
|
|
|
|
$coverImageUrl = trim((string)$animalCoverImageUrl);
|
|
$profileImageUrl = trim((string)($animalProfileImageUrl ?? ''));
|
|
$hasCoverImage = $coverImageUrl !== '' && (preg_match('/^https?:\/\//i', $coverImageUrl) || substr($coverImageUrl, 0, 1) === '/');
|
|
$hasProfileImage = $profileImageUrl !== '' && (preg_match('/^https?:\/\//i', $profileImageUrl) || substr($profileImageUrl, 0, 1) === '/');
|
|
$statusLabel = Animal::statusOptions()[$animal->status] ?? (string)$animal->status;
|
|
|
|
$detailFieldMap = [
|
|
'name' => (string)$animal->getDisplayName(),
|
|
'species' => (string)$animal->species,
|
|
'breed' => (string)$animal->breed,
|
|
'sex' => (string)$animal->sex,
|
|
'status' => (string)$statusLabel,
|
|
'location_name' => (string)$animal->location_name,
|
|
'animal_uid' => (string)$animal->animal_uid,
|
|
'public_summary' => trim((string)$animal->public_summary),
|
|
'last_medical' => !empty($medicalVisits) ? DateDisplayHelper::format((string)$medicalVisits[0]->visit_at) : '',
|
|
];
|
|
|
|
$heroFieldValues = [];
|
|
foreach ($detailHeroFields as $fieldKey) {
|
|
$fieldKey = trim((string)$fieldKey);
|
|
if ($fieldKey === '' || $fieldKey === 'name' || !array_key_exists($fieldKey, $detailFieldMap)) {
|
|
continue;
|
|
}
|
|
|
|
$value = trim((string)$detailFieldMap[$fieldKey]);
|
|
if ($value === '') {
|
|
continue;
|
|
}
|
|
|
|
$heroFieldValues[] = $value;
|
|
}
|
|
|
|
$customHeroCount = 0;
|
|
foreach ($customFieldValues as $customField) {
|
|
if ($customHeroCount >= 3) {
|
|
break;
|
|
}
|
|
|
|
$label = trim((string)($customField['label'] ?? ''));
|
|
$value = trim((string)($customField['value'] ?? ''));
|
|
if ($label === '' || $value === '') {
|
|
continue;
|
|
}
|
|
|
|
$heroFieldValues[] = $label . ': ' . $value;
|
|
$customHeroCount++;
|
|
}
|
|
|
|
if (class_exists(GalleryAssets::class)) {
|
|
GalleryAssets::register($this);
|
|
}
|
|
|
|
$uiGalleryId = 'animal-gallery-' . (int)$animal->id;
|
|
|
|
$showDonationSettingsButton = $canManage && $space->moduleManager->isEnabled('donations');
|
|
$existingDonationGoal = null;
|
|
$profileTileOverlayAddonHtml = '';
|
|
|
|
if ($space->moduleManager->isEnabled('donations')) {
|
|
$donationGoalClass = 'humhub\\modules\\donations\\models\\DonationGoal';
|
|
if (class_exists($donationGoalClass)
|
|
&& Yii::$app->db->schema->getTableSchema($donationGoalClass::tableName(), true) !== null
|
|
) {
|
|
$existingDonationGoal = $donationGoalClass::find()
|
|
->where([
|
|
'contentcontainer_id' => (int)$space->contentcontainer_id,
|
|
'goal_type' => $donationGoalClass::TYPE_ANIMAL,
|
|
'target_animal_id' => (int)$animal->id,
|
|
])
|
|
->orderBy(['is_active' => SORT_DESC, 'id' => SORT_DESC])
|
|
->one();
|
|
}
|
|
}
|
|
|
|
$profileDonationToggleInputId = 'animal-profile-donation-toggle-' . (int)$animal->id;
|
|
$profileDonationInlineFormId = 'animal-profile-donation-inline-' . (int)$animal->id;
|
|
$profileDonationFileFieldId = 'animal-profile-donation-image-file-' . (int)$animal->id;
|
|
$profileDonationPreviewId = 'animal-profile-donation-image-preview-' . (int)$animal->id;
|
|
$profileCreateInlineGoalUrl = $space->createUrl('/donations/settings/create-animal-goal-inline', [
|
|
'animalId' => (int)$animal->id,
|
|
]);
|
|
|
|
$profileGalleryUrls = [];
|
|
foreach ($galleryItems as $galleryItem) {
|
|
if (!$galleryItem instanceof AnimalGalleryItem) {
|
|
continue;
|
|
}
|
|
|
|
$url = trim((string)$galleryItem->getImageUrl());
|
|
if ($url === '') {
|
|
continue;
|
|
}
|
|
|
|
$profileGalleryUrls[] = $url;
|
|
}
|
|
$profileGalleryUrls = array_slice($profileGalleryUrls, 0, 8);
|
|
|
|
$profileDefaultGoalTitle = Yii::t('DonationsModule.base', '{animalName} Care Fund', [
|
|
'animalName' => (string)$animal->getDisplayName(),
|
|
]);
|
|
|
|
$profileExistingGoalId = is_object($existingDonationGoal) ? (int)($existingDonationGoal->id ?? 0) : 0;
|
|
$profileExistingGoalTitle = trim((string)(is_object($existingDonationGoal) ? ($existingDonationGoal->title ?? '') : ''));
|
|
$profileExistingGoalTargetAmount = is_object($existingDonationGoal) ? (float)($existingDonationGoal->target_amount ?? 0) : 0.0;
|
|
$profileExistingGoalDescription = trim((string)(is_object($existingDonationGoal) ? ($existingDonationGoal->description ?? '') : ''));
|
|
$profileExistingGoalImage = trim((string)(is_object($existingDonationGoal) ? ($existingDonationGoal->image_path ?? '') : ''));
|
|
$profileExistingGoalActive = is_object($existingDonationGoal) ? (int)($existingDonationGoal->is_active ?? 1) : 1;
|
|
|
|
if ($profileExistingGoalTitle === '') {
|
|
$profileExistingGoalTitle = $profileDefaultGoalTitle;
|
|
}
|
|
|
|
if (class_exists(AnimalTileRenderEvent::class) && $space->moduleManager->isEnabled('donations')) {
|
|
$profileTileRenderEvent = new AnimalTileRenderEvent([
|
|
'animal' => $animal,
|
|
'contentContainer' => $space,
|
|
'existingDonationGoal' => $existingDonationGoal,
|
|
'showDonationSettingsButton' => $showDonationSettingsButton,
|
|
'donationToggleInputId' => $profileDonationToggleInputId,
|
|
'donationInlineFormId' => $profileDonationInlineFormId,
|
|
]);
|
|
|
|
Event::trigger(AnimalTileRenderEvent::class, AnimalTileRenderEvent::EVENT_RENDER_OVERLAY, $profileTileRenderEvent);
|
|
$profileTileOverlayAddonHtml = $profileTileRenderEvent->getHtml();
|
|
}
|
|
|
|
$profileInlineFormBackgroundStyle = 'padding:12px;border-top:1px solid #e6edf5;display:none;background:#fff;';
|
|
if ($profileExistingGoalImage !== '') {
|
|
$profileInlineFormBackgroundStyle = 'padding:12px;border-top:1px solid #e6edf5;display:none;'
|
|
. 'background-image:linear-gradient(rgba(255,255,255,0.35),rgba(255,255,255,0.45)),url(' . Html::encode($profileExistingGoalImage) . ');'
|
|
. 'background-size:cover;background-position:center;';
|
|
}
|
|
?>
|
|
|
|
<div class="panel panel-default<?= $isTabletLayout ? ' animal-tablet-layout' : '' ?>">
|
|
<?php if ($showDonationSettingsButton): ?>
|
|
<input
|
|
type="checkbox"
|
|
id="<?= Html::encode($profileDonationToggleInputId) ?>"
|
|
style="display:none;"
|
|
onchange="var f=document.getElementById('<?= Html::encode($profileDonationInlineFormId) ?>');if(f){f.style.display=this.checked?'block':'none';}"
|
|
>
|
|
<?php endif; ?>
|
|
|
|
<div id="animal-profile-hero-media" class="<?= ($hasCoverImage && $hasProfileImage) ? 'animal-hero-has-both-images' : '' ?>" style="position:relative;min-height:370px;overflow:hidden;border-radius:12px;background:#dbe3eb;">
|
|
<?php if ($isTabletLayout): ?>
|
|
<div style="position:absolute;top:12px;left:12px;z-index:3;">
|
|
<a href="<?= Html::encode($tabletBackUrl) ?>" class="btn btn-default btn-sm" style="border-radius:999px;background:rgba(255,255,255,0.92);border:0;">
|
|
<i class="fa fa-chevron-left"></i> <?= Yii::t('AnimalManagementModule.base', 'Animals') ?>
|
|
</a>
|
|
</div>
|
|
<?php endif; ?>
|
|
<?php if ($hasCoverImage || $hasProfileImage): ?>
|
|
<?php if ($hasCoverImage): ?>
|
|
<img class="animal-hero-image-cover" src="<?= Html::encode($coverImageUrl) ?>" alt="<?= Html::encode($animal->getDisplayName()) ?>" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;">
|
|
<?php endif; ?>
|
|
<?php if ($hasProfileImage): ?>
|
|
<img class="animal-hero-image-profile" src="<?= Html::encode($profileImageUrl) ?>" alt="<?= Html::encode($animal->getDisplayName()) ?>" style="position:absolute;inset:0;width:100%;height:100%;object-fit:cover;<?= $hasCoverImage ? 'display:none;' : '' ?>">
|
|
<?php endif; ?>
|
|
<?php else: ?>
|
|
<div style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#9aa5b1;">
|
|
<i class="fa fa-paw fa-4x"></i>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div style="position:absolute;inset:0;background:linear-gradient(180deg, rgba(7,10,16,0.08) 0%, rgba(7,10,16,0.6) 56%, rgba(7,10,16,0.84) 100%);"></div>
|
|
|
|
<?php if ($canManage): ?>
|
|
<div style="position:absolute;top:12px;right:12px;z-index:2;">
|
|
<a href="<?= Html::encode($space->createUrl('/animal_management/animals/edit', ['id' => $animal->id])) ?>" class="btn btn-default btn-sm animal-profile-action-icon-btn" title="<?= Yii::t('AnimalManagementModule.base', 'Edit Profile') ?>" aria-label="<?= Yii::t('AnimalManagementModule.base', 'Edit Profile') ?>">
|
|
<i class="fa fa-pencil"></i>
|
|
</a>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div data-animal-tile-overlay-stack="1" style="position:absolute;left:14px;right:14px;bottom:14px;color:#fff;z-index:1;transition:top 150ms ease,bottom 150ms ease;">
|
|
<div style="font-size:30px;line-height:1.1;font-weight:800;margin-bottom:8px;text-shadow:0 3px 10px rgba(0,0,0,0.45);">
|
|
<?= Html::encode($animal->getDisplayName()) ?>
|
|
</div>
|
|
<?php if (!empty($heroFieldValues)): ?>
|
|
<div style="display:flex;flex-wrap:wrap;gap:8px;margin-bottom:8px;">
|
|
<?php foreach ($heroFieldValues as $heroFieldValue): ?>
|
|
<span style="display:inline-block;background:rgba(15,23,42,0.58);border:1px solid rgba(255,255,255,0.28);padding:3px 10px;border-radius:999px;font-size:12px;">
|
|
<?= Html::encode($heroFieldValue) ?>
|
|
</span>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($animal->public_summary)): ?>
|
|
<div style="font-size:13px;line-height:1.35;text-shadow:0 2px 8px rgba(0,0,0,0.45);max-width:960px;">
|
|
<?= nl2br(Html::encode((string)$animal->public_summary)) ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($profileTileOverlayAddonHtml !== ''): ?>
|
|
<div style="margin-top:10px;max-width:100%;pointer-events:auto;">
|
|
<?= $profileTileOverlayAddonHtml ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($showDonationSettingsButton): ?>
|
|
<div id="<?= Html::encode($profileDonationInlineFormId) ?>" style="<?= $profileInlineFormBackgroundStyle ?>">
|
|
<div style="background:rgba(255,255,255,0.28);padding:10px;border-radius:8px;backdrop-filter:blur(1.8px);">
|
|
<div style="font-weight:700;margin-bottom:8px;color:#1f2937;">
|
|
<?= Yii::t('DonationsModule.base', 'Animal Donation Goal') ?>
|
|
</div>
|
|
|
|
<?= Html::beginForm($profileCreateInlineGoalUrl, 'post', [
|
|
'enctype' => 'multipart/form-data',
|
|
'style' => 'margin:0;',
|
|
]) ?>
|
|
<?= Html::hiddenInput(Yii::$app->request->csrfParam, Yii::$app->request->getCsrfToken()) ?>
|
|
<?= Html::hiddenInput('DonationGoalForm[id]', $profileExistingGoalId) ?>
|
|
<?= Html::hiddenInput('DonationGoalForm[goal_type]', 'animal') ?>
|
|
<?= Html::hiddenInput('DonationGoalForm[target_animal_id]', (int)$animal->id) ?>
|
|
<?= Html::hiddenInput('DonationGoalForm[is_active]', $profileExistingGoalActive) ?>
|
|
|
|
<div class="form-group" style="margin-bottom:8px;">
|
|
<label style="font-size:12px;font-weight:600;margin-bottom:4px;display:block;"><?= Yii::t('DonationsModule.base', 'Title') ?></label>
|
|
<?= Html::textInput('DonationGoalForm[title]', $profileExistingGoalTitle, [
|
|
'class' => 'form-control input-sm animal-profile-donation-inline-input',
|
|
'maxlength' => 190,
|
|
'required' => true,
|
|
]) ?>
|
|
</div>
|
|
|
|
<div class="form-group" style="margin-bottom:8px;">
|
|
<label style="font-size:12px;font-weight:600;margin-bottom:4px;display:block;"><?= Yii::t('DonationsModule.base', 'Target') ?></label>
|
|
<?= Html::input('number', 'DonationGoalForm[target_amount]', $profileExistingGoalTargetAmount > 0 ? (string)$profileExistingGoalTargetAmount : '', [
|
|
'class' => 'form-control input-sm animal-profile-donation-inline-input',
|
|
'step' => '0.01',
|
|
'min' => '0',
|
|
'required' => true,
|
|
]) ?>
|
|
</div>
|
|
|
|
<div class="form-group" style="margin-bottom:8px;">
|
|
<label style="font-size:12px;font-weight:600;margin-bottom:4px;display:block;"><?= Yii::t('DonationsModule.base', 'Description') ?></label>
|
|
<?= Html::textarea('DonationGoalForm[description]', $profileExistingGoalDescription, [
|
|
'class' => 'form-control input-sm animal-profile-donation-inline-input',
|
|
'rows' => 2,
|
|
]) ?>
|
|
</div>
|
|
|
|
<div class="form-group" style="margin-bottom:8px;">
|
|
<label style="font-size:12px;font-weight:600;margin-bottom:6px;display:block;"><?= Yii::t('DonationsModule.base', 'Image') ?></label>
|
|
<div id="<?= Html::encode($profileDonationPreviewId) ?>" class="text-muted" style="font-size:12px;margin-bottom:6px;">
|
|
<?php if ($profileExistingGoalImage !== ''): ?>
|
|
<img src="<?= Html::encode($profileExistingGoalImage) ?>" alt="" style="width:64px;height:64px;object-fit:cover;border-radius:3px;border:1px solid #d5deea;">
|
|
<?php else: ?>
|
|
<?= Yii::t('DonationsModule.base', 'No image selected.') ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if (!empty($profileGalleryUrls)): ?>
|
|
<div class="animal-profile-donation-inline-gallery" style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px;">
|
|
<?php foreach ($profileGalleryUrls as $galleryIndex => $galleryUrl): ?>
|
|
<?php $profileGalleryOptionId = 'animal-profile-donation-gallery-option-' . (int)$animal->id . '-' . (int)$galleryIndex; ?>
|
|
<div style="position:relative;">
|
|
<input
|
|
type="radio"
|
|
class="animal-profile-donation-gallery-radio"
|
|
id="<?= Html::encode($profileGalleryOptionId) ?>"
|
|
name="DonationGoalForm[imageGalleryPath]"
|
|
value="<?= Html::encode($galleryUrl) ?>"
|
|
data-preview="#<?= Html::encode($profileDonationPreviewId) ?>"
|
|
data-editor-bg="#<?= Html::encode($profileDonationInlineFormId) ?>"
|
|
<?= $profileExistingGoalImage === $galleryUrl ? 'checked' : '' ?>
|
|
>
|
|
<label for="<?= Html::encode($profileGalleryOptionId) ?>" style="display:block;border:1px solid #d5deea;background:rgba(255,255,255,0.34);padding:3px;border-radius:4px;line-height:0;pointer-events:auto;cursor:pointer;">
|
|
<img src="<?= Html::encode($galleryUrl) ?>" alt="" style="width:56px;height:56px;object-fit:cover;border-radius:2px;">
|
|
</label>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="text-muted" style="font-size:12px;margin-bottom:8px;">
|
|
<?= Yii::t('DonationsModule.base', 'No gallery images found for this animal.') ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?= Html::fileInput('DonationGoalForm[imageFile]', null, [
|
|
'id' => $profileDonationFileFieldId,
|
|
'class' => 'form-control input-sm js-animal-profile-donation-upload animal-profile-donation-inline-input',
|
|
'data-preview' => '#' . $profileDonationPreviewId,
|
|
'data-editor-bg' => '#' . $profileDonationInlineFormId,
|
|
'accept' => 'image/*',
|
|
]) ?>
|
|
</div>
|
|
|
|
<div style="display:flex;gap:8px;align-items:center;">
|
|
<?= Html::submitButton($profileExistingGoalId > 0 ? Yii::t('DonationsModule.base', 'Update Goal') : Yii::t('DonationsModule.base', 'Save Goal'), ['class' => 'btn btn-primary btn-sm']) ?>
|
|
<label for="<?= Html::encode($profileDonationToggleInputId) ?>" class="btn btn-default btn-sm" style="margin:0;">
|
|
<?= Yii::t('DonationsModule.base', 'Cancel') ?>
|
|
</label>
|
|
</div>
|
|
<?= Html::endForm() ?>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php
|
|
if ($showDonationSettingsButton) {
|
|
$this->registerCss("#{$profileDonationToggleInputId}:checked ~ #{$profileDonationInlineFormId}{display:block !important;}");
|
|
$this->registerCss("#{$profileDonationInlineFormId} .animal-profile-donation-inline-input{background:rgba(255,255,255,0.34);border-color:rgba(165,178,195,0.72);color:#16202a;}\n"
|
|
. "#{$profileDonationInlineFormId} .animal-profile-donation-inline-input::placeholder{color:rgba(31,41,55,0.72);}\n"
|
|
. "#{$profileDonationInlineFormId} .animal-profile-donation-inline-gallery{background:rgba(255,255,255,0.16);padding:6px;border-radius:6px;pointer-events:auto;}\n"
|
|
. "#{$profileDonationInlineFormId} .animal-profile-donation-gallery-radio{position:absolute;opacity:0;pointer-events:none;}\n"
|
|
. "#{$profileDonationInlineFormId} .animal-profile-donation-gallery-radio:checked + label{border-color:#1f78c1 !important;box-shadow:0 0 0 2px rgba(31,120,193,0.32) !important;}");
|
|
|
|
$profileUploadPendingText = Json::htmlEncode(Yii::t('DonationsModule.base', 'Image will be uploaded with this goal.'));
|
|
$profileNoImageText = Json::htmlEncode(Yii::t('DonationsModule.base', 'No image selected.'));
|
|
$profileInlineJsNamespace = 'animalProfileDonationInlineToggle' . (int)$animal->id;
|
|
|
|
$this->registerJs(<<<JS
|
|
(function() {
|
|
function syncProfileInlineEditor(toggleSelector, formSelector) {
|
|
var toggle = $(toggleSelector);
|
|
var form = $(formSelector);
|
|
if (!toggle.length || !form.length) {
|
|
return;
|
|
}
|
|
|
|
form.css('display', toggle.is(':checked') ? 'block' : 'none');
|
|
}
|
|
|
|
function setProfileEditorBackground(editorSelector, imageUrl) {
|
|
if (!editorSelector) {
|
|
return;
|
|
}
|
|
|
|
var editor = $(editorSelector);
|
|
if (!editor.length) {
|
|
return;
|
|
}
|
|
|
|
if (imageUrl) {
|
|
editor.css('background-image', 'linear-gradient(rgba(255,255,255,0.35),rgba(255,255,255,0.45)),url(' + imageUrl + ')');
|
|
editor.css('background-size', 'cover');
|
|
editor.css('background-position', 'center');
|
|
} else {
|
|
editor.css('background-image', 'none');
|
|
editor.css('background-color', '#fff');
|
|
}
|
|
}
|
|
|
|
function setProfilePreview(previewSelector, imageUrl) {
|
|
var preview = $(previewSelector);
|
|
if (!preview.length) {
|
|
return;
|
|
}
|
|
|
|
if (!imageUrl) {
|
|
preview.text($profileNoImageText);
|
|
return;
|
|
}
|
|
|
|
preview.html('<img src="' + $('<div/>').text(imageUrl).html() + '" alt="" style="width:64px;height:64px;object-fit:cover;border-radius:3px;border:1px solid #d5deea;">');
|
|
}
|
|
|
|
var profileInlineToggleSelector = '#$profileDonationToggleInputId';
|
|
var profileInlineFormSelector = '#$profileDonationInlineFormId';
|
|
|
|
syncProfileInlineEditor(profileInlineToggleSelector, profileInlineFormSelector);
|
|
|
|
$(document).off('change.$profileInlineJsNamespace').on('change.$profileInlineJsNamespace', profileInlineToggleSelector, function() {
|
|
syncProfileInlineEditor(profileInlineToggleSelector, profileInlineFormSelector);
|
|
});
|
|
|
|
$(document).off('change.animalProfileDonationGallery').on('change.animalProfileDonationGallery', '.animal-profile-donation-gallery-radio', function() {
|
|
var radio = $(this);
|
|
if (!radio.is(':checked')) {
|
|
return;
|
|
}
|
|
|
|
var previewSelector = radio.data('preview');
|
|
var editorSelector = radio.data('editor-bg');
|
|
var url = radio.val() || '';
|
|
|
|
setProfilePreview(previewSelector, url);
|
|
setProfileEditorBackground(editorSelector, url);
|
|
});
|
|
|
|
$(document).off('change.animalProfileDonationUpload').on('change.animalProfileDonationUpload', '.js-animal-profile-donation-upload', function() {
|
|
var previewSelector = $(this).data('preview');
|
|
var editorSelector = $(this).data('editor-bg');
|
|
if (!previewSelector) {
|
|
return;
|
|
}
|
|
|
|
var form = $(this).closest('form');
|
|
form.find('.animal-profile-donation-gallery-radio').prop('checked', false);
|
|
|
|
var previousObjectUrl = $(this).data('object-url') || '';
|
|
if (previousObjectUrl && window.URL && window.URL.revokeObjectURL) {
|
|
window.URL.revokeObjectURL(previousObjectUrl);
|
|
}
|
|
|
|
if (this.files && this.files.length > 0) {
|
|
var objectUrl = '';
|
|
if (window.URL && window.URL.createObjectURL) {
|
|
objectUrl = window.URL.createObjectURL(this.files[0]);
|
|
$(this).data('object-url', objectUrl);
|
|
}
|
|
|
|
if (objectUrl) {
|
|
setProfilePreview(previewSelector, objectUrl);
|
|
setProfileEditorBackground(editorSelector, objectUrl);
|
|
} else {
|
|
$(previewSelector).text($profileUploadPendingText);
|
|
}
|
|
} else {
|
|
$(this).data('object-url', '');
|
|
var selectedRadio = form.find('.animal-profile-donation-gallery-radio:checked').first();
|
|
var fallbackUrl = selectedRadio.length ? (selectedRadio.val() || '') : '';
|
|
setProfilePreview(previewSelector, fallbackUrl);
|
|
setProfileEditorBackground(editorSelector, fallbackUrl);
|
|
}
|
|
});
|
|
})();
|
|
JS, \yii\web\View::POS_READY, 'animal-profile-donation-inline-' . (int)$animal->id);
|
|
}
|
|
|
|
$this->registerJs(<<<'JS'
|
|
(function() {
|
|
function getCsrfPayload() {
|
|
var csrfParam = $('meta[name="csrf-param"]').attr('content') || '';
|
|
var csrfToken = $('meta[name="csrf-token"]').attr('content') || '';
|
|
var payload = {};
|
|
if (csrfParam && csrfToken) {
|
|
payload[csrfParam] = csrfToken;
|
|
}
|
|
return payload;
|
|
}
|
|
|
|
function scrollInlineEditorIntoView(editor) {
|
|
var $editor = $(editor);
|
|
if (!$editor.length) {
|
|
return;
|
|
}
|
|
|
|
var sideSpacing = parseFloat($editor.css('margin-left'));
|
|
if (!(sideSpacing > 0)) {
|
|
sideSpacing = parseFloat($editor.closest('.panel-body').css('padding-left'));
|
|
}
|
|
if (!(sideSpacing > 0)) {
|
|
sideSpacing = 14;
|
|
}
|
|
|
|
var fixedHeaderHeight = 0;
|
|
$('.navbar-fixed-top:visible, #topbar:visible, .topbar:visible, .layout-top-container:visible').each(function() {
|
|
var h = $(this).outerHeight() || 0;
|
|
if (h > fixedHeaderHeight) {
|
|
fixedHeaderHeight = h;
|
|
}
|
|
});
|
|
|
|
var topReserve = Math.max(sideSpacing, 14) + Math.max(fixedHeaderHeight, 64) + 28;
|
|
|
|
var top = Math.max(0, $editor.offset().top - topReserve);
|
|
$('html, body').stop(true).animate({scrollTop: top}, 220);
|
|
}
|
|
|
|
function refreshPanels(selectors) {
|
|
selectors = selectors || [];
|
|
if (!selectors.length) {
|
|
return $.Deferred().resolve().promise();
|
|
}
|
|
|
|
return $.get(window.location.href).done(function(html) {
|
|
var $doc = $('<div></div>').append($.parseHTML(html, document, true));
|
|
selectors.forEach(function(selector) {
|
|
var $next = $doc.find(selector).first();
|
|
if ($next.length) {
|
|
$(selector).replaceWith($next);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
window.addEventListener('message', function(event) {
|
|
var data = event.data || {};
|
|
if (!data || typeof data !== 'object' || data.source !== 'animal-inline-editor') {
|
|
return;
|
|
}
|
|
|
|
if (data.type === 'cancel') {
|
|
if (data.collapseId) {
|
|
$('#' + data.collapseId).collapse('hide');
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (data.type === 'saved') {
|
|
if (data.collapseId) {
|
|
$('#' + data.collapseId).collapse('hide');
|
|
}
|
|
|
|
var selectors = $.isArray(data.refreshSelectors) && data.refreshSelectors.length
|
|
? data.refreshSelectors
|
|
: ['#animal-medical-panel', '#animal-progress-panel', '#animal-gallery-panel'];
|
|
|
|
refreshPanels(selectors);
|
|
}
|
|
});
|
|
|
|
$(document)
|
|
.off('shown.bs.collapse.animalInlineScroll', '.animal-inline-editor')
|
|
.on('shown.bs.collapse.animalInlineScroll', '.animal-inline-editor', function() {
|
|
var $content = $(this).closest('.animal-feed-content');
|
|
if ($content.length) {
|
|
$content.addClass('animal-feed-editing');
|
|
}
|
|
scrollInlineEditorIntoView(this);
|
|
});
|
|
|
|
$(document)
|
|
.off('hidden.bs.collapse.animalInlineScroll', '.animal-inline-editor')
|
|
.on('hidden.bs.collapse.animalInlineScroll', '.animal-inline-editor', function() {
|
|
var $content = $(this).closest('.animal-feed-content');
|
|
if ($content.length) {
|
|
$content.removeClass('animal-feed-editing');
|
|
}
|
|
});
|
|
|
|
$('.animal-inline-editor.in').each(function() {
|
|
var $content = $(this).closest('.animal-feed-content');
|
|
if ($content.length) {
|
|
$content.addClass('animal-feed-editing');
|
|
}
|
|
});
|
|
|
|
$(document).on('submit', '#animal-gallery-upload', function(event) {
|
|
event.preventDefault();
|
|
var form = this;
|
|
var filesInput = form.querySelector('#galleryImages');
|
|
var selectedCount = filesInput && filesInput.files ? filesInput.files.length : 0;
|
|
if (selectedCount > 10) {
|
|
window.alert('You can upload up to 10 images at a time.');
|
|
return;
|
|
}
|
|
|
|
var formData = new FormData(form);
|
|
|
|
$.ajax({
|
|
url: form.action,
|
|
type: 'POST',
|
|
data: formData,
|
|
processData: false,
|
|
contentType: false
|
|
}).done(function() {
|
|
var shouldReopenModal = selectedCount > 0;
|
|
if (form && typeof form.reset === 'function') {
|
|
form.reset();
|
|
}
|
|
$('#animal-gallery-manage-modal').modal('hide');
|
|
refreshPanels(['#animal-gallery-panel']).done(function() {
|
|
if (shouldReopenModal) {
|
|
$('#animal-gallery-manage-modal').modal('show');
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
$(document).on('click', '.js-ajax-gallery-remove', function(event) {
|
|
event.preventDefault();
|
|
|
|
var $link = $(this);
|
|
var confirmText = $link.data('confirmMessage') || $link.data('confirm');
|
|
if (confirmText && !window.confirm(confirmText)) {
|
|
return;
|
|
}
|
|
|
|
$.post($link.attr('href'), getCsrfPayload()).done(function() {
|
|
refreshPanels(['#animal-gallery-panel']);
|
|
});
|
|
});
|
|
})();
|
|
JS
|
|
, \yii\web\View::POS_END);
|
|
|
|
?>
|
|
|
|
<div class="panel panel-default animal-inline-source-panel" id="animal-gallery-panel" data-inline-panel="gallery" data-inline-title="<?= Html::encode(Yii::t('AnimalManagementModule.base', 'Gallery')) ?>">
|
|
<div class="panel-heading" style="display:flex;justify-content:space-between;align-items:center;gap:8px;">
|
|
<span><?= Yii::t('AnimalManagementModule.base', '<strong>Gallery</strong>') ?></span>
|
|
<?php if ($canManage): ?>
|
|
<?= Html::a('<i class="fa fa-plus"></i> ' . Yii::t('AnimalManagementModule.base', 'Add'), '#animal-gallery-manage-modal', [
|
|
'class' => 'btn btn-xs animal-profile-action-pill',
|
|
'title' => Yii::t('AnimalManagementModule.base', 'Upload Gallery Images'),
|
|
'aria-label' => Yii::t('AnimalManagementModule.base', 'Upload Gallery Images'),
|
|
'data-toggle' => 'modal',
|
|
]) ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="panel-body">
|
|
<?php if (empty($galleryItems)): ?>
|
|
<div class="text-muted" style="margin-bottom:10px;">
|
|
<?= Yii::t('AnimalManagementModule.base', 'No gallery images yet.') ?>
|
|
</div>
|
|
<?php else: ?>
|
|
<div class="row" style="margin-bottom:8px;">
|
|
<?php foreach ($galleryItems as $galleryItem): ?>
|
|
<?php $galleryUrl = trim((string)$galleryItem->getImageUrl()); ?>
|
|
<?php if ($galleryUrl === '') { continue; } ?>
|
|
<div class="col-sm-4 col-md-3" style="margin-bottom:10px;">
|
|
<div style="position:relative;border-radius:8px;overflow:hidden;background:#f3f5f7;">
|
|
<a href="<?= Html::encode($galleryUrl) ?>#.jpeg"
|
|
data-type="image"
|
|
data-toggle="lightbox"
|
|
data-parent="#animal-gallery-panel"
|
|
data-ui-gallery="<?= Html::encode($uiGalleryId) ?>"
|
|
data-pjax="0"
|
|
data-pjax-prevent
|
|
aria-label="<?= Yii::t('AnimalManagementModule.base', 'Open image') ?>">
|
|
<img src="<?= Html::encode($galleryUrl) ?>" alt="<?= Yii::t('AnimalManagementModule.base', 'Gallery image') ?>" style="width:100%;height:170px;object-fit:cover;display:block;">
|
|
</a>
|
|
<?php if ($canManage): ?>
|
|
<div style="position:absolute;top:8px;right:8px;">
|
|
<?= Html::a('<i class="fa fa-times"></i>', $space->createUrl('/animal_management/animals/remove-gallery-image', ['id' => $animal->id, 'galleryId' => $galleryItem->id]), [
|
|
'class' => 'btn btn-xs btn-default js-ajax-gallery-remove animal-profile-action-icon-btn',
|
|
'title' => Yii::t('AnimalManagementModule.base', 'Remove Image'),
|
|
'aria-label' => Yii::t('AnimalManagementModule.base', 'Remove Image'),
|
|
'data-confirm-message' => Yii::t('AnimalManagementModule.base', 'Remove this image from the gallery?'),
|
|
]) ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<?php if ($canManage): ?>
|
|
<div class="modal fade" id="animal-gallery-manage-modal" tabindex="-1" role="dialog" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg" role="document">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<button type="button" class="close" data-dismiss="modal" aria-label="<?= Yii::t('AnimalManagementModule.base', 'Close') ?>"><span aria-hidden="true">×</span></button>
|
|
<h4 class="modal-title"><?= Yii::t('AnimalManagementModule.base', 'Add Images to Gallery') ?></h4>
|
|
</div>
|
|
<div class="modal-body">
|
|
<?php if (!empty($galleryItems)): ?>
|
|
<div class="row" style="margin-bottom:10px;max-height:260px;overflow:auto;">
|
|
<?php foreach ($galleryItems as $galleryItem): ?>
|
|
<?php $galleryUrl = trim((string)$galleryItem->getImageUrl()); ?>
|
|
<?php if ($galleryUrl === '') { continue; } ?>
|
|
<div class="col-xs-6 col-sm-3" style="margin-bottom:8px;">
|
|
<img src="<?= Html::encode($galleryUrl) ?>" alt="<?= Yii::t('AnimalManagementModule.base', 'Gallery image') ?>" style="width:100%;height:110px;object-fit:cover;border-radius:6px;">
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<hr style="margin-top:0;">
|
|
<?php endif; ?>
|
|
|
|
<form id="animal-gallery-upload" method="post" action="<?= Html::encode($space->createUrl('/animal_management/animals/add-gallery-images', ['id' => $animal->id])) ?>" enctype="multipart/form-data">
|
|
<?= Html::hiddenInput(Yii::$app->request->csrfParam, Yii::$app->request->getCsrfToken()) ?>
|
|
<div class="form-group" style="margin-bottom:8px;">
|
|
<label class="control-label" for="galleryImages"><?= Yii::t('AnimalManagementModule.base', 'Upload Images') ?></label>
|
|
<input type="file" class="form-control" id="galleryImages" name="galleryImages[]" accept="image/*" multiple>
|
|
<div class="help-block" style="margin-bottom:0;"><?= Yii::t('AnimalManagementModule.base', 'You can upload up to 10 images at a time.') ?></div>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary"><?= Yii::t('AnimalManagementModule.base', 'Upload to Gallery') ?></button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php
|
|
$profileDonationInlineFormIdJson = Json::htmlEncode((string)$profileDonationInlineFormId);
|
|
$this->registerJs(<<<JS
|
|
(function animalProfileHeroHeightFix() {
|
|
var inlineFormId = {$profileDonationInlineFormIdJson};
|
|
|
|
function syncAnimalProfileHeroHeight() {
|
|
var hero = document.getElementById('animal-profile-hero-media');
|
|
if (!hero) {
|
|
return;
|
|
}
|
|
|
|
var overlayStack = hero.querySelector('[data-animal-tile-overlay-stack="1"]');
|
|
if (!overlayStack) {
|
|
return;
|
|
}
|
|
|
|
var inlineForm = document.getElementById(inlineFormId);
|
|
var requiredHeight = Math.max(370, overlayStack.scrollHeight + 68);
|
|
if (inlineForm && inlineForm.offsetParent !== null) {
|
|
requiredHeight = Math.max(requiredHeight, 370 + inlineForm.scrollHeight + 24);
|
|
}
|
|
|
|
hero.style.minHeight = requiredHeight + 'px';
|
|
}
|
|
|
|
function applyFixes() {
|
|
syncAnimalProfileHeroHeight();
|
|
}
|
|
|
|
applyFixes();
|
|
window.setTimeout(syncAnimalProfileHeroHeight, 50);
|
|
window.setTimeout(syncAnimalProfileHeroHeight, 300);
|
|
window.setTimeout(syncAnimalProfileHeroHeight, 900);
|
|
|
|
var attempts = 0;
|
|
var retryTimer = window.setInterval(function () {
|
|
attempts += 1;
|
|
applyFixes();
|
|
if (attempts >= 20) {
|
|
window.clearInterval(retryTimer);
|
|
}
|
|
}, 250);
|
|
|
|
window.addEventListener('resize', syncAnimalProfileHeroHeight);
|
|
|
|
if (window.ResizeObserver) {
|
|
var hero = document.getElementById('animal-profile-hero-media');
|
|
var overlayStack = hero ? hero.querySelector('[data-animal-tile-overlay-stack="1"]') : null;
|
|
if (overlayStack) {
|
|
var observer = new ResizeObserver(syncAnimalProfileHeroHeight);
|
|
observer.observe(overlayStack);
|
|
}
|
|
}
|
|
|
|
var inlineForm = document.getElementById(inlineFormId);
|
|
if (inlineForm && window.MutationObserver) {
|
|
var mutationObserver = new MutationObserver(syncAnimalProfileHeroHeight);
|
|
mutationObserver.observe(inlineForm, { attributes: true, childList: true, subtree: true });
|
|
}
|
|
|
|
var iframes = document.querySelectorAll('iframe');
|
|
for (var i = 0; i < iframes.length; i++) {
|
|
iframes[i].addEventListener('load', syncAnimalProfileHeroHeight);
|
|
}
|
|
})();
|
|
JS
|
|
, \yii\web\View::POS_READY, 'animal-profile-hero-height-' . (int)$animal->id);
|
|
?>
|
|
|
|
<style>
|
|
<?php if ($showDonationSettingsButton): ?>
|
|
#animal-profile-hero-media {
|
|
min-height: 370px !important;
|
|
}
|
|
|
|
#<?= Html::encode($profileDonationToggleInputId) ?>:checked ~ #animal-profile-hero-media {
|
|
min-height: 370px !important;
|
|
}
|
|
<?php endif; ?>
|
|
|
|
.animal-feed-card {
|
|
position: relative;
|
|
overflow: hidden;
|
|
border: 1px solid #d5dfe8;
|
|
border-radius: 12px;
|
|
background: #223446;
|
|
min-height: 240px;
|
|
box-shadow: 0 8px 22px rgba(12, 24, 36, 0.16);
|
|
}
|
|
|
|
.animal-feed-cover {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
display: block;
|
|
}
|
|
|
|
.animal-feed-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(110deg, rgba(10, 18, 28, 0.28) 10%, rgba(10, 18, 28, 0.55) 52%, rgba(10, 18, 28, 0.75) 100%);
|
|
}
|
|
|
|
.animal-feed-content {
|
|
position: relative;
|
|
z-index: 1;
|
|
min-height: 240px;
|
|
padding: 14px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: flex-end;
|
|
gap: 10px;
|
|
}
|
|
|
|
.animal-feed-top-row {
|
|
width: 100%;
|
|
max-width: none;
|
|
margin-left: 0;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 8px;
|
|
}
|
|
|
|
.animal-feed-date {
|
|
font-size: 15px;
|
|
font-weight: 700;
|
|
color: #ffffff;
|
|
margin-right: auto;
|
|
}
|
|
|
|
.animal-feed-details {
|
|
width: 55%;
|
|
max-width: 55%;
|
|
min-width: 0;
|
|
margin-left: auto;
|
|
border-radius: 10px;
|
|
border: 1px solid rgba(255, 255, 255, 0.22);
|
|
background: rgba(10, 18, 28, 0.5);
|
|
backdrop-filter: blur(2px);
|
|
padding: 12px;
|
|
color: #ecf2f8;
|
|
}
|
|
|
|
.animal-feed-content.animal-feed-editing .animal-feed-details {
|
|
display: none;
|
|
}
|
|
|
|
.animal-feed-head {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
align-items: flex-start;
|
|
gap: 8px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.animal-feed-chips {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 6px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.animal-feed-chips--top {
|
|
margin-bottom: 0;
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.animal-feed-chip {
|
|
display: inline-block;
|
|
border-radius: 999px;
|
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
background: rgba(255, 255, 255, 0.16);
|
|
color: #ffffff;
|
|
font-size: 12px;
|
|
padding: 4px 10px;
|
|
}
|
|
|
|
.animal-feed-label {
|
|
font-size: 11px;
|
|
text-transform: uppercase;
|
|
letter-spacing: .04em;
|
|
color: rgba(231, 241, 249, 0.78);
|
|
margin-bottom: 4px;
|
|
}
|
|
|
|
.animal-feed-copy {
|
|
color: #eff5fb;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.animal-inline-editor {
|
|
position: relative;
|
|
z-index: 2;
|
|
width: auto;
|
|
max-width: none;
|
|
min-width: 0;
|
|
margin: 0 0 14px 0;
|
|
padding-top: 0;
|
|
align-self: stretch;
|
|
box-sizing: border-box;
|
|
border: 1px solid rgba(255, 255, 255, 0.22);
|
|
border-radius: 12px;
|
|
background: rgba(10, 18, 28, 0.2);
|
|
padding: 8px;
|
|
}
|
|
|
|
.animal-inline-editor iframe {
|
|
display: block;
|
|
width: 100%;
|
|
border: 0;
|
|
border-radius: 10px;
|
|
background: transparent;
|
|
}
|
|
|
|
.animal-profile-transfer-history-card {
|
|
position: relative;
|
|
overflow: hidden;
|
|
border: 1px solid rgba(255, 255, 255, 0.18);
|
|
border-radius: 12px;
|
|
min-height: 150px;
|
|
width: 100%;
|
|
max-width: 400px;
|
|
background: rgba(34, 52, 70, 0.34);
|
|
box-shadow: 0 8px 22px rgba(12, 24, 36, 0.16);
|
|
}
|
|
|
|
.animal-profile-transfer-history-cover {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
object-fit: cover;
|
|
display: block;
|
|
}
|
|
|
|
.animal-profile-transfer-history-overlay {
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(115deg, rgba(10, 18, 28, 0.2) 8%, rgba(10, 18, 28, 0.42) 54%, rgba(10, 18, 28, 0.62) 100%);
|
|
}
|
|
|
|
.animal-profile-transfer-history-body {
|
|
position: relative;
|
|
z-index: 1;
|
|
padding: 10px;
|
|
}
|
|
|
|
.animal-profile-transfer-event-head {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 8px;
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
.animal-profile-transfer-route-row {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
|
align-items: start;
|
|
gap: 12px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.animal-profile-transfer-rescue-col {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
text-align: center;
|
|
min-width: 0;
|
|
gap: 5px;
|
|
}
|
|
|
|
.animal-profile-transfer-rescue-avatar {
|
|
width: 54px;
|
|
height: 54px;
|
|
border-radius: 999px;
|
|
object-fit: cover;
|
|
border: 1px solid rgba(255, 255, 255, 0.38);
|
|
box-shadow: 0 3px 10px rgba(2, 8, 23, 0.28);
|
|
display: block;
|
|
background: rgba(255, 255, 255, 0.12);
|
|
}
|
|
|
|
.animal-profile-transfer-rescue-avatar-fallback {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #f8fafc;
|
|
font-size: 20px;
|
|
}
|
|
|
|
.animal-profile-transfer-rescue-name {
|
|
color: #f8fafc;
|
|
font-size: 14px;
|
|
font-weight: 700;
|
|
line-height: 1.2;
|
|
text-decoration: none;
|
|
max-width: 100%;
|
|
overflow-wrap: anywhere;
|
|
}
|
|
|
|
.animal-profile-transfer-rescue-name:hover {
|
|
text-decoration: underline;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.animal-profile-transfer-rescue-date {
|
|
color: rgba(226, 232, 240, 0.92);
|
|
font-size: 12px;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.animal-profile-transfer-route-arrow {
|
|
align-self: center;
|
|
justify-self: center;
|
|
font-size: 20px;
|
|
color: rgba(248, 250, 252, 0.9);
|
|
line-height: 1;
|
|
padding-top: 8px;
|
|
}
|
|
|
|
.animal-profile-transfer-event-lines {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 4px;
|
|
}
|
|
|
|
.animal-profile-transfer-event-line {
|
|
font-size: 14px;
|
|
line-height: 1.35;
|
|
color: #f8fafc;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 10px;
|
|
backdrop-filter: brightness(0.7);
|
|
padding: 8px 12px;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.animal-profile-transfer-event-actor {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
min-width: 0;
|
|
flex: 1 1 auto;
|
|
}
|
|
|
|
.animal-profile-transfer-event-avatar {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: 999px;
|
|
object-fit: cover;
|
|
border: 1px solid rgba(255, 255, 255, 0.36);
|
|
flex: 0 0 auto;
|
|
display: block;
|
|
background: rgba(255, 255, 255, 0.1);
|
|
}
|
|
|
|
.animal-profile-transfer-event-avatar-fallback {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #f8fafc;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.animal-profile-transfer-event-identity {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.animal-profile-transfer-event-actor-name {
|
|
color: #f8fafc;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
text-decoration: none;
|
|
line-height: 1.2;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.animal-profile-transfer-event-actor-name:hover {
|
|
text-decoration: underline;
|
|
color: #ffffff;
|
|
}
|
|
|
|
.animal-profile-transfer-event-line-time {
|
|
opacity: 0.9;
|
|
font-weight: 500;
|
|
font-size: 11px;
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.animal-profile-transfer-event-action {
|
|
margin-left: auto;
|
|
text-align: right;
|
|
font-size: 13px;
|
|
font-weight: 700;
|
|
color: #e2e8f0;
|
|
white-space: nowrap;
|
|
flex: 0 0 auto;
|
|
}
|
|
|
|
.animal-profile-transfer-time {
|
|
font-size: 16px;
|
|
font-weight: 700;
|
|
color: #f8fafc;
|
|
}
|
|
|
|
.animal-profile-transfer-badge {
|
|
display: inline-block;
|
|
padding: 3px 8px;
|
|
border-radius: 999px;
|
|
font-size: 11px;
|
|
font-weight: 800;
|
|
letter-spacing: .02em;
|
|
text-transform: uppercase;
|
|
}
|
|
|
|
.animal-profile-transfer-badge-requested {
|
|
background: #fef3c7;
|
|
color: #92400e;
|
|
}
|
|
|
|
.animal-profile-transfer-badge-accepted {
|
|
background: #dcfce7;
|
|
color: #166534;
|
|
}
|
|
|
|
.animal-profile-transfer-badge-declined {
|
|
background: #fee2e2;
|
|
color: #991b1b;
|
|
}
|
|
|
|
.animal-profile-transfer-badge-completed {
|
|
background: #dbeafe;
|
|
color: #1d4ed8;
|
|
}
|
|
|
|
.animal-profile-transfer-badge-cancelled {
|
|
background: #e5e7eb;
|
|
color: #374151;
|
|
}
|
|
|
|
.animal-profile-transfer-badge-default {
|
|
background: rgba(255, 255, 255, 0.2);
|
|
color: #f8fafc;
|
|
}
|
|
|
|
.animal-profile-action-icon-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 32px;
|
|
height: 32px;
|
|
padding: 0 !important;
|
|
line-height: 1 !important;
|
|
border-radius: 999px;
|
|
border: 1px solid rgba(15, 23, 42, 0.24);
|
|
background: rgba(255, 255, 255, 0.9);
|
|
color: #0f172a !important;
|
|
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.18);
|
|
}
|
|
|
|
.animal-profile-action-icon-btn i {
|
|
display: block;
|
|
margin: 0 !important;
|
|
line-height: 1 !important;
|
|
}
|
|
|
|
.animal-profile-action-pill {
|
|
border-radius: 999px;
|
|
border: 1px solid rgba(15, 23, 42, 0.18);
|
|
background: rgba(255, 255, 255, 0.92);
|
|
color: #0f172a !important;
|
|
font-weight: 700;
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
.animal-profile-action-icon-btn,
|
|
.animal-profile-action-pill {
|
|
border-color: rgba(226, 232, 240, 0.35);
|
|
background: rgba(15, 23, 42, 0.72);
|
|
color: #f8fafc !important;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 1200px) {
|
|
.animal-feed-details {
|
|
width: 55%;
|
|
max-width: 55%;
|
|
min-width: 0;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 991px) {
|
|
.animal-feed-details {
|
|
width: 55%;
|
|
max-width: 55%;
|
|
min-width: 0;
|
|
}
|
|
|
|
.animal-feed-chips--top {
|
|
justify-content: flex-start;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<div class="row animal-inline-source-panel" id="animal-medical-progress-panel" data-inline-panel="medical-progress" data-inline-title="<?= Html::encode(Yii::t('AnimalManagementModule.base', 'Medical & Progress')) ?>">
|
|
<div class="col-md-6">
|
|
<div class="panel panel-default" id="animal-medical-panel">
|
|
<div class="panel-heading" style="display:flex;justify-content:space-between;align-items:center;gap:8px;">
|
|
<a href="<?= Html::encode($space->createUrl('/animal_management/animals/medical-visits', ['id' => $animal->id])) ?>" style="font-weight:bold;">
|
|
<?= Yii::t('AnimalManagementModule.base', 'Medical Visits') ?>
|
|
</a>
|
|
<?php if ($canManage): ?>
|
|
<?= Html::a('<i class="fa fa-plus"></i> ' . Yii::t('AnimalManagementModule.base', 'Add'), $space->createUrl('/animal_management/animals/medical-visits', ['id' => $animal->id, 'inlineMedicalAdd' => 1]) . '#medical-add-inline', [
|
|
'class' => 'btn btn-xs animal-profile-action-pill',
|
|
'title' => Yii::t('AnimalManagementModule.base', 'Add Medical Visit'),
|
|
'aria-label' => Yii::t('AnimalManagementModule.base', 'Add Medical Visit'),
|
|
]) ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="panel-body">
|
|
<?php if (empty($medicalVisits)): ?>
|
|
<div class="text-muted" style="margin-bottom:10px;"><?= Yii::t('AnimalManagementModule.base', 'No medical visits recorded.') ?></div>
|
|
<?php else: ?>
|
|
<?php
|
|
$hiddenMedicalKeys = [
|
|
'second_physician_name',
|
|
'second_physician_business_name',
|
|
'second_physician_street_address',
|
|
'second_physician_city',
|
|
'second_physician_state',
|
|
'second_physician_zip',
|
|
'second_physician_cell_phone',
|
|
'second_physician_business_phone',
|
|
'second_physician_license_number',
|
|
'previous_physicians',
|
|
];
|
|
|
|
$knownMedicalKeys = [
|
|
'weight',
|
|
'pulse',
|
|
'blood_pressure',
|
|
'oxygen',
|
|
'chronic_conditions',
|
|
'acute_conditions',
|
|
'special_needs',
|
|
'date_of_most_recent_medical_visit',
|
|
'physician_name',
|
|
'physician_business_name',
|
|
'physician_street_address',
|
|
'physician_city',
|
|
'physician_state',
|
|
'physician_zip',
|
|
'physician_cell_phone',
|
|
'physician_business_phone',
|
|
'physician_license_number',
|
|
'medical_media_reference',
|
|
'media_reference',
|
|
];
|
|
$medicalVitalLabelOverrides = [
|
|
'blood_pressure' => 'BP',
|
|
'oxygen' => 'O₂',
|
|
];
|
|
?>
|
|
<?php foreach ($medicalVisits as $visit): ?>
|
|
<?php
|
|
$visitCustomValues = $visit->getCustomFieldDisplayValues($canManage);
|
|
$visitFieldsByKey = [];
|
|
$additionalVisitFields = [];
|
|
$medicalMedia = '';
|
|
foreach ($visitCustomValues as $customField) {
|
|
$fieldKey = (string)($customField['field_key'] ?? '');
|
|
if (in_array($fieldKey, $hiddenMedicalKeys, true)) {
|
|
continue;
|
|
}
|
|
|
|
$fieldValue = trim((string)($customField['value'] ?? ''));
|
|
if ($fieldValue === '') {
|
|
continue;
|
|
}
|
|
|
|
if ($fieldKey === 'medical_media_reference' || $fieldKey === 'media_reference') {
|
|
$medicalMedia = $fieldValue;
|
|
continue;
|
|
}
|
|
|
|
if (in_array($fieldKey, $knownMedicalKeys, true)) {
|
|
$visitFieldsByKey[$fieldKey] = [
|
|
'label' => (string)($medicalVitalLabelOverrides[$fieldKey] ?? ($customField['label'] ?? $fieldKey)),
|
|
'value' => $fieldValue,
|
|
];
|
|
continue;
|
|
}
|
|
|
|
$additionalVisitFields[] = [
|
|
'label' => (string)($customField['label'] ?? $fieldKey),
|
|
'value' => $fieldValue,
|
|
];
|
|
}
|
|
|
|
$hasMedicalMedia = $medicalMedia !== '' && (preg_match('/^https?:\/\//i', $medicalMedia) || substr($medicalMedia, 0, 1) === '/');
|
|
$visitDateDisplay = DateDisplayHelper::format((string)$visit->visit_at);
|
|
?>
|
|
<div class="panel panel-default animal-feed-card" style="margin-bottom:12px;">
|
|
<?php if ($hasMedicalMedia): ?>
|
|
<img class="animal-feed-cover" src="<?= Html::encode($medicalMedia) ?>" alt="<?= Yii::t('AnimalManagementModule.base', 'Medical media') ?>">
|
|
<?php endif; ?>
|
|
<div class="animal-feed-overlay"></div>
|
|
<div class="animal-feed-content">
|
|
<?php
|
|
$vitalKeys = ['weight', 'pulse', 'blood_pressure', 'oxygen'];
|
|
$hasVitals = false;
|
|
foreach ($vitalKeys as $vitalKey) {
|
|
if (!empty($visitFieldsByKey[$vitalKey]['value'])) {
|
|
$hasVitals = true;
|
|
break;
|
|
}
|
|
}
|
|
?>
|
|
<div class="animal-feed-top-row">
|
|
<span class="animal-feed-date"><?= Html::encode($visitDateDisplay !== '' ? $visitDateDisplay : (string)$visit->visit_at) ?></span>
|
|
<?php if ($hasVitals): ?>
|
|
<div class="animal-feed-chips animal-feed-chips--top">
|
|
<?php foreach ($vitalKeys as $vitalKey): ?>
|
|
<?php if (empty($visitFieldsByKey[$vitalKey]['value'])) { continue; } ?>
|
|
<span class="animal-feed-chip"><?= Html::encode($visitFieldsByKey[$vitalKey]['label']) ?>: <?= Html::encode($visitFieldsByKey[$vitalKey]['value']) ?></span>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="animal-feed-details">
|
|
<div class="animal-feed-head">
|
|
<?php if ($canManage): ?>
|
|
<?= Html::a(
|
|
'<i class="fa fa-pencil"></i>',
|
|
'#medical-edit-inline-' . (int)$visit->id,
|
|
[
|
|
'class' => 'btn btn-xs btn-default animal-profile-action-icon-btn',
|
|
'data-toggle' => 'collapse',
|
|
'title' => Yii::t('AnimalManagementModule.base', 'Edit'),
|
|
'aria-label' => Yii::t('AnimalManagementModule.base', 'Edit'),
|
|
]
|
|
) ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if (!empty($visit->provider_name)): ?>
|
|
<div class="animal-feed-copy" style="margin-bottom:8px;"><?= Yii::t('AnimalManagementModule.base', 'Provider') ?>: <?= Html::encode((string)$visit->provider_name) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($visit->notes)): ?>
|
|
<div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Clinical Notes') ?></div>
|
|
<div class="animal-feed-copy"><?= nl2br(Html::encode((string)$visit->notes)) ?></div>
|
|
<?php endif; ?>
|
|
<?php if (!empty($visit->recommendations)): ?>
|
|
<div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Recommendations') ?></div>
|
|
<div class="animal-feed-copy"><?= nl2br(Html::encode((string)$visit->recommendations)) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<?php
|
|
$conditionKeys = ['chronic_conditions', 'acute_conditions', 'special_needs'];
|
|
foreach ($conditionKeys as $conditionKey):
|
|
if (empty($visitFieldsByKey[$conditionKey]['value'])) {
|
|
continue;
|
|
}
|
|
?>
|
|
<div class="animal-feed-label"><?= Html::encode($visitFieldsByKey[$conditionKey]['label']) ?></div>
|
|
<div class="animal-feed-copy"><?= nl2br(Html::encode($visitFieldsByKey[$conditionKey]['value'])) ?></div>
|
|
<?php endforeach; ?>
|
|
|
|
<?php if (!empty($visitFieldsByKey['date_of_most_recent_medical_visit']['value'])): ?>
|
|
<div class="animal-feed-label"><?= Html::encode($visitFieldsByKey['date_of_most_recent_medical_visit']['label']) ?></div>
|
|
<div class="animal-feed-copy"><?= Html::encode(DateDisplayHelper::format((string)$visitFieldsByKey['date_of_most_recent_medical_visit']['value'])) ?></div>
|
|
<?php endif; ?>
|
|
|
|
<?php
|
|
$contactKeys = [
|
|
'physician_name',
|
|
'physician_business_name',
|
|
'physician_street_address',
|
|
'physician_city',
|
|
'physician_state',
|
|
'physician_zip',
|
|
'physician_cell_phone',
|
|
'physician_business_phone',
|
|
'physician_license_number',
|
|
];
|
|
$hasContact = false;
|
|
foreach ($contactKeys as $contactKey) {
|
|
if (!empty($visitFieldsByKey[$contactKey]['value'])) {
|
|
$hasContact = true;
|
|
break;
|
|
}
|
|
}
|
|
?>
|
|
|
|
<?php if ($hasContact): ?>
|
|
<?php
|
|
$contactLines = [];
|
|
if (!empty($visitFieldsByKey['physician_name']['value'])) {
|
|
$contactLines[] = (string)$visitFieldsByKey['physician_name']['value'];
|
|
}
|
|
if (!empty($visitFieldsByKey['physician_business_name']['value'])) {
|
|
$contactLines[] = (string)$visitFieldsByKey['physician_business_name']['value'];
|
|
}
|
|
if (!empty($visitFieldsByKey['physician_street_address']['value'])) {
|
|
$contactLines[] = (string)$visitFieldsByKey['physician_street_address']['value'];
|
|
}
|
|
|
|
$cityStateZip = trim(implode(', ', array_filter([
|
|
trim((string)($visitFieldsByKey['physician_city']['value'] ?? '')),
|
|
trim((string)($visitFieldsByKey['physician_state']['value'] ?? '')),
|
|
])));
|
|
$zipValue = trim((string)($visitFieldsByKey['physician_zip']['value'] ?? ''));
|
|
if ($zipValue !== '') {
|
|
$cityStateZip = trim($cityStateZip . ($cityStateZip !== '' ? ' ' : '') . $zipValue);
|
|
}
|
|
if ($cityStateZip !== '') {
|
|
$contactLines[] = $cityStateZip;
|
|
}
|
|
|
|
$phones = array_filter([
|
|
trim((string)($visitFieldsByKey['physician_cell_phone']['value'] ?? '')),
|
|
trim((string)($visitFieldsByKey['physician_business_phone']['value'] ?? '')),
|
|
]);
|
|
if (!empty($phones)) {
|
|
$contactLines[] = implode(' · ', $phones);
|
|
}
|
|
|
|
if (!empty($visitFieldsByKey['physician_license_number']['value'])) {
|
|
$contactLines[] = (string)$visitFieldsByKey['physician_license_number']['value'];
|
|
}
|
|
?>
|
|
<div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Care Contact') ?></div>
|
|
<div class="animal-feed-copy">
|
|
<?php foreach ($contactLines as $contactLine): ?>
|
|
<div><?= Html::encode($contactLine) ?></div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($additionalVisitFields)): ?>
|
|
<div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Additional Fields') ?></div>
|
|
<div class="animal-feed-copy">
|
|
<?php foreach ($additionalVisitFields as $additionalField): ?>
|
|
<div><strong><?= Html::encode((string)$additionalField['label']) ?>:</strong> <?= nl2br(Html::encode((string)$additionalField['value'])) ?></div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if ($canManage): ?>
|
|
<div id="medical-edit-inline-<?= (int)$visit->id ?>" class="collapse animal-inline-editor<?= $openMedicalEditId === (int)$visit->id ? ' in' : '' ?>">
|
|
<iframe
|
|
src="<?= Html::encode($space->createUrl('/animal_management/animals/edit-medical-visit', ['id' => $animal->id, 'visitId' => $visit->id, 'inline' => 1, 'showTopCancel' => 1, '_v' => time()])) ?>"
|
|
style="width:100%;min-height:640px;"
|
|
loading="lazy"
|
|
></iframe>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-md-6">
|
|
<div class="panel panel-default" id="animal-progress-panel">
|
|
<div class="panel-heading" style="display:flex;justify-content:space-between;align-items:center;gap:8px;">
|
|
<a href="<?= Html::encode($space->createUrl('/animal_management/animals/progress-updates', ['id' => $animal->id])) ?>" style="font-weight:bold;">
|
|
<?= Yii::t('AnimalManagementModule.base', 'Progress Feed') ?>
|
|
</a>
|
|
<?php if ($canManage): ?>
|
|
<?= Html::a('<i class="fa fa-plus"></i> ' . Yii::t('AnimalManagementModule.base', 'Add'), $space->createUrl('/animal_management/animals/progress-updates', ['id' => $animal->id, 'inlineProgressAdd' => 1]) . '#progress-add-inline', [
|
|
'class' => 'btn btn-xs animal-profile-action-pill',
|
|
'title' => Yii::t('AnimalManagementModule.base', 'Add Progress Update'),
|
|
'aria-label' => Yii::t('AnimalManagementModule.base', 'Add Progress Update'),
|
|
]) ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="panel-body">
|
|
<?php if (empty($progressUpdates)): ?>
|
|
<div class="text-muted" style="margin-bottom:10px;"><?= Yii::t('AnimalManagementModule.base', 'No progress updates recorded.') ?></div>
|
|
<?php else: ?>
|
|
<?php foreach ($progressUpdates as $update): ?>
|
|
<?php
|
|
$progressCustomValues = $update->getCustomFieldDisplayValues($canManage);
|
|
$mediaReference = '';
|
|
$progressCustomDisplayValues = [];
|
|
foreach ($progressCustomValues as $customField) {
|
|
if ((string)($customField['field_key'] ?? '') === 'media_reference') {
|
|
$mediaReference = trim((string)$customField['value']);
|
|
continue;
|
|
}
|
|
|
|
$progressCustomDisplayValues[] = $customField;
|
|
}
|
|
|
|
$hasMediaImage = $mediaReference !== '' && (preg_match('/^https?:\/\//i', $mediaReference) || substr($mediaReference, 0, 1) === '/');
|
|
?>
|
|
<div class="panel panel-default animal-feed-card" style="margin-bottom:12px;">
|
|
<?php if ($hasMediaImage): ?>
|
|
<img class="animal-feed-cover" src="<?= Html::encode($mediaReference) ?>" alt="<?= Yii::t('AnimalManagementModule.base', 'Progress media') ?>">
|
|
<?php endif; ?>
|
|
<div class="animal-feed-overlay"></div>
|
|
<div class="animal-feed-content">
|
|
<div class="animal-feed-top-row">
|
|
<span class="animal-feed-date"><?= Html::encode(DateDisplayHelper::format((string)$update->update_at)) ?></span>
|
|
<?php if (!empty($update->weight) || !empty($update->vitals)): ?>
|
|
<div class="animal-feed-chips animal-feed-chips--top">
|
|
<?php if (!empty($update->weight)): ?><span class="animal-feed-chip"><?= Yii::t('AnimalManagementModule.base', 'Weight') ?>: <?= Html::encode((string)$update->weight) ?></span><?php endif; ?>
|
|
<?php if (!empty($update->vitals)): ?><span class="animal-feed-chip"><?= Yii::t('AnimalManagementModule.base', 'Vitals') ?></span><?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="animal-feed-details">
|
|
<div class="animal-feed-head">
|
|
<?php if ($canManage): ?>
|
|
<?= Html::a(
|
|
'<i class="fa fa-pencil"></i>',
|
|
'#progress-edit-inline-' . (int)$update->id,
|
|
[
|
|
'class' => 'btn btn-xs btn-default animal-profile-action-icon-btn',
|
|
'data-toggle' => 'collapse',
|
|
'title' => Yii::t('AnimalManagementModule.base', 'Edit'),
|
|
'aria-label' => Yii::t('AnimalManagementModule.base', 'Edit'),
|
|
]
|
|
) ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if (!empty($update->vitals)): ?><div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Vitals') ?></div><div class="animal-feed-copy"><?= nl2br(Html::encode((string)$update->vitals)) ?></div><?php endif; ?>
|
|
<?php if (!empty($update->behavior_notes)): ?><div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Behavior') ?></div><div class="animal-feed-copy"><?= nl2br(Html::encode((string)$update->behavior_notes)) ?></div><?php endif; ?>
|
|
<?php if (!empty($update->meal_plan_changes)): ?><div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Meal Plan') ?></div><div class="animal-feed-copy"><?= nl2br(Html::encode((string)$update->meal_plan_changes)) ?></div><?php endif; ?>
|
|
<?php if (!empty($update->housing_changes)): ?><div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Housing') ?></div><div class="animal-feed-copy"><?= nl2br(Html::encode((string)$update->housing_changes)) ?></div><?php endif; ?>
|
|
<?php if (!empty($update->medical_concerns)): ?><div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Medical Concerns') ?></div><div class="animal-feed-copy"><?= nl2br(Html::encode((string)$update->medical_concerns)) ?></div><?php endif; ?>
|
|
|
|
<?php if (!empty($progressCustomDisplayValues)): ?>
|
|
<div class="animal-feed-label"><?= Yii::t('AnimalManagementModule.base', 'Additional Fields') ?></div>
|
|
<div class="animal-feed-copy">
|
|
<?php foreach ($progressCustomDisplayValues as $customField): ?>
|
|
<div><strong><?= Html::encode((string)$customField['label']) ?>:</strong> <?= nl2br(Html::encode((string)$customField['value'])) ?></div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if ($canManage): ?>
|
|
<div id="progress-edit-inline-<?= (int)$update->id ?>" class="collapse animal-inline-editor<?= $openProgressEditId === (int)$update->id ? ' in' : '' ?>">
|
|
<iframe
|
|
src="<?= Html::encode($space->createUrl('/animal_management/animals/edit-progress-update', ['id' => $animal->id, 'updateId' => $update->id, 'inline' => 1, 'showTopCancel' => 1, '_v' => time()])) ?>"
|
|
style="width:100%;min-height:760px;"
|
|
loading="lazy"
|
|
></iframe>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel panel-default animal-inline-source-panel" id="animal-transfer-panel" data-inline-panel="transfer" data-inline-title="<?= Html::encode(Yii::t('AnimalManagementModule.base', 'Transfer')) ?>">
|
|
<div class="panel-heading" style="display:flex;justify-content:space-between;align-items:center;gap:8px;">
|
|
<span><?= Yii::t('AnimalManagementModule.base', '<strong>Transfers</strong>') ?></span>
|
|
<?php if ($canManage): ?>
|
|
<?= Html::a('<i class="fa fa-plus"></i> ' . Yii::t('AnimalManagementModule.base', 'Request Transfer'), $transferRequestUrl, [
|
|
'class' => 'btn btn-xs animal-profile-action-pill',
|
|
'title' => Yii::t('AnimalManagementModule.base', 'Request Transfer'),
|
|
'aria-label' => Yii::t('AnimalManagementModule.base', 'Request Transfer'),
|
|
]) ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
<div class="panel-body" style="background:#f8fbfe;">
|
|
<?php if ($canManage): ?>
|
|
<div style="margin-bottom:10px;display:flex;flex-wrap:wrap;gap:8px;align-items:center;">
|
|
<?= Html::a('<i class="fa fa-exchange"></i> ' . Yii::t('AnimalManagementModule.base', 'Transfer Form'), $transferRequestUrl, ['class' => 'btn btn-default btn-sm']) ?>
|
|
<span style="display:inline-block;font-size:12px;padding:4px 8px;border-radius:999px;background:#e7eff8;color:#27435f;">
|
|
<?= Yii::t('AnimalManagementModule.base', 'Intelligent Rescue Matching (Coming Soon)') ?>
|
|
</span>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (empty($transferEvents)): ?>
|
|
<div class="text-muted" style="font-size:12px;"><?= Yii::t('AnimalManagementModule.base', 'No transfer events recorded yet.') ?></div>
|
|
<?php else: ?>
|
|
<?php
|
|
$eventsByTransfer = [];
|
|
foreach ($transferEvents as $transferEvent) {
|
|
if (!$transferEvent instanceof AnimalTransferEvent) {
|
|
continue;
|
|
}
|
|
|
|
$transferId = (int)$transferEvent->transfer_id;
|
|
if ($transferId <= 0) {
|
|
continue;
|
|
}
|
|
|
|
if (!isset($eventsByTransfer[$transferId])) {
|
|
$eventsByTransfer[$transferId] = [];
|
|
}
|
|
$eventsByTransfer[$transferId][] = $transferEvent;
|
|
}
|
|
|
|
foreach ($eventsByTransfer as &$transferEventsGroup) {
|
|
usort($transferEventsGroup, static function (AnimalTransferEvent $a, AnimalTransferEvent $b): int {
|
|
return strcmp((string)$b->created_at, (string)$a->created_at);
|
|
});
|
|
}
|
|
unset($transferEventsGroup);
|
|
|
|
$eventActionMap = [
|
|
AnimalTransferEvent::EVENT_REQUESTED => Yii::t('AnimalManagementModule.base', 'requested Transfer'),
|
|
AnimalTransferEvent::EVENT_ACCEPTED => Yii::t('AnimalManagementModule.base', 'accepted Transfer'),
|
|
AnimalTransferEvent::EVENT_DECLINED => Yii::t('AnimalManagementModule.base', 'declined Transfer'),
|
|
AnimalTransferEvent::EVENT_COMPLETED => Yii::t('AnimalManagementModule.base', 'completed Transfer'),
|
|
AnimalTransferEvent::EVENT_CANCELLED => Yii::t('AnimalManagementModule.base', 'cancelled Transfer'),
|
|
];
|
|
|
|
$eventBadgeMap = [
|
|
AnimalTransferEvent::EVENT_REQUESTED => ['label' => Yii::t('AnimalManagementModule.base', 'Requested'), 'class' => 'animal-profile-transfer-badge-requested'],
|
|
AnimalTransferEvent::EVENT_ACCEPTED => ['label' => Yii::t('AnimalManagementModule.base', 'Accepted'), 'class' => 'animal-profile-transfer-badge-accepted'],
|
|
AnimalTransferEvent::EVENT_DECLINED => ['label' => Yii::t('AnimalManagementModule.base', 'Declined'), 'class' => 'animal-profile-transfer-badge-declined'],
|
|
AnimalTransferEvent::EVENT_COMPLETED => ['label' => Yii::t('AnimalManagementModule.base', 'Completed'), 'class' => 'animal-profile-transfer-badge-completed'],
|
|
AnimalTransferEvent::EVENT_CANCELLED => ['label' => Yii::t('AnimalManagementModule.base', 'Cancelled'), 'class' => 'animal-profile-transfer-badge-cancelled'],
|
|
];
|
|
?>
|
|
|
|
<?php foreach ($eventsByTransfer as $transferId => $transferEventsGroup): ?>
|
|
<?php
|
|
$latestEvent = $transferEventsGroup[0] ?? null;
|
|
$latestType = $latestEvent ? (string)$latestEvent->event_type : '';
|
|
$eventBadge = $eventBadgeMap[$latestType] ?? ['label' => Yii::t('AnimalManagementModule.base', 'Updated'), 'class' => 'animal-profile-transfer-badge-default'];
|
|
$transferModel = $transferById[(int)$transferId] ?? null;
|
|
$fromName = Yii::t('AnimalManagementModule.base', 'Unknown Rescue');
|
|
$toName = Yii::t('AnimalManagementModule.base', 'Unknown Rescue');
|
|
$fromUrl = '';
|
|
$toUrl = '';
|
|
$fromAvatarUrl = '';
|
|
$toAvatarUrl = '';
|
|
$careWindowText = '';
|
|
$receivingStatusDateText = '';
|
|
|
|
if ($transferModel instanceof AnimalTransfer) {
|
|
$fromSpace = $transferModel->getFromSpace();
|
|
$toSpace = $transferModel->getToSpace();
|
|
if ($fromSpace !== null) {
|
|
$fromName = (string)$fromSpace->name;
|
|
$fromUrl = (string)$fromSpace->createUrl('/rescues');
|
|
if (method_exists($fromSpace, 'getProfileImage')) {
|
|
$fromProfileImage = $fromSpace->getProfileImage();
|
|
if ($fromProfileImage !== null && method_exists($fromProfileImage, 'getUrl')) {
|
|
$fromAvatarUrl = trim((string)$fromProfileImage->getUrl());
|
|
}
|
|
}
|
|
}
|
|
if ($toSpace !== null) {
|
|
$toName = (string)$toSpace->name;
|
|
$toUrl = (string)$toSpace->createUrl('/rescues');
|
|
if (method_exists($toSpace, 'getProfileImage')) {
|
|
$toProfileImage = $toSpace->getProfileImage();
|
|
if ($toProfileImage !== null && method_exists($toProfileImage, 'getUrl')) {
|
|
$toAvatarUrl = trim((string)$toProfileImage->getUrl());
|
|
}
|
|
}
|
|
}
|
|
|
|
$startTs = strtotime((string)$transferModel->created_at);
|
|
$endRaw = trim((string)($transferModel->completed_at ?? ''));
|
|
if ($endRaw === '') {
|
|
$endRaw = trim((string)$transferModel->updated_at);
|
|
}
|
|
$endTs = $endRaw !== '' ? strtotime($endRaw) : false;
|
|
|
|
if ($startTs !== false) {
|
|
$careWindowText = date('m/d/y', $startTs);
|
|
if ($endTs !== false) {
|
|
$careWindowText .= ' - ' . date('m/d/y', $endTs);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($latestType === AnimalTransferEvent::EVENT_COMPLETED) {
|
|
foreach ($transferEventsGroup as $candidateEvent) {
|
|
if ((string)$candidateEvent->event_type === AnimalTransferEvent::EVENT_COMPLETED) {
|
|
$completedTs = strtotime((string)$candidateEvent->created_at);
|
|
if ($completedTs !== false) {
|
|
$receivingStatusDateText = Yii::t('AnimalManagementModule.base', 'Completed {date}', [
|
|
'date' => date('m/d/y', $completedTs),
|
|
]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} elseif ($latestType === AnimalTransferEvent::EVENT_REQUESTED) {
|
|
foreach ($transferEventsGroup as $candidateEvent) {
|
|
if ((string)$candidateEvent->event_type === AnimalTransferEvent::EVENT_REQUESTED) {
|
|
$requestedTs = strtotime((string)$candidateEvent->created_at);
|
|
if ($requestedTs !== false) {
|
|
$receivingStatusDateText = Yii::t('AnimalManagementModule.base', 'Requested {date}', [
|
|
'date' => date('m/d/y', $requestedTs),
|
|
]);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
$fromNameHtml = $fromUrl !== ''
|
|
? Html::a(Html::encode($fromName), $fromUrl, ['class' => 'animal-profile-transfer-rescue-name'])
|
|
: '<span class="animal-profile-transfer-rescue-name">' . Html::encode($fromName) . '</span>';
|
|
$toNameHtml = $toUrl !== ''
|
|
? Html::a(Html::encode($toName), $toUrl, ['class' => 'animal-profile-transfer-rescue-name'])
|
|
: '<span class="animal-profile-transfer-rescue-name">' . Html::encode($toName) . '</span>';
|
|
|
|
$historyImageUrl = $hasCoverImage ? $coverImageUrl : ($hasProfileImage ? $profileImageUrl : '');
|
|
?>
|
|
<div class="animal-profile-transfer-history-card" style="margin-bottom:10px;">
|
|
<?php if ($historyImageUrl !== ''): ?>
|
|
<img class="animal-profile-transfer-history-cover" src="<?= Html::encode($historyImageUrl) ?>" alt="<?= Html::encode($animal->getDisplayName()) ?>">
|
|
<?php endif; ?>
|
|
<div class="animal-profile-transfer-history-overlay"></div>
|
|
<div class="animal-profile-transfer-history-body">
|
|
<div class="animal-profile-transfer-event-head">
|
|
<span class="animal-profile-transfer-badge <?= Html::encode($eventBadge['class']) ?>"><?= Html::encode($eventBadge['label']) ?></span>
|
|
</div>
|
|
<div class="animal-profile-transfer-route-row">
|
|
<div class="animal-profile-transfer-rescue-col">
|
|
<?php if ($fromAvatarUrl !== ''): ?>
|
|
<img class="animal-profile-transfer-rescue-avatar" src="<?= Html::encode($fromAvatarUrl) ?>" alt="<?= Html::encode($fromName) ?>">
|
|
<?php else: ?>
|
|
<span class="animal-profile-transfer-rescue-avatar animal-profile-transfer-rescue-avatar-fallback"><i class="fa fa-home"></i></span>
|
|
<?php endif; ?>
|
|
<?= $fromNameHtml ?>
|
|
<?php if ($careWindowText !== ''): ?>
|
|
<span class="animal-profile-transfer-rescue-date"><?= Html::encode($careWindowText) ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<div class="animal-profile-transfer-route-arrow" aria-hidden="true">→</div>
|
|
|
|
<div class="animal-profile-transfer-rescue-col">
|
|
<?php if ($toAvatarUrl !== ''): ?>
|
|
<img class="animal-profile-transfer-rescue-avatar" src="<?= Html::encode($toAvatarUrl) ?>" alt="<?= Html::encode($toName) ?>">
|
|
<?php else: ?>
|
|
<span class="animal-profile-transfer-rescue-avatar animal-profile-transfer-rescue-avatar-fallback"><i class="fa fa-home"></i></span>
|
|
<?php endif; ?>
|
|
<?= $toNameHtml ?>
|
|
<?php if ($receivingStatusDateText !== ''): ?>
|
|
<span class="animal-profile-transfer-rescue-date"><?= Html::encode($receivingStatusDateText) ?></span>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="animal-profile-transfer-event-lines">
|
|
<?php foreach ($transferEventsGroup as $transferEvent): ?>
|
|
<?php
|
|
$eventTimeText = date('m/d/y g:i A', strtotime((string)$transferEvent->created_at));
|
|
$eventActionText = $eventActionMap[(string)$transferEvent->event_type] ?? (string)$transferEvent->event_type;
|
|
$transferActor = $transferEvent->createdByUser;
|
|
$actorName = $transferActor ? (string)$transferActor->displayName : Yii::t('AnimalManagementModule.base', 'System');
|
|
$actorUrl = ($transferActor && method_exists($transferActor, 'getUrl')) ? (string)$transferActor->getUrl() : '';
|
|
$actorAvatarUrl = '';
|
|
if ($transferActor && method_exists($transferActor, 'getProfileImage')) {
|
|
$actorProfileImage = $transferActor->getProfileImage();
|
|
if ($actorProfileImage !== null && method_exists($actorProfileImage, 'getUrl')) {
|
|
$actorAvatarUrl = trim((string)$actorProfileImage->getUrl());
|
|
}
|
|
}
|
|
?>
|
|
<div class="animal-profile-transfer-event-line">
|
|
<div class="animal-profile-transfer-event-actor">
|
|
<?php if ($actorAvatarUrl !== ''): ?>
|
|
<img class="animal-profile-transfer-event-avatar" src="<?= Html::encode($actorAvatarUrl) ?>" alt="<?= Html::encode($actorName) ?>">
|
|
<?php else: ?>
|
|
<span class="animal-profile-transfer-event-avatar animal-profile-transfer-event-avatar-fallback"><i class="fa fa-user"></i></span>
|
|
<?php endif; ?>
|
|
<div class="animal-profile-transfer-event-identity">
|
|
<?php if ($actorUrl !== ''): ?>
|
|
<?= Html::a(Html::encode($actorName), $actorUrl, ['class' => 'animal-profile-transfer-event-actor-name']) ?>
|
|
<?php else: ?>
|
|
<span class="animal-profile-transfer-event-actor-name"><?= Html::encode($actorName) ?></span>
|
|
<?php endif; ?>
|
|
<span class="animal-profile-transfer-event-line-time"><?= Html::encode($eventTimeText) ?></span>
|
|
</div>
|
|
</div>
|
|
<span class="animal-profile-transfer-event-action"><?= Html::encode($eventActionText) ?></span>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<?php endforeach; ?>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|