mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat(ui): Add user requests page (#936)
* feat(ui): add user requests page * fix: return error if user attempts to fetch another user's requests without adequate perms * fix(ui): make user name on request page link back to user profile * feat(ui): link user request count to their filtered request list view * fix(frontend): only display user requests on profiles if current user has adequate perms * fix: use 'all' filter for user-filtered request list * fix(frontend): pass userId to router.push() * fix: do not pass userId in query for non-user-filtered requests page * fix(frontend): also allow REQUEST_VIEW perm through route guard * fix(frontend): only link request count to user request list if current user has required perms
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import Link from 'next/link';
|
||||
import { useRouter } from 'next/router';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
@@ -225,29 +226,51 @@ const UserProfile: React.FC = () => {
|
||||
</dl>
|
||||
</div>
|
||||
)}
|
||||
<div className="relative z-40 mt-6 mb-4 md:flex md:items-center md:justify-between">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="inline-flex items-center text-xl leading-7 text-gray-300 cursor-default sm:text-2xl sm:leading-9 sm:truncate">
|
||||
<span>{intl.formatMessage(messages.recentrequests)}</span>
|
||||
{(user.id === currentUser?.id ||
|
||||
currentHasPermission(
|
||||
[Permission.MANAGE_REQUESTS, Permission.REQUEST_VIEW],
|
||||
{ type: 'or' }
|
||||
)) && (
|
||||
<>
|
||||
<div className="slider-header">
|
||||
<Link href={`/users/${user?.id}/requests?filter=all`}>
|
||||
<a className="slider-title">
|
||||
<span>{intl.formatMessage(messages.recentrequests)}</span>
|
||||
<svg
|
||||
className="w-6 h-6 ml-2"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M13 9l3 3m0 0l-3 3m3-3H8m13 0a9 9 0 11-18 0 9 9 0 0118 0z"
|
||||
/>
|
||||
</svg>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative z-40">
|
||||
<Slider
|
||||
sliderKey="requests"
|
||||
isLoading={!requests && !requestError}
|
||||
isEmpty={!!requests && !requestError && requests.results.length === 0}
|
||||
items={(requests?.results ?? []).map((request) => (
|
||||
<RequestCard
|
||||
key={`request-slider-item-${request.id}`}
|
||||
request={request}
|
||||
onTitleData={updateAvailableTitles}
|
||||
/>
|
||||
))}
|
||||
placeholder={<RequestCard.Placeholder />}
|
||||
emptyMessage={intl.formatMessage(messages.norequests)}
|
||||
/>
|
||||
</div>
|
||||
<Slider
|
||||
sliderKey="requests"
|
||||
isLoading={!requests && !requestError}
|
||||
isEmpty={
|
||||
!!requests && !requestError && requests.results.length === 0
|
||||
}
|
||||
items={(requests?.results ?? []).map((request) => (
|
||||
<RequestCard
|
||||
key={`request-slider-item-${request.id}`}
|
||||
request={request}
|
||||
onTitleData={updateAvailableTitles}
|
||||
/>
|
||||
))}
|
||||
placeholder={<RequestCard.Placeholder />}
|
||||
emptyMessage={intl.formatMessage(messages.norequests)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
Reference in New Issue
Block a user