I'm not sure if there is a plugin that allows you to block job execution while waiting for a webhook.

I think a more straight forward approach would be to split your pipeline in two:

QA + Merge Request

UAT + Prod

The second pipeline can be configured to be triggered using the GitLab plugin for Jenkins. As I understand it, you can follow the example in the README.md but your trigger should only fire when a push is made to the target branch e.g. if all of your merge-requests target master :

triggers { gitlab(triggerOnPush: true, triggerOnMergeRequest: false, branchFilterType: 'master') }

The benefit here is that you're not tying up a slave while waiting for the webhook (which could take a while depending on the size of the changes in the Merge Request and who is reviewing them).

The only issue this raises is if you have to maintain state across the two playbooks. I've written pipelines before that use a unique sha in the name for related resources. In your scenario you would lose access to that variable in the second pipeline.