Vistas
En src/main/webapp/WEB-INF creamos el archivo faces-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-facesconfig_4_0.xsd"
version="4.0">
<navigation-rule>
<from-view-id>
/login.xhtml
</from-view-id>
<navigation-case>
<from-outcome>
admin
</from-outcome>
<to-view-id>
/admin.xhtml
</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
En src/main/webapp creamos el archivo plantilla.xml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<ui:insert name="header">
<ui:include src="encabezado.xhtml"></ui:include>
</ui:insert>
<ui:insert name="content">
<ui:include src="contenido.xhtml"></ui:include>
</ui:insert>
</h:body>
</html>
En el mismo directorio creamos el archivo encabezado.xml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<ui:composition>
<div class="card">
<h:form>
<p:growl id="messages"/>
<p:menubar>
<p:menuitem value="#{loginView.nombreUsuario}" icon="pi pi-fw pi-file" outcome="" />
<p:submenu label="Mi control de Ventas" icon="pi pi-fw pi-file">
<p:menuitem value="Usuarios" icon="pi pi-fw pi-pencil" outcome="usuario" />
<p:menuitem value="Clientes" icon="pi pi-fw pi-pencil" outcome="cliente" />
</p:submenu>
<p:menuitem value="Salir" action="#{loginView.logout}" icon="pi pi-fw pi-power-off"/>
</p:menubar>
</h:form>
</div>
</ui:composition>
</h:body>
</html>
En directorio src/main/webapp creamos el folder images
Y en images colocamos la siguiente imagen

En directorio src/main/webapp creamos el archivo contenido.xml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<ui:composition>
<h:form>
<p:panel header="Mi control de ventas parciales" footer="Tutosoftware">
<h1 style="color:red;">MICOVEN</h1>
<h:graphicImage url="/images/book.jpg" />
</p:panel>
</h:form>
</ui:composition>
</h:body>
</html>
Escribimos el archivo login.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:body>
<div style="margin:0 auto;width:70%">
<ui:composition template="plantilla.xhtml" >
<ui:define name="header">
<h1><h:outputText value="Bienvenido" /></h1>
</ui:define>
<ui:define name="content" >
<h:form>
<p:growl id="messagesLogin"/>
<p:panel header="MICOVEN" footer="Tutosoftware">
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel value="Email:" for="email" />
<p:inputText id="email" value="#{loginView.email}" required="true" label="Correo">
</p:inputText>
<h:outputLabel value="Password:" for="contrasena" />
<p:password id="contrasena" value="#{loginView.contrasena}" required="true" label="password">
</p:password>
<f:facet name="footer">
<p:commandButton value="Acceder" action="#{loginView.loginAccess}" update="messagesLogin" > </p:commandButton>
</f:facet>
</h:panelGrid>
</p:panel>
</h:form>
</ui:define>
</ui:composition>
</div>
</h:body>
</html>
Escribimos la vista admin.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<ui:composition template="plantilla.xhtml">
</ui:composition>
</h:body>
</html>
Creamos el archivo usuario.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<ui:composition template="plantilla.xhtml">
<ui:define name="content" >
<h:form id="form1">
<p:panel header="MICOVEN" footer="Tutosoftware">
<h1><h:outputText value="Usuarios" /> </h1>
<p:toolbar>
<p:toolbarGroup>
<p:commandButton value="Crear Usuario" icon="pi pi-plus" actionListener="#{usuarioView.abrirNuevoUsuario}"
update=":dialogs:manage-usuario-content" oncomplete="PF('manageUsuarioDialog').show()"
styleClass="ui-button-success" style="margin-right: .5rem">
<p:resetInput target=":dialogs:manage-usuario-content" />
</p:commandButton>
</p:toolbarGroup>
</p:toolbar>
<p:dataTable id="dt-usuario" var="usuario" value="#{usuarioView.usuarios}"
reflow="true" selectionRowMode="add" paginatorPosition="bottom">
<p:column headerText="Nombre" >
<h:outputText value="#{usuario.nombre}" />
</p:column>
<p:column headerText="Apellido Paterno">
<h:outputText value="#{usuario.apellidopaterno}" />
</p:column>
<p:column headerText="Apellido Materno">
<h:outputText value="#{usuario.apellidomaterno}" />
</p:column>
<p:column headerText="Email">
<h:outputText value="#{usuario.email}" />
</p:column>
<p:column headerText="Password">
<h:outputText value="#{usuario.password}" />
</p:column>
<p:column headerText="Acciones">
<p:commandButton icon="pi pi-pencil" update=":dialogs:manage-usuario-content2"
oncomplete="PF('manageUsuarioDialog2').show()"
styleClass="edit-button rounded-button ui-button-success" process="@this">
<f:setPropertyActionListener value="#{usuario}" target="#{usuarioView.newusuario}" />
<p:resetInput target=":dialogs:manage-usuario-content2" />
</p:commandButton>
<p:commandButton class="ui-button-warning rounded-button" icon="pi pi-trash"
process="@this"
oncomplete="PF('deleteUsuarioDialog').show()">
<f:setPropertyActionListener value="#{usuario}" target="#{usuarioView.newusuario}" />
</p:commandButton>
</p:column>
</p:dataTable>
</p:panel>
</h:form>
<h:form id="dialogs">
<p:dialog header="Ingresa tus datos" showEffect="fade" modal="true" widgetVar="manageUsuarioDialog"
responsive="true">
<p:outputPanel id="manage-usuario-content" class="ui-fluid">
<p:outputPanel rendered="#{not empty usuarioView.newusuario}">
<div class="field">
<p:outputLabel for="nombre"><h:outputText value="Nombre" /></p:outputLabel>
<p:inputText id="nombre" value="#{usuarioView.newusuario.nombre}" required="true" />
</div>
<div class="field">
<p:outputLabel for="apellidoPaterno"><h:outputText value="Apellido Paterno" /></p:outputLabel>
<p:inputText id="apellidoPaterno" value="#{usuarioView.newusuario.apellidopaterno}" required="true" />
</div>
<div class="field">
<p:outputLabel for="apellidoMaterno"><h:outputText value="Apellido Materno" /></p:outputLabel>
<p:inputText id="apellidoMaterno" value="#{usuarioView.newusuario.apellidomaterno}" />
</div>
<div class="field">
<p:outputLabel for="email"><h:outputText value="Email" /></p:outputLabel>
<p:inputText id="email" value="#{usuarioView.newusuario.email}" required="true" />
</div>
<div class="field">
<p:outputLabel for="password"><h:outputText value="Password" /></p:outputLabel>
<p:inputText id="password" value="#{usuarioView.newusuario.password}" required="true" />
</div>
</p:outputPanel>
</p:outputPanel>
<f:facet name="footer">
<p:commandButton value="Guardar" icon="pi pi-check" actionListener="#{usuarioView.crearUsuario}"
update="manage-usuario-content,form1:dt-usuario" process="manage-usuario-content @this" />
<p:commandButton value="Cancelar" icon="pi pi-times" onclick="PF('manageUsuarioDialog').hide()"
class="ui-button-secondary" type="button" />
</f:facet>
</p:dialog>
<p:dialog header="Actualizar usuario" showEffect="fade" modal="true" widgetVar="manageUsuarioDialog2"
responsive="true">
<p:outputPanel id="manage-usuario-content2" class="ui-fluid">
<p:outputPanel rendered="#{not empty usuarioView.newusuario}">
<div class="field">
<p:outputLabel for="nombre2"><h:outputText value="Nombre" /></p:outputLabel>
<p:inputText id="nombre2" value="#{usuarioView.newusuario.nombre}" required="true" />
</div>
<div class="field">
<p:outputLabel for="apellidoPaterno2"><h:outputText value="Apellido Paterno" /></p:outputLabel>
<p:inputText id="apellidoPaterno2" value="#{usuarioView.newusuario.apellidopaterno}" required="true" />
</div>
<div class="field">
<p:outputLabel for="apellidoMaterno2"><h:outputText value="Apellido Materno" /></p:outputLabel>
<p:inputText id="apellidoMaterno2" value="#{usuarioView.newusuario.apellidomaterno}" />
</div>
<div class="field">
<p:outputLabel for="email2"><h:outputText value="Email" /></p:outputLabel>
<p:inputText id="email2" value="#{usuarioView.newusuario.email}" required="true" readonly="true" />
</div>
<div class="field">
<p:outputLabel for="password2"><h:outputText value="Password" /></p:outputLabel>
<p:inputText id="password2" value="#{usuarioView.newusuario.password}" required="true" />
</div>
</p:outputPanel>
</p:outputPanel>
<f:facet name="footer">
<p:commandButton value="Actualizar" icon="pi pi-check" actionListener="#{usuarioView.actualizarUsuario()}"
update="manage-usuario-content2,form1:dt-usuario" process="manage-usuario-content2 @this" />
<p:commandButton value="Cancelar" icon="pi pi-times" onclick="PF('manageUsuarioDialog2').hide()"
class="ui-button-secondary" type="button" />
</f:facet>
</p:dialog>
<p:confirmDialog widgetVar="deleteUsuarioDialog" showEffect="fade" width="300"
message="Eliminar" header="Eliminar Usuario" severity="warn">
<p:commandButton value="Si" icon="pi pi-check" actionListener="#{usuarioView.eliminarUsuario}"
process="@this" update="form1:dt-usuario"
oncomplete="PF('deleteUsuarioDialog').hide()" />
<p:commandButton value="No" type="button" styleClass="ui-button-secondary" icon="pi pi-times"
onclick="PF('deleteUsuarioDialog').hide()" />
</p:confirmDialog>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
Creamos el archivo cliente.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<ui:composition template="plantilla.xhtml">
<ui:define name="content" >
<h:form id="form1">
<p:panel header="MICOVEN" footer="Tutosoftware">
<h1><h:outputText value="Clientes" /> </h1>
<p:toolbar>
<p:toolbarGroup>
<p:commandButton value="Crear Cliente" icon="pi pi-plus" actionListener="#{clienteView.abrirNuevoCliente}"
update=":dialogs:manage-cliente-content" oncomplete="PF('manageClienteDialog').show()"
styleClass="ui-button-success" style="margin-right: .5rem">
<p:resetInput target=":dialogs:manage-cliente-content" />
</p:commandButton>
</p:toolbarGroup>
</p:toolbar>
<p:dataTable id="dt-cliente" var="cliente" value="#{clienteView.clientes}"
reflow="true" selectionRowMode="add" paginatorPosition="bottom">
<p:column headerText="Whatsapp" >
<h:outputText value="#{cliente.whatsapp}" />
</p:column>
<p:column headerText="Nombre" >
<h:outputText value="#{cliente.nombre}" />
</p:column>
<p:column headerText="Apellido Paterno">
<h:outputText value="#{cliente.apellidopaterno}" />
</p:column>
<p:column headerText="Apellido Materno">
<h:outputText value="#{cliente.apellidomaterno}" />
</p:column>
<p:column headerText="Cuenta">
<p:commandButton icon="pi pi-pencil" value="Ver cuenta" >
</p:commandButton>
</p:column>
<p:column headerText="Acciones">
<p:commandButton icon="pi pi-pencil" update=":dialogs:manage-cliente-content2"
oncomplete="PF('manageClienteDialog2').show()"
styleClass="edit-button rounded-button ui-button-success" process="@this">
<f:setPropertyActionListener value="#{cliente}" target="#{clienteView.newcliente}" />
<p:resetInput target=":dialogs:manage-cliente-content2" />
</p:commandButton>
<p:commandButton class="ui-button-warning rounded-button" icon="pi pi-trash"
process="@this"
oncomplete="PF('deleteClienteDialog').show()">
<f:setPropertyActionListener value="#{cliente}" target="#{clienteView.newcliente}" />
</p:commandButton>
</p:column>
</p:dataTable>
</p:panel>
</h:form>
<h:form id="dialogs">
<p:dialog header="Ingresa tus datos" showEffect="fade" modal="true" widgetVar="manageClienteDialog"
responsive="true">
<p:outputPanel id="manage-cliente-content" class="ui-fluid">
<p:outputPanel rendered="#{not empty clienteView.newcliente}">
<div class="field">
<p:outputLabel for="whatsapp"><h:outputText value="Whatsapp" /></p:outputLabel>
<p:inputText id="whatsapp" value="#{clienteView.newcliente.whatsapp}" required="true" />
</div>
<div class="field">
<p:outputLabel for="nombre"><h:outputText value="Nombre" /></p:outputLabel>
<p:inputText id="nombre" value="#{clienteView.newcliente.nombre}" required="true" />
</div>
<div class="field">
<p:outputLabel for="apellidoPaterno"><h:outputText value="Apellido Paterno" /></p:outputLabel>
<p:inputText id="apellidoPaterno" value="#{clienteView.newcliente.apellidopaterno}" required="true" />
</div>
<div class="field">
<p:outputLabel for="apellidoMaterno"><h:outputText value="Apellido Materno" /></p:outputLabel>
<p:inputText id="apellidoMaterno" value="#{clienteView.newcliente.apellidomaterno}" />
</div>
<div class="field">
<h:inputHidden id="tienecuenta" value="#{clienteView.newcliente.tienecuenta}" />
</div>
</p:outputPanel>
</p:outputPanel>
<f:facet name="footer">
<p:commandButton value="Guardar" icon="pi pi-check" actionListener="#{clienteView.crearCliente}"
update="manage-cliente-content,form1:dt-cliente" process="manage-cliente-content @this" />
<p:commandButton value="Cancelar" icon="pi pi-times" onclick="PF('manageClienteDialog').hide()"
class="ui-button-secondary" type="button" />
</f:facet>
</p:dialog>
<p:dialog header="Actualizar cliente" showEffect="fade" modal="true" widgetVar="manageClienteDialog2"
responsive="true">
<p:outputPanel id="manage-cliente-content2" class="ui-fluid">
<p:outputPanel rendered="#{not empty clienteView.newcliente}">
<div class="field">
<p:outputLabel for="whatsapp2"><h:outputText value="Whatsapp" /></p:outputLabel>
<p:inputText id="whatsapp2" value="#{clienteView.newcliente.whatsapp}" required="true" readonly="true" />
</div>
<div class="field">
<p:outputLabel for="nombre2"><h:outputText value="Nombre" /></p:outputLabel>
<p:inputText id="nombre2" value="#{clienteView.newcliente.nombre}" required="true" />
</div>
<div class="field">
<p:outputLabel for="apellidoPaterno2"><h:outputText value="Apellido Paterno" /></p:outputLabel>
<p:inputText id="apellidoPaterno2" value="#{clienteView.newcliente.apellidopaterno}" required="true" />
</div>
<div class="field">
<p:outputLabel for="apellidoMaterno2"><h:outputText value="Apellido Materno" /></p:outputLabel>
<p:inputText id="apellidoMaterno2" value="#{clienteView.newcliente.apellidomaterno}" />
</div>
<div class="field">
<h:inputHidden id="tienecuenta2" value="#{clienteView.newcliente.tienecuenta}" />
</div>
</p:outputPanel>
</p:outputPanel>
<f:facet name="footer">
<p:commandButton value="Actualizar" icon="pi pi-check" actionListener="#{clienteView.actualizarCliente}"
update="manage-cliente-content2,form1:dt-cliente" process="manage-cliente-content2 @this" />
<p:commandButton value="Cancelar" icon="pi pi-times" onclick="PF('manageClienteDialog2').hide()"
class="ui-button-secondary" type="button" />
</f:facet>
</p:dialog>
<p:confirmDialog widgetVar="deleteClienteDialog" showEffect="fade" width="300"
message="Eliminar" header="Eliminar Cliente" severity="warn">
<p:commandButton value="Si" icon="pi pi-check" actionListener="#{clienteView.eliminarCliente}"
process="@this" update="form1:dt-cliente"
oncomplete="PF('deleteClienteDialog').hide()" />
<p:commandButton value="No" type="button" styleClass="ui-button-secondary" icon="pi pi-times"
onclick="PF('deleteClienteDialog').hide()" />
</p:confirmDialog>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>