Hi @rotcivegaf,
Welcome to the community 
You could do something like the following.
You would need to add a mint function to meet your requirements for how you are setting the tokenURI. Your mint should be appropriately protected with AccessControl (we have a workshop on AccessControl next week: https://blog.openzeppelin.com/ozevents)
You may or may not want to include _baseURI
depending on your requirements.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
contract Foo is ERC721, ERC721Enumerable, ERC721URIStorage {
constructor() ERC721("Foo", "foo") {}
function _beforeTokenTransfer(address from, address to, uint256 tokenId)
internal
override(ERC721, ERC721Enumerable)
{
super._beforeTokenTransfer(from, to, tokenId);
}
function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) {
super._burn(tokenId);
}
function tokenURI(uint256 tokenId)
public
view
override(ERC721, ERC721URIStorage)
returns (string memory)
{
return super.tokenURI(tokenId);
}
function supportsInterface(bytes4 interfaceId)
public
view
override(ERC721, ERC721Enumerable)
returns (bool)
{
return super.supportsInterface(interfaceId);
}
function _baseURI() internal pure override returns (string memory) {
return "https://foo.com/token/";
}
}