Yes, I left such a position to go and get a doctorate, because I was fed up with the dumbing-down of the codebase, the way that my colleagues wrote absolute undocumented spaghetti cruft, I had to keep fixing their bugs, and management were making some very dumb decisions about key features. As far as I know they are still going fine, which is surprising given I was the only one who could understand how whole subsystems worked, mainly because I knew how to write safe threaded code.
But, enough on that. A few years before then, I felt like you did, but I wasn't actually in that situation. There is a very real positive feedback loop in effect - you feel like you're doing a bad job, so work longer hours on it, end up taking longer, feeling like you have "wasted" hours, and feel worse about doing a bad job.
Believe your employers when they say you are doing great, otherwise you're likely to be heading down the burnout route which had me off sick for half a year. It's not every coder that has such high standards as you, and that is not something to be ashamed of. Be proud of the code that you have produced. Think to yourself "It's just as well I wrote this bit, because if X had, it would have been awful".
I know this sounds like extreme arrogance, however sometimes it is necessary for the purposes of regaining balance. It sounds like you are being a little too humble. If it gets too bad though, get some help from someone.
Something else that can help is that once you've learned how to write clean, safe, reusable code, the next step is learning when not to. Clean code is an expense, and there's times to put in the extra effort, and there's times to not. Code's needs are not evenly distributed, in fact they are very unevenly distributed (power law distribution I suspect without proof)... carefully crafting to the n-th degree an end-user GUI page for a marginal feature is probably a waste of time, just make it work. On the other hand, adding a hack to a core routine used by huge swathes of the code may have much bigger negative effects than it even feels like now, and it sounds like it already feels pretty bad.
Consider working on the next level and using this as a chance to study when and where the effort is actually worth it. It may feel like you're handing yourself a license to be sloppier, but if done correctly this actually turns you into an even more capable developer than someone who finely engineers everything, because you'll have that much more time to finely engineer the things that matter once you clear away the time of fine engineering of the things that don't, and on the whole you'll be creating much more value in your code.
I wouldn't mind writing unclean code if I weren't the one who's going to have to maintain it and add new features to it in the near future or the years to come.
This is part of what I mean by learning when it is and is not appropriate; I tried to make it clear it was not a blanket permission slip to be sloppy (anticipating that obvious misunderstanding of my point). If you end up having to seriously maintain "unclean" code, you did it wrong. You will do it wrong before you get the hang of it, no sarcasm. Untrained gut intuitions are not very reliable here, and the only training available is practice.
And on the other hand, "maintain" is a very ambiguous word. If you are frustrated because it took you ten minutes to add one field to a form, once in the course of 3 years (to put some concrete numbers on for example's sake), you still came out ahead not spending an additional 10 hours polishing the code to a fine sheen, so you could be happy adding that one field 3 years later and saving that ten minutes. If you're frustrated because you actually have to overhaul it significantly, and it's a mess, and now you've also dropped all your context and can't remember what is what at all, and you could have cleaned up up three years ago in three hours and now lose two weeks just to understanding what the hell, then you've lost, yes. And of course "maintain" can mean a lot more than either of those two cases, too.
And as a final note, it's all gambling, and that is also something you must come to grips with. You don't really know where the changes are going to be in three years. However, you can learn to guess with a success rate much higher than mere random chance. (Don't forget to discount future time appropriately.)
But, enough on that. A few years before then, I felt like you did, but I wasn't actually in that situation. There is a very real positive feedback loop in effect - you feel like you're doing a bad job, so work longer hours on it, end up taking longer, feeling like you have "wasted" hours, and feel worse about doing a bad job.
Believe your employers when they say you are doing great, otherwise you're likely to be heading down the burnout route which had me off sick for half a year. It's not every coder that has such high standards as you, and that is not something to be ashamed of. Be proud of the code that you have produced. Think to yourself "It's just as well I wrote this bit, because if X had, it would have been awful".
I know this sounds like extreme arrogance, however sometimes it is necessary for the purposes of regaining balance. It sounds like you are being a little too humble. If it gets too bad though, get some help from someone.