updates for admin area
This commit is contained in:
+15
-3
@@ -1,4 +1,16 @@
|
||||
@import "tailwindcss";
|
||||
:root{--ink:#070a19;--panel:#0d1228;--purple:#7c3aed;--pink:#ec4899;--cyan:#22d3ee;--gold:#fbbf24}*{box-sizing:border-box}body{margin:0;background:#070a19;color:#f8fafc;font-family:Inter,ui-sans-serif,system-ui,sans-serif}.shell{max-width:1280px;margin:auto;padding:0 24px}.nav{height:76px;display:flex;align-items:center;justify-content:space-between}.brand{font-size:25px;font-weight:900;color:white;text-decoration:none}.brand b{color:#ec4899}.navlinks{display:flex;gap:28px}.navlinks a{color:#dbeafe;text-decoration:none;font-size:14px}.button{display:inline-flex;padding:13px 20px;border-radius:12px;background:linear-gradient(135deg,var(--purple),var(--pink));color:white;text-decoration:none;border:0;font-weight:800}.button.ghost{background:transparent;border:1px solid #334155}.hero{min-height:610px;background:linear-gradient(90deg,rgba(7,10,25,.97) 0%,rgba(7,10,25,.72) 50%,rgba(7,10,25,.25)),url('https://images.unsplash.com/photo-1571266028243-d220c9c3b2d2?auto=format&fit=crop&w=2000&q=85') center/cover;border-bottom:1px solid #202743}.hero-copy{padding:105px 0 35px;max-width:760px}.eyebrow{color:#67e8f9;font-weight:800;letter-spacing:.18em;text-transform:uppercase}.hero h1{font-size:72px;line-height:.95;margin:14px 0 22px;letter-spacing:-.05em}.hero h1 span{background:linear-gradient(90deg,#c084fc,#f472b6,#22d3ee);background-clip:text;color:transparent}.hero p{font-size:19px;color:#cbd5e1;max-width:620px}.searchbox{margin-top:34px;padding:10px;background:white;border-radius:18px;display:grid;grid-template-columns:1.2fr 1fr 1fr auto;gap:8px;box-shadow:0 25px 80px #0008}.searchbox input,.searchbox select{border:0;padding:17px;color:#0f172a;background:#f8fafc;border-radius:10px;outline:none}.section{padding:72px 0}.section-head{display:flex;justify-content:space-between;align-items:end;margin-bottom:25px}.section h2{font-size:34px;margin:0}.muted{color:#94a3b8}.cards{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}.card{background:#10162d;border:1px solid #27304d;border-radius:18px;overflow:hidden;box-shadow:0 14px 35px #0004}.card-img{height:235px;background:center/cover}.card-body{padding:18px}.card h3{margin:0 0 8px;font-size:20px}.stars{color:var(--gold)}.price{font-size:20px;font-weight:900;margin:14px 0}.chips{display:flex;gap:7px;flex-wrap:wrap}.chip{font-size:12px;padding:6px 9px;background:#1e293b;border-radius:99px;color:#cbd5e1}.profile-hero{height:350px;background:center/cover;position:relative}.profile-panel{margin:-90px auto 40px;position:relative;background:white;color:#0f172a;border-radius:22px;padding:30px;display:grid;grid-template-columns:130px 1fr 220px;gap:25px;box-shadow:0 30px 70px #0007}.avatar{width:130px;height:130px;border-radius:16px;object-fit:cover}.admin{display:grid;grid-template-columns:240px 1fr;min-height:100vh;background:#f8fafc;color:#0f172a}.sidebar{background:#0b1022;color:white;padding:28px 18px}.sidebar a{display:block;color:#cbd5e1;text-decoration:none;padding:11px;border-radius:8px}.sidebar a:hover{background:#1e293b}.admin-main{padding:35px}.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:18px}.stat{background:white;padding:24px;border-radius:14px;box-shadow:0 3px 15px #0f172a0d}.stat strong{display:block;font-size:30px;color:#7c3aed}.cookie{position:fixed;bottom:18px;left:18px;right:18px;max-width:650px;background:#fff;color:#0f172a;border-radius:16px;padding:18px;box-shadow:0 20px 60px #0008;z-index:50}@media(max-width:900px){.navlinks{display:none}.hero h1{font-size:50px}.searchbox{grid-template-columns:1fr}.cards{grid-template-columns:1fr 1fr}.profile-panel{grid-template-columns:1fr;margin:-40px 16px 30px}.admin{grid-template-columns:1fr}.sidebar{display:none}.stats{grid-template-columns:1fr 1fr}}@media(max-width:600px){.cards,.stats{grid-template-columns:1fr}.hero h1{font-size:42px}.hero-copy{padding-top:70px}}
|
||||
.nav-actions{display:flex;gap:9px;align-items:center}.inline-form{display:inline;margin:0}.footer{border-top:1px solid #1e293b}.flash{margin-top:14px;padding:14px 18px;border-radius:12px}.flash.success{background:#064e3b}.cookie p{margin:6px 0 12px}.cookie-secondary{color:#0f172a}.auth-page{min-height:calc(100vh - 160px);padding:70px 24px;background:radial-gradient(circle at 20% 15%,#3b076455,transparent 35%),radial-gradient(circle at 85% 35%,#164e6355,transparent 32%),#070a19}.auth-card{width:min(100%,520px);margin:0 auto;background:#10162d;border:1px solid #27304d;border-radius:24px;padding:34px;box-shadow:0 28px 80px #0008}.auth-card h1{margin:10px 0 8px;font-size:36px}.auth-form{display:grid;gap:16px;margin-top:26px}.auth-form label{display:grid;gap:8px;font-weight:700;color:#e2e8f0}.auth-form input{width:100%;border:1px solid #334155;background:#0b1022;color:#f8fafc;border-radius:12px;padding:14px 15px;font:inherit;outline:none}.auth-form input:focus{border-color:#a855f7;box-shadow:0 0 0 3px #a855f722}.auth-form .check-row{display:flex;grid-template-columns:auto 1fr;align-items:center;font-weight:500}.auth-form .check-row input{width:auto}.button.full{justify-content:center;width:100%;cursor:pointer}.auth-links{display:flex;flex-direction:column;gap:10px;margin-top:22px;color:#94a3b8}.auth-links a{color:#67e8f9;text-decoration:none}.form-errors{margin-top:18px;padding:14px 16px;border:1px solid #7f1d1d;background:#450a0a;color:#fecaca;border-radius:12px;display:grid;gap:5px}
|
||||
@media(max-width:900px){.nav-actions{gap:6px}.nav-actions .button{padding:10px 12px}.auth-page{padding:40px 16px}}@media(max-width:600px){.nav{height:auto;min-height:70px;gap:12px}.nav-actions{flex-wrap:wrap;justify-content:flex-end}.auth-card{padding:24px}.auth-card h1{font-size:30px}}
|
||||
|
||||
:root{--bg:#070914;--panel:#101526;--panel-2:#151c31;--line:#26304a;--text:#f8fafc;--muted:#9aa8bd;--purple:#7c3aed;--pink:#ec4899;--cyan:#22d3ee;--gold:#fbbf24;--white:#fff;--admin-bg:#f5f7fb;--admin-ink:#172033;--admin-muted:#65738a;--admin-line:#e4e9f1;--shadow:0 18px 55px rgba(0,0,0,.24)}
|
||||
*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;background:var(--bg);color:var(--text);font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;-webkit-font-smoothing:antialiased}a{color:inherit}.shell{width:min(100% - 40px,1240px);margin-inline:auto}.muted{color:var(--muted)}
|
||||
.site-header{height:76px;border-bottom:1px solid rgba(255,255,255,.07);background:rgba(7,9,20,.88);backdrop-filter:blur(18px);position:sticky;top:0;z-index:40}.nav{height:100%;display:flex;align-items:center;gap:32px}.brand{display:inline-flex;align-items:center;gap:8px;font-size:24px;font-weight:900;letter-spacing:-.04em;text-decoration:none;white-space:nowrap}.brand b{color:var(--pink)}.nav-panel{margin-left:auto;display:flex;align-items:center;gap:34px}.navlinks{display:flex;align-items:center;gap:26px}.navlinks a,.text-button{font-size:14px;font-weight:700;color:#dce5f4;text-decoration:none;background:none;border:0;padding:8px 0;cursor:pointer;font:inherit}.navlinks a:hover,.text-button:hover{color:#fff}.nav-actions{display:flex;align-items:center;gap:12px}.nav-account-link{display:flex;align-items:center;gap:8px;color:#fff;text-decoration:none;font-weight:800;font-size:14px}.mini-avatar{display:grid;place-items:center;width:31px;height:31px;border-radius:50%;background:linear-gradient(135deg,var(--purple),var(--pink));font-size:12px}.mobile-menu-button{display:none;margin-left:auto;background:transparent;border:1px solid #34405d;color:#fff;border-radius:10px;width:42px;height:42px;font-size:21px}.inline-form{margin:0}.button{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:46px;padding:0 19px;border:0;border-radius:12px;background:linear-gradient(135deg,var(--purple),var(--pink));color:#fff;font:inherit;font-size:14px;font-weight:850;text-decoration:none;cursor:pointer;box-shadow:0 9px 24px rgba(124,58,237,.24);transition:transform .18s ease,filter .18s ease}.button:hover{transform:translateY(-1px);filter:brightness(1.06)}.button.ghost{background:transparent;border:1px solid #3a4663;box-shadow:none}.button.small{min-height:40px;padding:0 15px}.button.full{width:100%}
|
||||
.hero{min-height:640px;position:relative;display:flex;align-items:center;background:url('https://images.unsplash.com/photo-1571266028243-d220c9c3b2d2?auto=format&fit=crop&w=2200&q=84') center 38%/cover no-repeat}.hero-shade{position:absolute;inset:0;background:linear-gradient(90deg,rgba(7,9,20,.98) 0%,rgba(7,9,20,.91) 44%,rgba(7,9,20,.47) 72%,rgba(7,9,20,.18) 100%)}.hero-layout{position:relative;z-index:1}.hero-copy{max-width:790px;padding:82px 0}.eyebrow{color:#67e8f9;font-size:12px;font-weight:900;letter-spacing:.18em;text-transform:uppercase}.hero h1{max-width:760px;margin:14px 0 22px;font-size:clamp(46px,6vw,78px);line-height:.97;letter-spacing:-.06em}.hero h1 span{background:linear-gradient(90deg,#c084fc,#f472b6,#67e8f9);-webkit-background-clip:text;background-clip:text;color:transparent}.hero-copy>p{max-width:650px;color:#c3cede;font-size:18px;line-height:1.65}.searchbox,.filterbar{display:grid;gap:8px;background:#fff;border-radius:18px;padding:9px;box-shadow:0 24px 70px rgba(0,0,0,.42)}.searchbox{grid-template-columns:1.2fr 1fr 1fr auto;margin-top:30px}.searchbox label,.filterbar label{display:grid;gap:3px;padding:8px 12px;border-radius:11px;background:#f6f8fb}.searchbox label span,.filterbar label span{font-size:10px;font-weight:900;color:#64748b;text-transform:uppercase;letter-spacing:.08em}.searchbox input,.searchbox select,.filterbar input,.filterbar select{min-width:0;width:100%;border:0;outline:0;background:transparent;color:#172033;font:inherit;font-size:14px}.hero-proof{display:flex;gap:22px;flex-wrap:wrap;margin-top:18px;color:#cbd5e1;font-size:13px;font-weight:700}
|
||||
.section{padding:78px 0}.section-alt{background:#0c1120;border-block:1px solid rgba(255,255,255,.06)}.section-head{display:flex;justify-content:space-between;align-items:end;gap:24px;margin-bottom:28px}.section-head h2,.section-intro h2,.split-feature h2,.pricing-box h2{font-size:clamp(30px,4vw,44px);letter-spacing:-.04em;margin:6px 0 8px}.section-head p,.section-intro p,.split-feature .lead,.pricing-box p{color:var(--muted);line-height:1.65}.cards{display:grid;gap:20px}.dj-cards{grid-template-columns:repeat(4,minmax(0,1fr))}.card{background:var(--panel);border:1px solid var(--line);border-radius:18px;overflow:hidden;box-shadow:0 12px 34px rgba(0,0,0,.18)}.dj-card{min-width:0}.card-img{display:block;aspect-ratio:4/3;background-position:center;background-size:cover}.card-body{padding:18px}.card-title-line{display:flex;align-items:center;gap:8px}.card-title-line h3{margin:0;font-size:19px;letter-spacing:-.02em}.verified{display:inline-grid;place-items:center;width:20px;height:20px;border-radius:50%;background:#2563eb;color:#fff;font-size:12px;font-weight:900}.verified.large{width:25px;height:25px}.stars{color:var(--gold);font-size:14px;font-weight:800}.stars span{color:var(--muted);font-weight:600}.card-body>p{min-height:42px;margin:10px 0;color:var(--muted);font-size:14px;line-height:1.5}.card-foot{display:flex;justify-content:space-between;align-items:center;gap:10px;padding-top:14px;border-top:1px solid var(--line)}.card-foot strong{font-size:17px}.card-foot a{color:#a5f3fc;text-decoration:none;font-size:13px;font-weight:800}.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-top:30px}.step-card{padding:26px;border:1px solid var(--line);border-radius:18px;background:linear-gradient(180deg,#11182b,#0e1425)}.step-card>span{font-size:12px;font-weight:900;color:#c084fc}.step-card h3{margin:26px 0 8px;font-size:21px}.step-card p{margin:0;color:var(--muted);line-height:1.55}.split-feature{display:grid;grid-template-columns:.9fr 1.1fr;gap:70px;align-items:center}.feature-list{display:grid;grid-template-columns:1fr 1fr;gap:14px}.feature-list>div{display:grid;gap:6px;padding:22px;background:var(--panel);border:1px solid var(--line);border-radius:16px}.feature-list span{color:var(--muted);line-height:1.5;font-size:14px}.pricing-section{padding-top:0}.pricing-box{display:flex;align-items:center;justify-content:space-between;gap:40px;padding:42px;border-radius:24px;background:linear-gradient(135deg,#1b1141,#10223b);border:1px solid #3a3f68}.pricing-box>div{max-width:760px}
|
||||
.directory-page{padding:68px 0 82px}.directory-heading{display:flex;justify-content:space-between;align-items:end;gap:20px}.directory-heading h1{font-size:clamp(40px,6vw,62px);margin:6px 0 6px;letter-spacing:-.05em}.directory-heading p{color:var(--muted)}.results-count,.metric-chip{display:inline-flex;align-items:center;padding:8px 12px;border-radius:999px;background:#171e31;border:1px solid var(--line);font-size:12px;font-weight:800;color:#cbd5e1}.filterbar{grid-template-columns:1.1fr 1fr 1fr auto;margin:28px 0 34px}.directory-empty{grid-column:1/-1}.pagination-wrap{margin-top:32px}.pagination-wrap nav{color:#fff}
|
||||
.profile-hero{height:360px;background:center/cover}.profile-shell{padding-bottom:80px}.profile-panel{position:relative;margin-top:-82px;background:#fff;color:#172033;border-radius:22px;padding:26px;display:grid;grid-template-columns:126px 1fr 210px;gap:24px;align-items:center;box-shadow:0 24px 70px rgba(0,0,0,.38)}.avatar{width:126px;height:126px;border-radius:16px;object-fit:cover}.profile-title{display:flex;align-items:center;gap:10px}.profile-title h1{margin:0;font-size:36px;letter-spacing:-.04em}.profile-summary p{color:#64748b}.chips{display:flex;gap:7px;flex-wrap:wrap}.chip{padding:6px 9px;border-radius:999px;background:#eef2f7;color:#526078;font-size:11px;font-weight:800}.profile-price{display:flex;flex-direction:column;align-items:flex-start;padding-left:22px;border-left:1px solid #e2e8f0}.profile-price>span,.profile-price small{color:#64748b}.profile-price strong{font-size:36px;line-height:1.1}.profile-price .button{margin-top:14px;width:100%}.profile-grid{display:grid;grid-template-columns:minmax(0,1fr) 370px;gap:34px;padding-top:38px}.profile-section{padding:4px 0 24px}.profile-section h2,.enquiry-card h2{font-size:27px;letter-spacing:-.03em}.profile-bio{color:#aab6c8;font-size:16px;line-height:1.8}.review-card{padding:20px 0;border-top:1px solid var(--line)}.review-card h3{margin:8px 0}.review-card p{color:var(--muted);line-height:1.65}.enquiry-card{height:max-content;position:sticky;top:100px;padding:24px;background:var(--panel);border:1px solid var(--line);border-radius:19px}.enquiry-card>p{color:var(--muted)}.enquiry-form,.settings-form{display:grid;gap:14px}.enquiry-form label,.settings-form label{display:grid;gap:7px}.enquiry-form label span,.settings-form label span{font-size:12px;font-weight:800;color:#b8c5d8}.enquiry-form input,.enquiry-form textarea,.settings-form input,.settings-form select{width:100%;border:1px solid #34405c;background:#0b1020;color:#fff;border-radius:10px;padding:12px 13px;font:inherit}.enquiry-form textarea{min-height:120px;resize:vertical}
|
||||
.flash{margin-top:14px;padding:13px 16px;border-radius:12px}.flash.success{background:#064e3b;border:1px solid #047857}.site-footer{border-top:1px solid #1e293b;background:#080b16;padding:56px 0 24px}.footer-grid{display:grid;grid-template-columns:2fr 1fr 1fr;gap:50px}.footer-grid>div{display:flex;flex-direction:column;gap:10px}.footer-grid p{max-width:470px;color:var(--muted);line-height:1.6}.footer-grid a:not(.brand){color:#9aa8bd;text-decoration:none;font-size:14px}.footer-bottom{margin-top:40px;padding-top:22px;border-top:1px solid #1b2235;color:#68768c;font-size:12px}.cookie{position:fixed;left:20px;right:20px;bottom:20px;z-index:60;max-width:720px;padding:18px;display:flex;align-items:center;justify-content:space-between;gap:20px;background:#fff;color:#172033;border-radius:16px;box-shadow:0 22px 70px rgba(0,0,0,.5)}.cookie p{margin:5px 0 0;color:#64748b;font-size:13px}.cookie-actions{display:flex;gap:8px;flex-shrink:0}.cookie .button.ghost{color:#172033;border-color:#cbd5e1}
|
||||
.auth-page{min-height:calc(100vh - 76px);padding:64px 20px;background:radial-gradient(circle at 20% 15%,rgba(124,58,237,.25),transparent 35%),radial-gradient(circle at 85% 35%,rgba(34,211,238,.13),transparent 32%),var(--bg)}.auth-card{width:min(100%,510px);margin:auto;background:var(--panel);border:1px solid var(--line);border-radius:22px;padding:32px;box-shadow:var(--shadow)}.auth-card h1{font-size:34px;margin:10px 0 8px}.auth-form{display:grid;gap:16px;margin-top:24px}.auth-form label{display:grid;gap:7px;font-weight:700;color:#dbe4f2}.auth-form input{width:100%;border:1px solid #34405d;background:#0a0f1d;color:#fff;border-radius:11px;padding:13px 14px;font:inherit}.auth-form .check-row{display:flex;align-items:center;gap:9px;font-weight:500}.auth-form .check-row input{width:auto}.auth-links{display:flex;flex-direction:column;gap:8px;margin-top:20px;color:var(--muted)}.auth-links a{color:#67e8f9;text-decoration:none}.form-errors{padding:12px 14px;border:1px solid #7f1d1d;background:#450a0a;color:#fecaca;border-radius:10px}
|
||||
.account-page{padding:54px 0 78px;min-height:70vh}.account-shell{display:grid;grid-template-columns:240px minmax(0,1fr);gap:28px}.account-sidebar{height:max-content;position:sticky;top:100px;background:var(--panel);border:1px solid var(--line);border-radius:18px;overflow:hidden}.account-person{display:flex;align-items:center;gap:11px;padding:18px;border-bottom:1px solid var(--line)}.account-avatar{width:42px;height:42px;display:grid;place-items:center;border-radius:50%;background:linear-gradient(135deg,var(--purple),var(--pink));font-weight:900}.account-person div:last-child{display:grid;min-width:0}.account-person span{font-size:11px;color:var(--muted);overflow:hidden;text-overflow:ellipsis}.account-nav{padding:9px}.account-nav a{display:block;padding:11px 12px;border-radius:9px;color:#bac6d8;text-decoration:none;font-size:14px;font-weight:700}.account-nav a:hover,.account-nav a.active{background:#1b2440;color:#fff}.account-content{min-width:0}.page-heading{display:flex;align-items:flex-end;justify-content:space-between;gap:22px;margin-bottom:24px}.page-heading h1{font-size:clamp(34px,4vw,48px);margin:6px 0;letter-spacing:-.045em}.page-heading p{margin:0;color:var(--muted)}.account-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-bottom:20px}.account-stat{padding:20px;background:var(--panel);border:1px solid var(--line);border-radius:15px}.account-stat span{display:block;color:var(--muted);font-size:12px;font-weight:800}.account-stat strong{display:block;margin-top:4px;font-size:30px}.dashboard-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}.panel{background:var(--panel);border:1px solid var(--line);border-radius:16px;padding:20px;min-width:0}.panel-head{display:flex;justify-content:space-between;align-items:center;gap:14px}.panel-head h2{margin:0;font-size:19px}.panel-head a,.panel-head span{color:#67e8f9;text-decoration:none;font-size:12px;font-weight:800}.list-row{display:flex;justify-content:space-between;align-items:center;gap:14px;padding:15px 0;border-top:1px solid var(--line);text-decoration:none}.list-row:first-of-type{margin-top:10px}.list-row div{display:grid;gap:3px}.list-row span{color:var(--muted);font-size:12px}.status-pill{display:inline-flex;align-items:center;width:max-content;padding:5px 8px;border-radius:999px;background:#e9eef6;color:#475569;font-size:11px!important;font-weight:800;white-space:nowrap}.empty-state{padding:28px 12px;color:var(--muted);text-align:center;line-height:1.6}.table-panel{padding:0;overflow:hidden}.responsive-table{width:100%;overflow-x:auto}.responsive-table table{width:100%;border-collapse:collapse;min-width:720px}.responsive-table th,.responsive-table td{padding:14px 16px;text-align:left;border-bottom:1px solid rgba(255,255,255,.08);font-size:13px;vertical-align:middle}.responsive-table th{color:#8f9db2;font-size:10px;text-transform:uppercase;letter-spacing:.08em}.responsive-table td small{display:block;color:var(--muted);margin-top:3px}.form-panel{max-width:720px}.settings-form input{background:#0b1020}.check-line{display:flex!important;grid-template-columns:auto 1fr;align-items:center}.check-line input{width:auto!important}
|
||||
.admin-body{background:var(--admin-bg);color:var(--admin-ink)}.admin-shell{min-height:100vh;display:grid;grid-template-columns:248px minmax(0,1fr)}.admin-sidebar{position:sticky;top:0;height:100vh;display:flex;flex-direction:column;padding:20px 14px;background:#0b1020;color:#fff;overflow-y:auto;z-index:80}.admin-sidebar-head{display:flex;align-items:center;justify-content:space-between;padding:0 8px 18px}.admin-kicker{padding:0 10px 8px;color:#66748c;font-size:10px;font-weight:900;text-transform:uppercase;letter-spacing:.12em}.admin-nav{display:grid;gap:2px}.admin-nav a,.admin-sidebar-foot a,.admin-sidebar-foot button{display:block;width:100%;padding:9px 10px;border:0;border-radius:8px;background:transparent;color:#aab7ca;text-align:left;text-decoration:none;font:inherit;font-size:13px;font-weight:700;cursor:pointer}.admin-nav a:hover,.admin-nav a.active,.admin-sidebar-foot a:hover,.admin-sidebar-foot button:hover{background:#17203a;color:#fff}.admin-sidebar-foot{margin-top:auto;padding-top:16px;border-top:1px solid #202a42}.admin-content{min-width:0}.admin-topbar{height:66px;padding:0 28px;display:flex;align-items:center;justify-content:space-between;gap:15px;background:#fff;border-bottom:1px solid var(--admin-line);position:sticky;top:0;z-index:30}.admin-topbar>div{display:grid}.admin-topbar span{font-size:11px;color:var(--admin-muted)}.admin-page{padding:30px}.admin-heading h1{color:var(--admin-ink)}.admin-heading p{color:var(--admin-muted)}.admin-stats{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:18px}.admin-stat{display:block;padding:20px;background:#fff;border:1px solid var(--admin-line);border-radius:14px;color:inherit;text-decoration:none;box-shadow:0 4px 18px rgba(31,45,75,.04)}.admin-stat span{display:block;color:var(--admin-muted);font-size:11px;font-weight:800;text-transform:uppercase}.admin-stat strong{display:block;margin:6px 0 4px;font-size:29px;letter-spacing:-.04em}.admin-stat small{color:#7c3aed;font-weight:800}.admin-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px}.admin-card{padding:20px;background:#fff;border:1px solid var(--admin-line);border-radius:14px;box-shadow:0 4px 18px rgba(31,45,75,.04);min-width:0}.admin-card-wide{grid-column:1/-1}.admin-card .panel-head h2{color:var(--admin-ink)}.admin-list-row{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:13px 0;border-top:1px solid var(--admin-line);font-size:12px}.admin-list-row:first-of-type{margin-top:10px}.admin-list-row>div{display:grid}.admin-list-row span{color:var(--admin-muted)}.admin-card .responsive-table th,.admin-card .responsive-table td{border-color:var(--admin-line);color:var(--admin-ink)}.admin-card .responsive-table th{color:#7a879c}.table-card{padding:0;overflow:hidden}.admin-button,.toggle-button{display:inline-flex;align-items:center;justify-content:center;min-height:33px;padding:0 11px;border:0;border-radius:8px;background:#172033;color:#fff;font:inherit;font-size:11px;font-weight:800;text-decoration:none;cursor:pointer}.toggle-button{background:#e9eef6;color:#5a677c}.toggle-button.on{background:#dcfce7;color:#166534}.inline-controls{display:flex;align-items:center;gap:7px}.inline-controls select{min-width:110px;padding:7px 9px;border:1px solid #d5dce7;border-radius:8px;background:#fff;color:#172033;font:inherit;font-size:11px}.admin-muted{color:var(--admin-muted);line-height:1.6}.admin-flash{margin:18px 30px 0;padding:12px 15px;border-radius:10px;background:#dcfce7;color:#166534;border:1px solid #bbf7d0;font-size:13px}.settings-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:16px}.settings-list>div{display:grid;grid-template-columns:140px 1fr auto;gap:14px;padding:12px 0;border-top:1px solid var(--admin-line);font-size:12px}.settings-list>div:first-child{margin-top:10px}.settings-list span{color:var(--admin-muted)}.action-card{display:block;color:inherit;text-decoration:none}.action-card:hover{border-color:#b8a5ff}.action-card h2{margin-top:0}.action-card p{color:var(--admin-muted);line-height:1.6}.action-card>span{color:#6d28d9;font-size:12px;font-weight:900}.role-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px}.role-badge{display:inline-flex;padding:5px 8px;border-radius:999px;background:#ede9fe;color:#6d28d9;font-size:11px;font-weight:900}.role-count{display:block;font-size:30px;margin-top:16px}.feature-empty{text-align:center;padding:38px 15px}.feature-icon{width:54px;height:54px;margin:0 auto 14px;display:grid;place-items:center;border-radius:15px;background:#ede9fe;color:#6d28d9;font-size:24px;font-weight:900}.feature-empty p{max-width:560px;margin:0 auto 20px;color:var(--admin-muted);line-height:1.6}.icon-button{display:none;border:0;background:transparent;font-size:22px;cursor:pointer}.admin-overlay{display:none}
|
||||
@media(max-width:1100px){.dj-cards{grid-template-columns:repeat(3,minmax(0,1fr))}.steps{grid-template-columns:repeat(2,1fr)}.profile-grid{grid-template-columns:minmax(0,1fr) 330px}.admin-stats{grid-template-columns:repeat(2,1fr)}.role-grid{grid-template-columns:repeat(2,1fr)}}
|
||||
@media(max-width:900px){.shell{width:min(100% - 28px,1240px)}.site-header{height:68px}.nav{height:68px}.mobile-menu-button{display:block}.nav-panel{display:none;position:absolute;top:68px;left:14px;right:14px;margin:0;padding:14px;flex-direction:column;align-items:stretch;gap:12px;background:#0e1425;border:1px solid var(--line);border-radius:14px;box-shadow:var(--shadow)}.nav-panel.open{display:flex}.navlinks,.nav-actions{align-items:stretch;flex-direction:column;gap:2px}.navlinks a,.nav-actions>a,.nav-actions .text-button{padding:11px 10px;text-align:left}.nav-actions{padding-top:8px;border-top:1px solid var(--line)}.nav-actions .button{width:100%}.hero{min-height:auto}.hero-copy{padding:74px 0}.searchbox,.filterbar{grid-template-columns:1fr 1fr}.searchbox .button,.filterbar .button{grid-column:1/-1}.dj-cards{grid-template-columns:repeat(2,minmax(0,1fr))}.split-feature{grid-template-columns:1fr;gap:36px}.profile-panel{grid-template-columns:100px 1fr}.profile-price{grid-column:1/-1;padding:18px 0 0;border-left:0;border-top:1px solid #e2e8f0;display:grid;grid-template-columns:auto auto 1fr auto;gap:8px;align-items:center}.profile-price .button{margin:0}.profile-grid{grid-template-columns:1fr}.enquiry-card{position:static}.account-shell{grid-template-columns:1fr}.account-sidebar{position:static}.account-nav{display:flex;gap:4px;overflow-x:auto}.account-nav a{white-space:nowrap}.dashboard-grid{grid-template-columns:1fr}.admin-shell{display:block}.admin-sidebar{position:fixed;left:0;top:0;width:270px;transform:translateX(-105%);transition:transform .2s ease}.admin-sidebar.open{transform:none}.admin-overlay{position:fixed;inset:0;background:rgba(11,16,32,.55);z-index:70}.admin-overlay.open{display:block}.admin-menu,.admin-close{display:inline-grid;place-items:center}.admin-topbar{padding:0 18px}.admin-page{padding:22px 18px}.admin-flash{margin:14px 18px 0}.admin-grid{grid-template-columns:1fr}.settings-grid{grid-template-columns:1fr}}
|
||||
@media(max-width:640px){.shell{width:min(100% - 22px,1240px)}.brand{font-size:21px}.hero-shade{background:linear-gradient(180deg,rgba(7,9,20,.78),rgba(7,9,20,.97))}.hero-copy{padding:58px 0}.hero h1{font-size:44px}.hero-copy>p{font-size:16px}.searchbox,.filterbar{grid-template-columns:1fr;padding:8px}.searchbox .button,.filterbar .button{grid-column:auto}.hero-proof{gap:9px 16px;font-size:11px}.section{padding:58px 0}.section-head,.directory-heading,.page-heading,.pricing-box{align-items:flex-start;flex-direction:column}.section-head .button{width:100%}.dj-cards{grid-template-columns:1fr}.card-img{aspect-ratio:16/10}.steps{grid-template-columns:1fr}.feature-list{grid-template-columns:1fr}.pricing-box{padding:28px}.pricing-box .button{width:100%}.footer-grid{grid-template-columns:1fr;gap:28px}.cookie{left:10px;right:10px;bottom:10px;flex-direction:column;align-items:stretch}.cookie-actions{display:grid;grid-template-columns:1fr 1fr}.profile-hero{height:230px}.profile-shell{width:100%}.profile-panel{margin:-34px 11px 0;padding:18px;grid-template-columns:72px 1fr;gap:14px;border-radius:17px}.avatar{width:72px;height:72px}.profile-title h1{font-size:27px}.profile-summary p{font-size:13px}.profile-price{grid-template-columns:auto 1fr}.profile-price strong{font-size:30px}.profile-price small{display:none}.profile-price .button{grid-column:1/-1}.profile-grid{padding:28px 11px 0}.directory-page{padding:44px 0 60px}.directory-heading h1{font-size:42px}.account-page{padding:36px 0 58px}.account-person{display:none}.account-sidebar{border-radius:12px}.account-stats{grid-template-columns:1fr 1fr}.account-stat:last-child{grid-column:1/-1}.panel{padding:16px}.admin-topbar .button{display:none}.admin-page{padding:18px 12px}.admin-stats{grid-template-columns:1fr 1fr;gap:10px}.admin-stat{padding:15px}.admin-stat strong{font-size:24px}.settings-list>div{grid-template-columns:1fr}.role-grid{grid-template-columns:1fr}.inline-controls{align-items:stretch;flex-direction:column}.inline-controls select,.inline-controls .admin-button{width:100%}.auth-card{padding:23px}.auth-page{padding:38px 12px}}
|
||||
|
||||
+30
-1
@@ -1 +1,30 @@
|
||||
import './bootstrap';
|
||||
import './bootstrap';
|
||||
|
||||
const menuButton = document.querySelector('[data-menu-toggle]');
|
||||
const menuPanel = document.querySelector('[data-menu-panel]');
|
||||
|
||||
menuButton?.addEventListener('click', () => {
|
||||
const open = menuPanel?.classList.toggle('open') ?? false;
|
||||
menuButton.setAttribute('aria-expanded', String(open));
|
||||
menuButton.textContent = open ? '×' : '☰';
|
||||
});
|
||||
|
||||
document.querySelectorAll('[data-menu-panel] a').forEach((link) => {
|
||||
link.addEventListener('click', () => {
|
||||
menuPanel?.classList.remove('open');
|
||||
menuButton?.setAttribute('aria-expanded', 'false');
|
||||
if (menuButton) menuButton.textContent = '☰';
|
||||
});
|
||||
});
|
||||
|
||||
const adminSidebar = document.querySelector('#adminSidebar');
|
||||
const adminOverlay = document.querySelector('[data-admin-overlay]');
|
||||
const setAdminMenu = (open) => {
|
||||
adminSidebar?.classList.toggle('open', open);
|
||||
adminOverlay?.classList.toggle('open', open);
|
||||
document.body.classList.toggle('admin-menu-open', open);
|
||||
};
|
||||
|
||||
document.querySelector('[data-admin-open]')?.addEventListener('click', () => setAdminMenu(true));
|
||||
document.querySelector('[data-admin-close]')?.addEventListener('click', () => setAdminMenu(false));
|
||||
adminOverlay?.addEventListener('click', () => setAdminMenu(false));
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
@extends('layouts.account')
|
||||
@section('title','My bookings — BeatBook')
|
||||
@section('account-content')
|
||||
<div class="page-heading"><div><div class="eyebrow">Your account</div><h1>Bookings</h1><p>Your confirmed and pending events in one place.</p></div></div>
|
||||
<div class="panel table-panel"><div class="responsive-table"><table><thead><tr><th>DJ</th><th>Event date</th><th>Total</th><th>Deposit</th><th>Payment</th><th>Status</th></tr></thead><tbody>
|
||||
@forelse($bookings as $item)<tr><td><strong>{{ $item->djProfile?->stage_name ?? 'DJ' }}</strong></td><td>{{ optional($item->event_date)->format('j M Y') }}</td><td>£{{ number_format((float)$item->total,2) }}</td><td>£{{ number_format((float)$item->deposit,2) }}</td><td>{{ $item->paid_at ? 'Paid' : 'Outstanding' }}</td><td><span class="status-pill">{{ ucfirst($item->status) }}</span></td></tr>@empty<tr><td colspan="6"><div class="empty-state">No bookings yet.</div></td></tr>@endforelse
|
||||
</tbody></table></div></div>{{ $bookings->links() }}
|
||||
@endsection
|
||||
@@ -0,0 +1,16 @@
|
||||
@extends('layouts.account')
|
||||
@section('title','Dashboard — BeatBook')
|
||||
@section('account-content')
|
||||
<div class="page-heading"><div><div class="eyebrow">Your account</div><h1>Welcome back, {{ Str::before($user->name, ' ') }}</h1><p>Manage your enquiries, bookings and account details.</p></div><a class="button" href="{{ route('djs.index') }}">Find a DJ</a></div>
|
||||
<div class="account-stats">
|
||||
@foreach($stats as $label => $value)<div class="account-stat"><span>{{ ucfirst($label) }}</span><strong>{{ $value }}</strong></div>@endforeach
|
||||
</div>
|
||||
<div class="dashboard-grid">
|
||||
<section class="panel"><div class="panel-head"><h2>Recent enquiries</h2><a href="{{ route('account.enquiries') }}">View all</a></div>
|
||||
@forelse($enquiries as $enquiry)<a class="list-row" href="{{ route('account.enquiries') }}"><div><strong>{{ $enquiry->djProfile?->stage_name ?? 'DJ' }}</strong><span>{{ $enquiry->event_type }} · {{ optional($enquiry->event_date)->format('j M Y') }}</span></div><span class="status-pill">{{ ucfirst($enquiry->status) }}</span></a>@empty<div class="empty-state">No enquiries yet. Find a DJ and send your first enquiry.</div>@endforelse
|
||||
</section>
|
||||
<section class="panel"><div class="panel-head"><h2>Bookings</h2><a href="{{ route('account.bookings') }}">View all</a></div>
|
||||
@forelse($bookings as $booking)<a class="list-row" href="{{ route('account.bookings') }}"><div><strong>{{ $booking->djProfile?->stage_name ?? 'DJ' }}</strong><span>{{ optional($booking->event_date)->format('j M Y') }} · £{{ number_format((float)$booking->total,2) }}</span></div><span class="status-pill">{{ ucfirst($booking->status) }}</span></a>@empty<div class="empty-state">You do not have any bookings yet.</div>@endforelse
|
||||
</section>
|
||||
</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,8 @@
|
||||
@extends('layouts.account')
|
||||
@section('title','My enquiries — BeatBook')
|
||||
@section('account-content')
|
||||
<div class="page-heading"><div><div class="eyebrow">Your account</div><h1>Enquiries</h1><p>Track every enquiry you have sent to a DJ.</p></div><a class="button" href="{{ route('djs.index') }}">New enquiry</a></div>
|
||||
<div class="panel table-panel"><div class="responsive-table"><table><thead><tr><th>DJ</th><th>Event</th><th>Date</th><th>Venue</th><th>Budget</th><th>Status</th></tr></thead><tbody>
|
||||
@forelse($enquiries as $item)<tr><td><strong>{{ $item->djProfile?->stage_name ?? 'DJ' }}</strong></td><td>{{ $item->event_type }}</td><td>{{ optional($item->event_date)->format('j M Y') }}</td><td>{{ $item->venue }}</td><td>{{ $item->budget ? '£'.number_format((float)$item->budget,2) : '—' }}</td><td><span class="status-pill">{{ ucfirst($item->status) }}</span></td></tr>@empty<tr><td colspan="6"><div class="empty-state">No enquiries yet.</div></td></tr>@endforelse
|
||||
</tbody></table></div></div>{{ $enquiries->links() }}
|
||||
@endsection
|
||||
@@ -0,0 +1,13 @@
|
||||
@extends('layouts.account')
|
||||
@section('title','Account details — BeatBook')
|
||||
@section('account-content')
|
||||
<div class="page-heading"><div><div class="eyebrow">Your account</div><h1>Account details</h1><p>Keep your contact information up to date.</p></div></div>
|
||||
<div class="panel form-panel"><form method="post" action="{{ route('account.profile.update') }}" class="settings-form">@csrf @method('PATCH')
|
||||
<label><span>Name</span><input name="name" value="{{ old('name',$user->name) }}" required></label>
|
||||
<label><span>Email</span><input type="email" name="email" value="{{ old('email',$user->email) }}" required></label>
|
||||
<label><span>Phone</span><input name="phone" value="{{ old('phone',$user->phone) }}"></label>
|
||||
<label class="check-line"><input type="checkbox" name="marketing_opt_in" value="1" @checked(old('marketing_opt_in',$user->marketing_opt_in))><span>Send me relevant BeatBook news and offers.</span></label>
|
||||
@if($errors->any())<div class="form-errors">@foreach($errors->all() as $error)<div>{{ $error }}</div>@endforeach</div>@endif
|
||||
<div><button class="button" type="submit">Save changes</button></div>
|
||||
</form></div>
|
||||
@endsection
|
||||
@@ -1,41 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>BeatBook Admin</title>
|
||||
@vite(['resources/css/app.css'])
|
||||
</head>
|
||||
<body>
|
||||
<div class="admin">
|
||||
<aside class="sidebar">
|
||||
<a class="brand" href="{{ route('admin.dashboard') }}"><b>◉</b> BeatBook</a>
|
||||
<p class="muted">Administration</p>
|
||||
<a href="{{ route('admin.dashboard') }}">Dashboard</a>
|
||||
@foreach([
|
||||
'users' => 'Users', 'djs' => 'DJs & Businesses', 'clients' => 'Clients',
|
||||
'bookings' => 'Bookings', 'payments' => 'Payments', 'reviews' => 'Reviews',
|
||||
'messages' => 'Messages', 'notifications' => 'Notifications', 'support' => 'Support',
|
||||
'reports' => 'Reports', 'content' => 'Content', 'roles' => 'Roles & Permissions',
|
||||
'privacy' => 'Privacy', 'settings' => 'Settings'
|
||||
] as $key => $label)
|
||||
<a href="{{ route('admin.section', $key) }}">{{ $label }}</a>
|
||||
@endforeach
|
||||
<a href="{{ route('home') }}">Back to site</a>
|
||||
</aside>
|
||||
<main class="admin-main">
|
||||
<h1>Dashboard</h1>
|
||||
<p style="color:#64748b">Marketplace overview and moderation queue.</p>
|
||||
<div class="stats">
|
||||
@foreach($stats as $key => $value)
|
||||
<div class="stat"><span>{{ ucfirst($key) }}</span><strong>{{ number_format($value) }}</strong></div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="stat" style="margin-top:22px;min-height:330px">
|
||||
<h2>Operations</h2>
|
||||
<p style="color:#64748b">Revenue charts, recent bookings, verification requests, support tickets and review moderation plug into this dashboard.</p>
|
||||
</div>
|
||||
</main>
|
||||
@extends('layouts.admin')
|
||||
@section('title','Dashboard')
|
||||
@section('page-title','Dashboard')
|
||||
@section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Marketplace control centre</div><h1>Dashboard</h1><p>Live overview of users, DJs, bookings and moderation.</p></div></div>
|
||||
<div class="admin-stats">@foreach($stats as $key=>$value)<a class="admin-stat" href="{{ $key === 'pending reviews' ? route('admin.section','reviews') : ($key === 'djs' ? route('admin.section','djs') : ($key === 'bookings' ? route('admin.section','bookings') : route('admin.section','users'))) }}"><span>{{ ucfirst($key) }}</span><strong>{{ number_format($value) }}</strong><small>Open section →</small></a>@endforeach</div>
|
||||
<div class="admin-grid">
|
||||
<section class="admin-card"><div class="panel-head"><h2>Newest users</h2><a href="{{ route('admin.section','users') }}">Manage</a></div>@forelse($recentUsers as $user)<div class="admin-list-row"><div><strong>{{ $user->name }}</strong><span>{{ $user->email }}</span></div><span>{{ $user->created_at?->diffForHumans() }}</span></div>@empty<div class="empty-state">No users yet.</div>@endforelse</section>
|
||||
<section class="admin-card"><div class="panel-head"><h2>Latest enquiries</h2><a href="{{ route('admin.section','clients') }}">Clients</a></div>@forelse($recentEnquiries as $item)<div class="admin-list-row"><div><strong>{{ $item->user?->name }}</strong><span>{{ $item->djProfile?->stage_name }} · {{ $item->event_type }}</span></div><span class="status-pill">{{ ucfirst($item->status) }}</span></div>@empty<div class="empty-state">No enquiries yet.</div>@endforelse</section>
|
||||
<section class="admin-card admin-card-wide"><div class="panel-head"><h2>Recent bookings</h2><a href="{{ route('admin.section','bookings') }}">View all</a></div><div class="responsive-table"><table><thead><tr><th>Client</th><th>DJ</th><th>Date</th><th>Total</th><th>Status</th></tr></thead><tbody>@forelse($recentBookings as $item)<tr><td>{{ $item->client?->name }}</td><td>{{ $item->djProfile?->stage_name }}</td><td>{{ optional($item->event_date)->format('j M Y') }}</td><td>£{{ number_format((float)$item->total,2) }}</td><td><span class="status-pill">{{ ucfirst($item->status) }}</span></td></tr>@empty<tr><td colspan="5">No bookings yet.</td></tr>@endforelse</tbody></table></div></section>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@endsection
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Bookings') @section('page-title','Bookings') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Events</div><h1>Bookings</h1><p>All marketplace bookings and event values.</p></div><span class="metric-chip">{{ number_format($counts['bookings']) }} bookings</span></div>
|
||||
<div class="admin-card table-card"><div class="responsive-table"><table><thead><tr><th>Client</th><th>DJ</th><th>Event date</th><th>Total</th><th>Deposit</th><th>Status</th></tr></thead><tbody>@forelse($bookings as $item)<tr><td>{{ $item->client?->name }}</td><td>{{ $item->djProfile?->stage_name }}</td><td>{{ optional($item->event_date)->format('j M Y') }}</td><td>£{{ number_format((float)$item->total,2) }}</td><td>£{{ number_format((float)$item->deposit,2) }}</td><td><span class="status-pill">{{ ucfirst($item->status) }}</span></td></tr>@empty<tr><td colspan="6">No bookings yet.</td></tr>@endforelse</tbody></table></div></div>{{ $bookings->links() }}
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Clients') @section('page-title','Clients') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Customers</div><h1>Clients</h1><p>Review client activity across enquiries and bookings.</p></div><span class="metric-chip">{{ number_format($counts['clients']) }} clients</span></div>
|
||||
<div class="admin-card table-card"><div class="responsive-table"><table><thead><tr><th>Client</th><th>Phone</th><th>Enquiries</th><th>Bookings</th><th>Joined</th></tr></thead><tbody>@forelse($clients as $client)<tr><td><strong>{{ $client->name }}</strong><small>{{ $client->email }}</small></td><td>{{ $client->phone ?: '—' }}</td><td>{{ $client->enquiries_count }}</td><td>{{ $client->bookings_count }}</td><td>{{ $client->created_at?->format('j M Y') }}</td></tr>@empty<tr><td colspan="5">No clients yet.</td></tr>@endforelse</tbody></table></div></div>{{ $clients->links() }}
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Content') @section('page-title','Content') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Website</div><h1>Content</h1><p>Public-site content and marketplace presentation.</p></div></div>
|
||||
<div class="settings-grid"><a class="admin-card action-card" href="{{ route('home') }}"><h2>Homepage</h2><p>Review hero, featured DJs, how it works and DJ proposition.</p><span>Open page →</span></a><a class="admin-card action-card" href="{{ route('djs.index') }}"><h2>DJ directory</h2><p>Review public listings, filtering and profile presentation.</p><span>Open directory →</span></a><a class="admin-card action-card" href="{{ route('privacy') }}"><h2>Legal content</h2><p>Review privacy, cookie and terms content.</p><span>Open privacy →</span></a></div>
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','DJs & businesses') @section('page-title','DJs & businesses') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Marketplace supply</div><h1>DJs & businesses</h1><p>Control visibility and featured placement.</p></div><span class="metric-chip">{{ number_format($counts['djs']) }} profiles</span></div>
|
||||
<div class="admin-card table-card"><div class="responsive-table"><table><thead><tr><th>DJ</th><th>Owner</th><th>City</th><th>Price</th><th>Published</th><th>Featured</th></tr></thead><tbody>@forelse($djs as $dj)<tr><td><strong>{{ $dj->stage_name }}</strong><small>{{ $dj->business?->name ?: 'Independent' }}</small></td><td>{{ $dj->user?->email }}</td><td>{{ $dj->city }}</td><td>{{ $dj->price_from ? '£'.number_format((float)$dj->price_from) : '—' }}</td><td><form method="post" action="{{ route('admin.djs.published',$dj) }}">@csrf @method('PATCH')<button class="toggle-button {{ $dj->is_published ? 'on' : '' }}" type="submit">{{ $dj->is_published ? 'Published' : 'Hidden' }}</button></form></td><td><form method="post" action="{{ route('admin.djs.featured',$dj) }}">@csrf @method('PATCH')<button class="toggle-button {{ $dj->is_featured ? 'on' : '' }}" type="submit">{{ $dj->is_featured ? 'Featured' : 'Standard' }}</button></form></td></tr>@empty<tr><td colspan="6">No DJ profiles yet.</td></tr>@endforelse</tbody></table></div></div>{{ $djs->links() }}
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Messages') @section('page-title','Messages') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Communication</div><h1>Messages</h1><p>Marketplace messaging will appear here once conversations are created.</p></div></div>
|
||||
<div class="admin-card"><div class="feature-empty"><div class="feature-icon">✉</div><h2>No conversations yet</h2><p>Enquiry messaging can be added here without exposing private contact details between clients and DJs.</p><a class="admin-button" href="{{ route('admin.section','clients') }}">View clients</a></div></div>
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Notifications') @section('page-title','Notifications') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Delivery</div><h1>Notifications</h1><p>System alerts and delivery health.</p></div></div>
|
||||
<div class="settings-grid"><div class="admin-card"><h2>Notification channels</h2><div class="settings-list"><div><strong>Email</strong><span>Laravel mail channel</span><span class="status-pill">Configured</span></div><div><strong>Database</strong><span>In-app notifications</span><span class="status-pill">Ready</span></div></div></div><div class="admin-card"><h2>Recommended events</h2><p class="admin-muted">Booking confirmation, new enquiry, review request, payment receipt and support replies can be delivered from this area.</p></div></div>
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Payments') @section('page-title','Payments') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Finance</div><h1>Payments</h1><p>Payment state and booking value overview.</p></div></div>
|
||||
<div class="admin-card table-card"><div class="responsive-table"><table><thead><tr><th>Booking</th><th>Client</th><th>DJ</th><th>Total</th><th>Deposit</th><th>Payment</th></tr></thead><tbody>@forelse($bookings as $item)<tr><td>{{ Str::limit($item->id,10,'…') }}</td><td>{{ $item->client?->name }}</td><td>{{ $item->djProfile?->stage_name }}</td><td>£{{ number_format((float)$item->total,2) }}</td><td>£{{ number_format((float)$item->deposit,2) }}</td><td><span class="status-pill">{{ $item->paid_at ? 'Paid' : 'Outstanding' }}</span></td></tr>@empty<tr><td colspan="6">No payment records yet.</td></tr>@endforelse</tbody></table></div></div>{{ $bookings->links() }}
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Privacy') @section('page-title','Privacy') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Compliance</div><h1>Privacy</h1><p>Quick access to the public legal policies and privacy controls.</p></div></div>
|
||||
<div class="settings-grid"><a class="admin-card action-card" href="{{ route('privacy') }}"><h2>Privacy policy</h2><p>Review the current public privacy policy.</p><span>Open policy →</span></a><a class="admin-card action-card" href="{{ route('cookies') }}"><h2>Cookie policy</h2><p>Review necessary, analytics and marketing cookie information.</p><span>Open policy →</span></a><a class="admin-card action-card" href="{{ route('terms') }}"><h2>Terms</h2><p>Review marketplace terms shown to users.</p><span>Open terms →</span></a></div>
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Reports') @section('page-title','Reports') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Performance</div><h1>Reports</h1><p>Marketplace totals calculated from live BeatBook data.</p></div></div>
|
||||
<div class="admin-stats"><div class="admin-stat"><span>Booking value</span><strong>£{{ number_format((float)$report['booking_value'],2) }}</strong></div><div class="admin-stat"><span>Deposits</span><strong>£{{ number_format((float)$report['deposits'],2) }}</strong></div><div class="admin-stat"><span>Published DJs</span><strong>{{ $report['published_djs'] }}</strong></div><div class="admin-stat"><span>Pending reviews</span><strong>{{ $report['pending_reviews'] }}</strong></div></div>
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Reviews') @section('page-title','Reviews') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Trust & safety</div><h1>Reviews</h1><p>Moderate feedback before it appears publicly.</p></div><span class="metric-chip">{{ number_format($counts['reviews']) }} reviews</span></div>
|
||||
<div class="admin-card table-card"><div class="responsive-table"><table><thead><tr><th>Reviewer</th><th>DJ</th><th>Rating</th><th>Review</th><th>Status</th><th>Moderate</th></tr></thead><tbody>@forelse($reviews as $review)<tr><td>{{ $review->user?->name }}</td><td>{{ $review->djProfile?->stage_name }}</td><td>★ {{ $review->rating }}/5</td><td><strong>{{ $review->title ?: 'Review' }}</strong><small>{{ Str::limit($review->body,80) }}</small></td><td><span class="status-pill">{{ ucfirst($review->status) }}</span></td><td><form class="inline-controls" method="post" action="{{ route('admin.reviews.status',$review) }}">@csrf @method('PATCH')<select name="status"><option value="pending" @selected($review->status==='pending')>Pending</option><option value="published" @selected($review->status==='published')>Published</option><option value="rejected" @selected($review->status==='rejected')>Rejected</option></select><button class="admin-button">Save</button></form></td></tr>@empty<tr><td colspan="6">No reviews yet.</td></tr>@endforelse</tbody></table></div></div>{{ $reviews->links() }}
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Roles & permissions') @section('page-title','Roles & permissions') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Access control</div><h1>Roles & permissions</h1><p>Roles currently available to BeatBook accounts.</p></div></div>
|
||||
<div class="role-grid">@foreach($roles as $role)<div class="admin-card"><span class="role-badge">{{ $role->name }}</span><strong class="role-count">{{ $role->users_count }}</strong><p>{{ Str::plural('user',$role->users_count) }}</p></div>@endforeach</div>
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Settings') @section('page-title','Settings') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Application</div><h1>Settings</h1><p>Operational controls for the BeatBook installation.</p></div></div>
|
||||
<div class="settings-grid"><div class="admin-card"><h2>Environment</h2><div class="settings-list"><div><strong>Application</strong><span>{{ config('app.name') }}</span></div><div><strong>Environment</strong><span>{{ app()->environment() }}</span></div><div><strong>URL</strong><span>{{ config('app.url') }}</span></div></div></div><div class="admin-card"><h2>Maintenance</h2><p class="admin-muted">Clear application cache after configuration or content changes.</p><form method="post" action="{{ route('admin.settings.clear-cache') }}">@csrf<button class="admin-button" type="submit">Clear application cache</button></form></div></div>
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Support') @section('page-title','Support') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">Customer care</div><h1>Support</h1><p>Central area for customer and DJ support cases.</p></div></div>
|
||||
<div class="admin-card"><div class="feature-empty"><div class="feature-icon">?</div><h2>No open support cases</h2><p>The support queue is ready for a ticket model and inbound support form when you enable that workflow.</p></div></div>
|
||||
@endsection
|
||||
@@ -0,0 +1,4 @@
|
||||
@extends('layouts.admin') @section('title','Users') @section('page-title','Users') @section('content')
|
||||
<div class="page-heading admin-heading"><div><div class="eyebrow">People</div><h1>Users</h1><p>Manage accounts and assign marketplace roles.</p></div><span class="metric-chip">{{ number_format($counts['users']) }} users</span></div>
|
||||
<div class="admin-card table-card"><div class="responsive-table"><table><thead><tr><th>User</th><th>Role</th><th>Joined</th><th>Change role</th></tr></thead><tbody>@foreach($users as $user)<tr><td><strong>{{ $user->name }}</strong><small>{{ $user->email }}</small></td><td>{{ $user->getRoleNames()->join(', ') ?: 'No role' }}</td><td>{{ $user->created_at?->format('j M Y') }}</td><td><form class="inline-controls" method="post" action="{{ route('admin.users.role',$user) }}">@csrf @method('PATCH')<select name="role">@foreach(['client','dj','support','moderator','admin','super-admin'] as $role)<option value="{{ $role }}" @selected($user->hasRole($role))>{{ ucfirst($role) }}</option>@endforeach</select><button class="admin-button" type="submit">Save</button></form></td></tr>@endforeach</tbody></table></div></div>{{ $users->links() }}
|
||||
@endsection
|
||||
@@ -1 +1 @@
|
||||
<article class="card"><div class="card-img" style="background-image:url('{{ $dj->profile_photo ?: 'https://images.unsplash.com/photo-1571266028243-d220c9c3b2d2?auto=format&fit=crop&w=700&q=80' }}')"></div><div class="card-body"><h3>{{ $dj->stage_name }} @if($dj->verified_at) ✓ @endif</h3><div class="stars">★★★★★ <span class="muted">{{ number_format($dj->average_rating,1) }} ({{ $dj->review_count }})</span></div><p class="muted">{{ $dj->city }} · {{ $dj->headline }}</p><div class="price">From £{{ number_format($dj->price_from,0) }}</div><a class="button" href="{{ route('djs.show',$dj) }}">View profile</a></div></article>
|
||||
<article class="card dj-card"><a class="card-img" href="{{ route('djs.show',$dj) }}" style="background-image:url('{{ $dj->profile_photo ?: 'https://images.unsplash.com/photo-1571266028243-d220c9c3b2d2?auto=format&fit=crop&w=900&q=82' }}')"></a><div class="card-body"><div class="card-title-line"><h3>{{ $dj->stage_name }}</h3>@if($dj->verified_at)<span class="verified" title="Verified">✓</span>@endif</div><div class="stars">★★★★★ <span>{{ number_format($dj->average_rating,1) }} ({{ $dj->review_count }})</span></div><p>{{ $dj->city }}@if($dj->headline) · {{ Str::limit($dj->headline,48) }}@endif</p><div class="card-foot"><strong>{{ $dj->price_from ? 'From £'.number_format($dj->price_from,0) : 'Ask for a quote' }}</strong><a href="{{ route('djs.show',$dj) }}">View profile →</a></div></div></article>
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
@extends('layouts.app') @section('title','Find DJs — BeatBook') @section('content')<main class="section"><div class="shell"><div class="eyebrow">Discover</div><h1 style="font-size:48px">Find your DJ</h1><form class="searchbox" style="margin:25px 0 35px"><input name="location" value="{{ request('location') }}" placeholder="Town or city"><input name="max_price" type="number" value="{{ request('max_price') }}" placeholder="Maximum price"><select><option>Highest rated</option></select><button class="button">Filter</button></form><div class="cards">@foreach($djs as $dj) @include('djs._card') @endforeach</div><div style="margin-top:30px">{{ $djs->links() }}</div></div></main>@endsection
|
||||
@extends('layouts.app')
|
||||
@section('title','Find DJs — BeatBook')
|
||||
@section('content')
|
||||
<main class="directory-page"><div class="shell"><div class="directory-heading"><div><div class="eyebrow">Discover</div><h1>Find your DJ</h1><p>Search trusted DJs by location and budget.</p></div><span class="results-count">{{ $djs->total() }} {{ Str::plural('DJ',$djs->total()) }}</span></div>
|
||||
<form class="filterbar" method="get"><label><span>Location</span><input name="location" value="{{ request('location') }}" placeholder="Town or city"></label><label><span>Maximum price</span><input name="max_price" type="number" min="0" value="{{ request('max_price') }}" placeholder="Any budget"></label><label><span>Sort</span><select name="sort"><option value="rating" @selected(request('sort')==='rating')>Highest rated</option><option value="price_low" @selected(request('sort')==='price_low')>Price: low to high</option><option value="price_high" @selected(request('sort')==='price_high')>Price: high to low</option></select></label><button class="button" type="submit">Apply filters</button></form>
|
||||
<div class="cards dj-cards directory-cards">@forelse($djs as $dj) @include('djs._card') @empty <div class="empty-state directory-empty"><h2>No DJs matched your search</h2><p>Try removing a filter or searching a nearby town.</p><a class="button ghost" href="{{ route('djs.index') }}">Clear filters</a></div>@endforelse</div><div class="pagination-wrap">{{ $djs->withQueryString()->links() }}</div></div></main>
|
||||
@endsection
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
@extends('layouts.app') @section('title',$dj->stage_name.' — BeatBook') @section('content')<div class="profile-hero" style="background-image:linear-gradient(#0002,#0008),url('{{ $dj->cover_photo ?: $dj->profile_photo }}')"></div><main class="shell"><section class="profile-panel"><img class="avatar" src="{{ $dj->profile_photo }}" alt="{{ $dj->stage_name }}"><div><h1 style="margin:0">{{ $dj->stage_name }} @if($dj->verified_at)<span style="color:#2563eb">✓</span>@endif</h1><div class="stars">★★★★★ <span style="color:#64748b">{{ $dj->average_rating }} · {{ $dj->review_count }} reviews</span></div><p>{{ $dj->headline }}</p><div class="chips">@foreach($dj->genres as $genre)<span class="chip">{{ $genre->name }}</span>@endforeach</div></div><aside><span>From</span><div style="font-size:34px;font-weight:900">£{{ number_format($dj->price_from,0) }}</div><span>per event</span><br><br><a class="button" href="#enquire">Request a quote</a></aside></section><section class="section" style="padding-top:15px"><div style="display:grid;grid-template-columns:2fr 1fr;gap:35px"><div><h2>About {{ $dj->stage_name }}</h2><p class="muted" style="font-size:17px;line-height:1.8">{{ $dj->bio }}</p><h2>Reviews</h2>@foreach($dj->reviews as $review)<div class="card" style="padding:20px;margin-bottom:12px"><div class="stars">{{ str_repeat('★',$review->rating) }}</div><h3>{{ $review->title }}</h3><p>{{ $review->body }}</p></div>@endforeach</div><aside id="enquire" class="card" style="padding:22px;height:max-content"><h2>Check availability</h2>@auth<form method="post" action="{{ route('enquiries.store',$dj) }}">@csrf<input name="event_type" placeholder="Event type" required style="width:100%;padding:12px;margin:5px 0"><input name="event_date" type="date" required style="width:100%;padding:12px;margin:5px 0"><input name="venue" placeholder="Venue / town" required style="width:100%;padding:12px;margin:5px 0"><input name="budget" type="number" placeholder="Budget £" style="width:100%;padding:12px;margin:5px 0"><textarea name="message" required placeholder="Tell the DJ about your event" style="width:100%;min-height:130px;padding:12px;margin:5px 0"></textarea><button class="button">Send enquiry</button></form>@else<p class="muted">Sign in to send a secure enquiry.</p><a class="button" href="{{ route('login') }}">Sign in</a>@endauth</aside></div></section></main>@endsection
|
||||
@extends('layouts.app')
|
||||
@section('title',$dj->stage_name.' — BeatBook')
|
||||
@section('content')
|
||||
<div class="profile-hero" style="background-image:linear-gradient(180deg,rgba(7,10,25,.1),rgba(7,10,25,.78)),url('{{ $dj->cover_photo ?: $dj->profile_photo }}')"></div>
|
||||
<main class="shell profile-shell"><section class="profile-panel"><img class="avatar" src="{{ $dj->profile_photo }}" alt="{{ $dj->stage_name }}"><div class="profile-summary"><div class="profile-title"><h1>{{ $dj->stage_name }}</h1>@if($dj->verified_at)<span class="verified large">✓</span>@endif</div><div class="stars">★★★★★ <span>{{ $dj->average_rating }} · {{ $dj->review_count }} reviews</span></div><p>{{ $dj->headline }}</p><div class="chips">@foreach($dj->genres as $genre)<span class="chip">{{ $genre->name }}</span>@endforeach</div></div><aside class="profile-price"><span>From</span><strong>£{{ number_format($dj->price_from,0) }}</strong><small>per event</small><a class="button" href="#enquire">Request a quote</a></aside></section>
|
||||
<div class="profile-grid"><section class="profile-main"><div class="profile-section"><h2>About {{ $dj->stage_name }}</h2><p class="profile-bio">{{ $dj->bio }}</p></div><div class="profile-section"><div class="panel-head"><h2>Reviews</h2><span>{{ $dj->review_count }} total</span></div>@forelse($dj->reviews->where('status','published') as $review)<article class="review-card"><div class="stars">{{ str_repeat('★',$review->rating) }}</div><h3>{{ $review->title }}</h3><p>{{ $review->body }}</p></article>@empty<div class="empty-state">No published reviews yet.</div>@endforelse</div></section>
|
||||
<aside id="enquire" class="enquiry-card"><h2>Check availability</h2><p>Tell {{ $dj->stage_name }} about your event.</p>@auth<form class="enquiry-form" method="post" action="{{ route('enquiries.store',$dj) }}">@csrf<label><span>Event type</span><input name="event_type" placeholder="Wedding, party…" required></label><label><span>Event date</span><input name="event_date" type="date" required></label><label><span>Venue / town</span><input name="venue" required></label><label><span>Budget</span><input name="budget" type="number" placeholder="£"></label><label><span>Event details</span><textarea name="message" required placeholder="Guests, timings, music, venue details…"></textarea></label><button class="button full" type="submit">Send enquiry</button></form>@else<p class="muted">Sign in to send a secure enquiry.</p><a class="button full" href="{{ route('login') }}">Sign in to enquire</a>@endauth</aside></div></main>
|
||||
@endsection
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
@extends('layouts.app') @section('content')<section class="hero"><div class="shell hero-copy"><div class="eyebrow">Music creates memories</div><h1>Find your <span>perfect DJ</span></h1><p>Discover trusted DJs for weddings, parties, corporate events and clubs. Compare profiles, reviews and prices, then enquire with confidence.</p><form class="searchbox" action="{{ route('djs.index') }}"><input name="location" placeholder="Town or postcode"><select name="event_type"><option value="">Event type</option><option>Wedding</option><option>Party</option><option>Corporate</option><option>Club</option></select><input type="date" name="date"><button class="button">Search DJs</button></form></div></section><section class="section"><div class="shell"><div class="section-head"><div><div class="eyebrow">Top talent</div><h2>Featured DJs</h2></div><a class="button ghost" href="{{ route('djs.index') }}">View all DJs</a></div><div class="cards">@forelse($featured as $dj) @include('djs._card',['dj'=>$dj]) @empty @foreach([['DJ Luna','London',350,'photo-1516280440614-37939bbacd81'],['DJ Maverick','Manchester',400,'photo-1571266028243-d220c9c3b2d2'],['DJ Rhythm','Birmingham',300,'photo-1524368535928-5b5e00ddc76b'],['DJ Serenity','Leeds',320,'photo-1506157786151-b8491531f063']] as $d)<article class="card"><div class="card-img" style="background-image:url('https://images.unsplash.com/{{ $d[3] }}?auto=format&fit=crop&w=700&q=80')"></div><div class="card-body"><h3>{{ $d[0] }}</h3><div class="stars">★★★★★ <span class="muted">4.9</span></div><p class="muted">{{ $d[1] }} · Weddings · Parties</p><div class="price">From £{{ $d[2] }}</div><a class="button" href="{{ route('djs.index') }}">View profile</a></div></article>@endforeach @endforelse</div></div></section><section id="how" class="section" style="background:#0d1228"><div class="shell"><div class="eyebrow">Simple & secure</div><h2>From search to dance floor</h2><div class="cards" style="margin-top:30px">@foreach(['Search'=>'Find DJs by location, date, event and budget.','Compare'=>'Review portfolios, pricing and verified feedback.','Enquire'=>'Send your event details without exposing private contact data.','Book & review'=>'Confirm securely and review after the event.'] as $a=>$b)<div class="card"><div class="card-body"><h3>{{ $a }}</h3><p class="muted">{{ $b }}</p></div></div>@endforeach</div></div></section><section id="for-djs" class="section"><div class="shell"><div class="section-head"><div><div class="eyebrow">For professionals</div><h2>Grow your DJ business</h2></div></div><div class="cards"><div class="card"><div class="card-body"><h3>Professional profile</h3><p class="muted">Show your sound, experience, service area and pricing in one trusted profile.</p></div></div><div class="card"><div class="card-body"><h3>Qualified enquiries</h3><p class="muted">Receive structured event details so you can quote quickly and accurately.</p></div></div><div class="card"><div class="card-body"><h3>Verified reviews</h3><p class="muted">Build reputation from completed BeatBook bookings.</p></div></div><div class="card"><div class="card-body"><h3>Business tools</h3><p class="muted">Manage bookings, payments and customer communication from your dashboard.</p></div></div></div></div></section><section id="pricing" class="section" style="background:#0d1228"><div class="shell"><div class="eyebrow">Straightforward pricing</div><h2>Built for clients and DJs</h2><p class="muted" style="max-width:720px">Browsing and creating a client account is free. DJ subscription and payment options can be configured from the BeatBook billing area as the marketplace launches.</p></div></section>@endsection
|
||||
@extends('layouts.app')
|
||||
@section('content')
|
||||
<section class="hero"><div class="hero-shade"></div><div class="shell hero-layout"><div class="hero-copy"><div class="eyebrow">Music creates memories</div><h1>Find the DJ that <span>fits your night.</span></h1><p>Discover trusted professionals for weddings, parties, corporate events and clubs. Compare profiles, reviews and prices, then enquire directly.</p><form class="searchbox" action="{{ route('djs.index') }}"><label><span>Where?</span><input name="location" placeholder="Town or postcode"></label><label><span>Event</span><select name="event_type"><option value="">Any event</option><option>Wedding</option><option>Party</option><option>Corporate</option><option>Club</option></select></label><label><span>Date</span><input type="date" name="date"></label><button class="button" type="submit">Search DJs</button></form><div class="hero-proof"><span>✓ Verified profiles</span><span>✓ Genuine reviews</span><span>✓ Secure enquiries</span></div></div></div></section>
|
||||
<section class="section"><div class="shell"><div class="section-head"><div><div class="eyebrow">Top talent</div><h2>Featured DJs</h2><p>Standout professionals ready for your next event.</p></div><a class="button ghost" href="{{ route('djs.index') }}">Browse all DJs</a></div><div class="cards dj-cards">@forelse($featured as $dj) @include('djs._card',['dj'=>$dj]) @empty @foreach([['DJ Luna','London',350,'photo-1516280440614-37939bbacd81'],['DJ Maverick','Manchester',400,'photo-1571266028243-d220c9c3b2d2'],['DJ Rhythm','Birmingham',300,'photo-1524368535928-5b5e00ddc76b'],['DJ Serenity','Leeds',320,'photo-1506157786151-b8491531f063']] as $d)<article class="card dj-card"><div class="card-img" style="background-image:url('https://images.unsplash.com/{{ $d[3] }}?auto=format&fit=crop&w=900&q=82')"></div><div class="card-body"><div class="card-title-line"><h3>{{ $d[0] }}</h3><span class="verified">✓</span></div><div class="stars">★★★★★ <span>4.9</span></div><p>{{ $d[1] }} · Weddings · Parties</p><div class="card-foot"><strong>From £{{ $d[2] }}</strong><a href="{{ route('djs.index') }}">View profile →</a></div></div></article>@endforeach @endforelse</div></div></section>
|
||||
<section id="how" class="section section-alt"><div class="shell"><div class="section-intro"><div class="eyebrow">Simple & secure</div><h2>From search to dance floor</h2><p>BeatBook keeps finding and booking entertainment straightforward.</p></div><div class="steps">@foreach([['01','Search','Find DJs by location, event and budget.'],['02','Compare','See experience, pricing and verified feedback.'],['03','Enquire','Share your event details securely.'],['04','Book','Confirm your event and review afterwards.']] as $step)<div class="step-card"><span>{{ $step[0] }}</span><h3>{{ $step[1] }}</h3><p>{{ $step[2] }}</p></div>@endforeach</div></div></section>
|
||||
<section id="for-djs" class="section"><div class="shell split-feature"><div><div class="eyebrow">For professionals</div><h2>Turn more enquiries into bookings.</h2><p class="lead">Build a trusted profile, receive structured leads and manage your work from one place.</p><a class="button" href="{{ route('register') }}">Join as a DJ</a></div><div class="feature-list"><div><strong>Professional presence</strong><span>Show your music, experience, service area and pricing.</span></div><div><strong>Better enquiries</strong><span>Get the event details you need before you quote.</span></div><div><strong>Reputation</strong><span>Build trust with reviews from completed bookings.</span></div><div><strong>One dashboard</strong><span>Keep enquiries, bookings and account details together.</span></div></div></div></section>
|
||||
<section id="pricing" class="section pricing-section"><div class="shell pricing-box"><div><div class="eyebrow">Straightforward pricing</div><h2>Free for clients. Built to grow with DJs.</h2><p>Clients can browse and enquire without a subscription. DJ plans and payment services can be introduced as the marketplace grows.</p></div><a class="button ghost" href="{{ route('register') }}">Create an account</a></div></section>
|
||||
@endsection
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
@extends('layouts.app')
|
||||
@section('content')
|
||||
<main class="account-page">
|
||||
<div class="shell account-shell">
|
||||
<aside class="account-sidebar">
|
||||
<div class="account-person">
|
||||
<div class="account-avatar">{{ strtoupper(substr(auth()->user()->name,0,1)) }}</div>
|
||||
<div><strong>{{ auth()->user()->name }}</strong><span>{{ auth()->user()->email }}</span></div>
|
||||
</div>
|
||||
<nav class="account-nav">
|
||||
<a class="{{ request()->routeIs('dashboard') ? 'active' : '' }}" href="{{ route('dashboard') }}">Overview</a>
|
||||
<a class="{{ request()->routeIs('account.enquiries') ? 'active' : '' }}" href="{{ route('account.enquiries') }}">Enquiries</a>
|
||||
<a class="{{ request()->routeIs('account.bookings') ? 'active' : '' }}" href="{{ route('account.bookings') }}">Bookings</a>
|
||||
<a class="{{ request()->routeIs('account.profile*') ? 'active' : '' }}" href="{{ route('account.profile') }}">Account details</a>
|
||||
@if(auth()->user()->hasAnyRole(['admin','super-admin']))
|
||||
<a href="{{ route('admin.dashboard') }}">Administration</a>
|
||||
@endif
|
||||
</nav>
|
||||
</aside>
|
||||
<section class="account-content">@yield('account-content')</section>
|
||||
</div>
|
||||
</main>
|
||||
@endsection
|
||||
@@ -0,0 +1,47 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<title>@yield('title', 'Administration') — BeatBook</title>
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
</head>
|
||||
<body class="admin-body">
|
||||
<div class="admin-shell">
|
||||
<aside class="admin-sidebar" id="adminSidebar">
|
||||
<div class="admin-sidebar-head">
|
||||
<a class="brand" href="{{ route('admin.dashboard') }}"><b>◉</b> BeatBook</a>
|
||||
<button class="icon-button admin-close" type="button" data-admin-close aria-label="Close menu">×</button>
|
||||
</div>
|
||||
<div class="admin-kicker">Administration</div>
|
||||
<nav class="admin-nav">
|
||||
<a class="{{ request()->routeIs('admin.dashboard') ? 'active' : '' }}" href="{{ route('admin.dashboard') }}">Overview</a>
|
||||
@foreach([
|
||||
'users' => 'Users', 'djs' => 'DJs & businesses', 'clients' => 'Clients', 'bookings' => 'Bookings',
|
||||
'payments' => 'Payments', 'reviews' => 'Reviews', 'messages' => 'Messages', 'notifications' => 'Notifications',
|
||||
'support' => 'Support', 'reports' => 'Reports', 'content' => 'Content', 'roles' => 'Roles & permissions',
|
||||
'privacy' => 'Privacy', 'settings' => 'Settings'
|
||||
] as $key => $label)
|
||||
<a class="{{ request()->is('admin/'.$key) ? 'active' : '' }}" href="{{ route('admin.section', $key) }}">{{ $label }}</a>
|
||||
@endforeach
|
||||
</nav>
|
||||
<div class="admin-sidebar-foot">
|
||||
<a href="{{ route('home') }}">View public site</a>
|
||||
<a href="{{ route('dashboard') }}">My account</a>
|
||||
<form method="post" action="{{ route('logout') }}">@csrf<button type="submit">Sign out</button></form>
|
||||
</div>
|
||||
</aside>
|
||||
<div class="admin-overlay" data-admin-overlay></div>
|
||||
<main class="admin-content">
|
||||
<header class="admin-topbar">
|
||||
<button class="icon-button admin-menu" type="button" data-admin-open aria-label="Open menu">☰</button>
|
||||
<div><strong>@yield('page-title', 'Administration')</strong><span>{{ auth()->user()->name }}</span></div>
|
||||
<a class="button small" href="{{ route('home') }}">Public site</a>
|
||||
</header>
|
||||
@if(session('success'))<div class="admin-flash">{{ session('success') }}</div>@endif
|
||||
<div class="admin-page">@yield('content')</div>
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2,69 +2,45 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<meta name="description" content="Find and book outstanding DJs for weddings, parties, clubs and corporate events.">
|
||||
<title>@yield('title', 'BeatBook — Find Your Perfect DJ')</title>
|
||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<header class="site-header">
|
||||
<div class="shell nav">
|
||||
<a class="brand" href="{{ route('home') }}"><b>◉</b> BeatBook</a>
|
||||
<nav class="navlinks">
|
||||
<a href="{{ route('djs.index') }}">Find a DJ</a>
|
||||
<a href="{{ route('home') }}#how">How it works</a>
|
||||
<a href="{{ route('home') }}#for-djs">For DJs</a>
|
||||
<a href="{{ route('home') }}#pricing">Pricing</a>
|
||||
</nav>
|
||||
<div class="nav-actions">
|
||||
@auth
|
||||
@if(auth()->user()->hasAnyRole(['admin', 'super-admin']))
|
||||
<a class="button ghost" href="{{ route('admin.dashboard') }}">Admin</a>
|
||||
@endif
|
||||
<a class="button ghost" href="{{ route('dashboard') }}">Dashboard</a>
|
||||
<form method="post" action="{{ route('logout') }}" class="inline-form">
|
||||
@csrf
|
||||
<button class="button" type="submit">Sign out</button>
|
||||
</form>
|
||||
@else
|
||||
<a class="button ghost" href="{{ route('login') }}">Sign in</a>
|
||||
<a class="button" href="{{ route('register') }}">Join</a>
|
||||
@endauth
|
||||
<button class="mobile-menu-button" type="button" data-menu-toggle aria-label="Open navigation" aria-expanded="false">☰</button>
|
||||
<div class="nav-panel" data-menu-panel>
|
||||
<nav class="navlinks">
|
||||
<a href="{{ route('djs.index') }}">Find a DJ</a>
|
||||
<a href="{{ route('home') }}#how">How it works</a>
|
||||
<a href="{{ route('home') }}#for-djs">For DJs</a>
|
||||
<a href="{{ route('home') }}#pricing">Pricing</a>
|
||||
</nav>
|
||||
<div class="nav-actions">
|
||||
@auth
|
||||
<a class="nav-account-link" href="{{ route('dashboard') }}"><span class="mini-avatar">{{ strtoupper(substr(auth()->user()->name,0,1)) }}</span><span>My account</span></a>
|
||||
@if(auth()->user()->hasAnyRole(['admin', 'super-admin']))<a class="button ghost small" href="{{ route('admin.dashboard') }}">Admin</a>@endif
|
||||
<form method="post" action="{{ route('logout') }}" class="inline-form">@csrf<button class="text-button" type="submit">Sign out</button></form>
|
||||
@else
|
||||
<a class="text-button" href="{{ route('login') }}">Sign in</a>
|
||||
<a class="button small" href="{{ route('register') }}">Join BeatBook</a>
|
||||
@endauth
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@if(session('success'))
|
||||
<div class="shell flash success">{{ session('success') }}</div>
|
||||
@endif
|
||||
@if(session('status'))
|
||||
<div class="shell flash success">{{ session('status') }}</div>
|
||||
@endif
|
||||
|
||||
@if(session('success'))<div class="shell flash success">{{ session('success') }}</div>@endif
|
||||
@if(session('status'))<div class="shell flash success">{{ session('status') }}</div>@endif
|
||||
@yield('content')
|
||||
|
||||
<footer class="section footer">
|
||||
<div class="shell">
|
||||
<b class="brand">BeatBook</b>
|
||||
<p class="muted">DJs for every moment. Secure enquiries, bookings and verified reviews.</p>
|
||||
<p>
|
||||
<a href="{{ route('privacy') }}" class="muted">Privacy</a> ·
|
||||
<a href="{{ route('cookies') }}" class="muted">Cookies</a> ·
|
||||
<a href="{{ route('terms') }}" class="muted">Terms</a>
|
||||
</p>
|
||||
</div>
|
||||
<footer class="site-footer">
|
||||
<div class="shell footer-grid"><div><a class="brand" href="{{ route('home') }}"><b>◉</b> BeatBook</a><p>DJs for every moment. Search, compare and book with confidence.</p></div><div><strong>Discover</strong><a href="{{ route('djs.index') }}">Find a DJ</a><a href="{{ route('home') }}#how">How it works</a><a href="{{ route('home') }}#for-djs">For DJs</a></div><div><strong>Legal</strong><a href="{{ route('privacy') }}">Privacy</a><a href="{{ route('cookies') }}">Cookies</a><a href="{{ route('terms') }}">Terms</a></div></div>
|
||||
<div class="shell footer-bottom">© {{ date('Y') }} BeatBook. All rights reserved.</div>
|
||||
</footer>
|
||||
|
||||
<div class="cookie" id="cookie">
|
||||
<strong>Your privacy matters</strong>
|
||||
<p>We use necessary cookies to run BeatBook. Analytics and marketing remain off until you choose them.</p>
|
||||
<button class="button" type="button" onclick="localStorage.setItem('cookieChoice','necessary');document.getElementById('cookie').remove()">Necessary only</button>
|
||||
<button class="button ghost cookie-secondary" type="button" onclick="localStorage.setItem('cookieChoice','all');document.getElementById('cookie').remove()">Accept all</button>
|
||||
</div>
|
||||
<script>
|
||||
if (localStorage.getItem('cookieChoice')) document.getElementById('cookie')?.remove();
|
||||
</script>
|
||||
<div class="cookie" id="cookie"><div><strong>Your privacy matters</strong><p>Necessary cookies keep BeatBook working. Optional analytics and marketing stay off unless you accept them.</p></div><div class="cookie-actions"><button class="button small" type="button" onclick="localStorage.setItem('cookieChoice','necessary');document.getElementById('cookie').remove()">Necessary only</button><button class="button ghost small" type="button" onclick="localStorage.setItem('cookieChoice','all');document.getElementById('cookie').remove()">Accept all</button></div></div>
|
||||
<script>if(localStorage.getItem('cookieChoice')) document.getElementById('cookie')?.remove();</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user