From 9d6c2f8bb81f907f4269ff471b9b679911e30f96 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Tue, 30 May 2023 23:44:05 +0000 Subject: [PATCH] Add API and UI to claim a member shelf --- apiserver/apiserver/api/views.py | 29 ++++++++++++ webclient/src/App.js | 6 ++- webclient/src/Home.js | 2 +- webclient/src/Storage.js | 79 ++++++++++++++++++++++++++++++++ 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/apiserver/apiserver/api/views.py b/apiserver/apiserver/api/views.py index 47280d7..227bbed 100644 --- a/apiserver/apiserver/api/views.py +++ b/apiserver/apiserver/api/views.py @@ -1790,6 +1790,35 @@ class StorageSpaceViewSet(Base, List, Retrieve, Update): queryset = models.StorageSpace.objects.all().order_by('id') serializer_class = serializers.StorageSpaceSerializer + @action(detail=False, methods=['post'], permission_classes=[AllowMetadata | IsAuthenticated]) + def claim(self, request): + user = self.request.user + + if user.storage.count(): + raise exceptions.ValidationError(dict(shelf_id='You already have a shelf.')) + + try: + shelf_id = str(request.data['shelf_id']).upper() + except KeyError: + raise exceptions.ValidationError(dict(shelf_id='This field is required.')) + + try: + storage = models.StorageSpace.objects.get(shelf_id=shelf_id) + except models.StorageSpace.DoesNotExist: + raise exceptions.ValidationError(dict(shelf_id='Shelf ID not found.')) + + if storage.location != 'member_shelves': + raise exceptions.ValidationError(dict(shelf_id='Not a member shelf. Please see a Director.')) + + if storage.user: + owner = storage.user.member.preferred_name + raise exceptions.ValidationError(dict(shelf_id='Shelf already belongs to {}.'.format(owner))) + + storage.user = user + storage.save() + + return Response(200) + class RegistrationView(RegisterView): serializer_class = serializers.MyRegisterSerializer diff --git a/webclient/src/App.js b/webclient/src/App.js index 5126301..ee75094 100644 --- a/webclient/src/App.js +++ b/webclient/src/App.js @@ -27,7 +27,7 @@ import { Subscribe } from './PayPal.js'; import { PasswordReset, ConfirmReset } from './PasswordReset.js'; import { NotFound, PleaseLogin } from './Misc.js'; import { Debug } from './Debug.js'; -import { StorageDetail } from './Storage.js'; +import { StorageDetail, ClaimShelf } from './Storage.js'; import { Garden } from './Garden.js'; import { Footer } from './Footer.js'; import { LCARS1Display, LCARS2Display } from './Display.js'; @@ -285,6 +285,10 @@ function App() { {user && user.member.set_details ? + + + + diff --git a/webclient/src/Home.js b/webclient/src/Home.js index f36afd0..14ad62d 100644 --- a/webclient/src/Home.js +++ b/webclient/src/Home.js @@ -77,7 +77,7 @@ function MemberInfo(props) { ) : - 'None' + <>None [claim] } diff --git a/webclient/src/Storage.js b/webclient/src/Storage.js index d451cb5..54e1b9f 100644 --- a/webclient/src/Storage.js +++ b/webclient/src/Storage.js @@ -241,3 +241,82 @@ export function StorageList(props) { ); }; + +export function ClaimShelfForm(props) { + const { token, user, refreshUser } = props; + const member = user.member; + const [input, setInput] = useState({}); + const [error, setError] = useState({}); + const [loading, setLoading] = useState(false); + const history = useHistory(); + + const handleValues = (e, v) => setInput({ ...input, [v.name]: v.value }); + const handleChange = (e) => handleValues(e, e.currentTarget); + + const handleSubmit = (e) => { + if (loading) return; + setLoading(true); + requester('/storage/claim/', 'POST', token, input) + .then(res => { + setError({}); + refreshUser(); + history.push('/'); + }) + .catch(err => { + setLoading(false); + console.log(err); + setError(err.data); + }); + }; + + const makeProps = (name) => ({ + name: name, + onChange: handleChange, + value: input[name] || '', + error: error[name], + }); + + return ( +
+
+ +

{user.username}

+
+ + + + + Submit + + + ); +}; + +export function ClaimShelf(props) { + const { token, user } = props; + const [error, setError] = useState(false); + + return ( + + + +
Claim Member Shelf
+ +

Use this form to claim a member shelf.

+ +

Please make sure your name and contact info are visible on the shelf.

+ +

Use the Shelf ID visible on the corner label (A1A, A2B, etc.)

+ + +
+
+
+ ); +};