Files
stroy-bot-monorepo/src/webparts/stroyBot/pages/resources/ResourcesPage.module.scss
T
Тимур Городецкий 55ce772eaa feat: port stroy-bot-project-assigner as resources page
Add the "resources" section (?page=resources&projectId=): professions and
companies assigned to a project, with the same lists, fields, texts and
optimistic add/remove with rollback as the legacy web part.

PnPjs is replaced by SharePoint REST through the app's IHttpClient so the
bundle needs no new dependency: the same $select/$expand/$filter, PnP paging
replaced by following odata.nextLink, adds as POST to items with the same
body, deletes as POST with X-HTTP-Method DELETE and IF-MATCH *. Known legacy
edge cases (temporary negative id) are kept and listed in the checklist.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-16 08:46:08 +05:00

177 lines
2.9 KiB
SCSS

@import '../../../../styles/design-tokens';
// Длинный справочник прокручивается внутри колонки — как в assigner.
$pool-max-height: 440px;
// Минимальная высота строки — чтобы строки с кнопкой и без неё были одной высоты.
$item-row-min-height: 40px;
// Вертикальный отступ строки списка — как в assigner (между $sp-2 и $sp-3).
$item-row-padding-y: 10px;
.page {
display: flex;
flex-direction: column;
gap: $sp-4;
width: 100%;
line-height: 1.55;
}
.projectHeader {
box-shadow: $sh-2;
@include page-header;
}
.projectTitle {
position: relative;
z-index: 1;
margin: 0;
font-family: $font-serif;
font-size: $fs-page-title;
font-weight: 600;
color: $white;
}
.dismissibleAlert {
display: flex;
align-items: flex-start;
gap: $sp-2;
}
.dismissibleAlertBody {
flex: 1;
min-width: 0;
}
.tabContent {
padding-top: $sp-1;
}
.splitColumns {
display: flex;
align-items: flex-start;
}
.splitLeft {
flex: 1;
min-width: 0;
padding-right: $sp-5;
border-right: 1px solid $gray-200;
}
.splitRight {
flex: 1;
min-width: 0;
padding-left: $sp-5;
}
.panelColumn {
min-width: 0;
}
.panelTitle {
position: relative;
margin: 0 0 $sp-3;
padding-bottom: $sp-2;
font-size: $fs-overline;
font-weight: 600;
letter-spacing: 1.6px;
text-transform: uppercase;
color: $gray-400;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
right: 0;
@include hairline;
}
}
.searchBox {
display: flex;
align-items: center;
gap: $sp-1;
margin-bottom: $sp-2;
}
.searchInput {
flex: 1;
min-width: 0;
}
.poolScrollArea {
max-height: $pool-max-height;
overflow-y: auto;
border: 1px solid $gray-200;
border-radius: $r-sm;
background: $white;
}
.itemRow {
display: flex;
align-items: center;
justify-content: space-between;
gap: $sp-2;
min-height: $item-row-min-height;
padding: $item-row-padding-y $sp-3;
border-bottom: 1px solid $gray-100;
transition: background 0.12s;
&:last-child {
border-bottom: none;
}
&:hover {
background: $gold-50;
}
}
.itemName,
.itemNameMuted {
flex: 1;
font-size: $fs-body;
word-break: break-word;
}
.itemName {
font-weight: 500;
color: $gray-700;
}
.itemNameMuted {
color: $gray-400;
}
.alreadyAddedTag {
margin-left: $sp-2;
vertical-align: middle;
}
.emptyMsg {
padding: $sp-4 $sp-3;
font-size: $fs-sm;
font-style: italic;
text-align: center;
color: $gray-400;
}
@include below($bp-md) {
.splitColumns {
flex-direction: column;
}
.splitLeft {
width: 100%;
padding-right: 0;
padding-bottom: $sp-4;
margin-bottom: $sp-4;
border-right: none;
border-bottom: 1px solid $gray-200;
}
.splitRight {
width: 100%;
padding-left: 0;
}
}