Skip to content

Commit 626357a

Browse files
authored
Merge pull request #11 from CodeBoxxTechSchool/ml/ventures-functions
Ml/ventures functions
2 parents c9062c0 + 17d0538 commit 626357a

4 files changed

Lines changed: 115 additions & 77 deletions

File tree

src/pages/Home.jsx

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Button, Badge, Form, Offcanvas } from 'react-bootstrap';
44
import { TopBar, Footer } from '../components/Chrome';
55
import Avatar from '../components/Avatar';
66
import Logo from '../components/Logo';
7-
import { useSanityTeam, useSanityLogos } from '../lib/sanity';
7+
import { useSanityTeam, useSanityLogos, useSanityPosts, sanityImageUrl } from '../lib/sanity';
88
import { useIntakes } from '../lib/intakes';
99
import '../lib/image-slot.js';
1010

@@ -1522,13 +1522,12 @@ function WSJTeaser() {
15221522
return (
15231523
<section className="band-dark">
15241524
<div className="wrap band-dark-inner">
1525-
<image-slot
1525+
<img
15261526
id="wsj-logo"
1527-
shape="rect"
1528-
fit="contain"
1529-
placeholder="Wall Street Journal logo"
1530-
style={{ width: 320, height: 88, '--slot-frame-bg': 'transparent', color: '#fff' }}
1531-
></image-slot>
1527+
alt="Wall Street Journal logo"
1528+
src="/assets/the-wall-street-journal.png"
1529+
style={{ width: 320, height: 'auto' }}
1530+
/>
15321531
<h2 className="band-heading">How Five Americans Made It to the Middle Class</h2>
15331532
<p className="band-body">
15341533
We are proud to be part of this success story, as featured in the Wall Street Journal. Tim
@@ -1551,10 +1550,10 @@ function WSJTeaser() {
15511550
);
15521551
}
15531552

1554-
// Latest three from the CodeBlog. Same source as blog.jsx — replaced by the Sanity `post` document type at runtime.
1555-
// Same 3 posts (and same seed slugs) as SEED_POSTS in Blog.jsx — this teaser stays
1556-
// hardcoded rather than Sanity-backed (a separate, pre-existing gap unrelated to
1557-
// giving posts their own pages), but its links now point at those pages too.
1553+
// Latest three from the CodeBlog. Seed fallback only — same shape and seed slugs as
1554+
// SEED_POSTS in Blog.jsx. CodeBlog() below fetches the real thing via useSanityPosts,
1555+
// same as the /blog page, so this array only renders when there's no Sanity project
1556+
// configured or no live posts yet.
15581557
const LATEST_POSTS = [
15591558
{
15601559
title: 'Best Corporate AI Bootcamps',
@@ -1588,6 +1587,7 @@ function fmtPostDate(iso) {
15881587
}
15891588

15901589
function CodeBlog() {
1590+
const posts = useSanityPosts(LATEST_POSTS).slice(0, 3);
15911591
return (
15921592
<section id="codeblog" className="sect sect-steel">
15931593
<div className="wrap">
@@ -1602,16 +1602,26 @@ function CodeBlog() {
16021602
</p>
16031603
</div>
16041604
<div className="grid3">
1605-
{LATEST_POSTS.map((p) => (
1605+
{posts.map((p) => (
16061606
<Link key={p.slug} to={'/blog/' + p.slug} className="panel panel-link-card">
1607-
<div className="d-flex flex-column gap-3">
1608-
<Badge bg="brand">{p.category}</Badge>
1609-
<h3 className="ptitle">{p.title}</h3>
1610-
<p className="pbody">{p.excerpt}</p>
1611-
</div>
1612-
<div className="d-flex flex-column gap-4">
1613-
<div className="rule" />
1614-
<span className="card-date">{fmtPostDate(p.date)}</span>
1607+
<image-slot
1608+
id={'codeblog-' + p.slug}
1609+
src={sanityImageUrl(p.featuredImage, { w: 500 })}
1610+
shape="rect"
1611+
fit="cover"
1612+
placeholder="Cover image"
1613+
style={{ width: '100%', height: 180 }}
1614+
></image-slot>
1615+
<div className="panel-link-card-body">
1616+
<div className="d-flex flex-column gap-3">
1617+
<Badge bg="brand">{p.category}</Badge>
1618+
<h3 className="ptitle">{p.title}</h3>
1619+
<p className="pbody">{p.excerpt}</p>
1620+
</div>
1621+
<div className="d-flex flex-column gap-4">
1622+
<div className="rule" />
1623+
<span className="card-date">{fmtPostDate(p.date)}</span>
1624+
</div>
16151625
</div>
16161626
</Link>
16171627
))}

src/pages/Ventures.jsx

Lines changed: 69 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import React from 'react';
2-
import { Button, Badge, Form } from 'react-bootstrap';
2+
import { Button, Badge, Form, Offcanvas } from 'react-bootstrap';
33
import { TopBar, Footer } from '../components/Chrome';
44
import '../lib/image-slot.js';
55

6+
const PITCH_BLANK = { first: '', last: '', email: '', phone: '', kind: '', details: '' };
7+
const PROJECT_KINDS = ['Native App', 'Web App', 'Web Base Project', 'Other'];
8+
69
const MODELS = [
710
[
811
'Build for Equity',
@@ -48,7 +51,7 @@ const CRITERIA = [
4851
['A Path to Revenue', 'A named first customer or a market we can reach in the first year.'],
4952
];
5053

51-
function Band() {
54+
function Band({ onPitch }) {
5255
return (
5356
<section className="band-dark">
5457
<div className="wrap d-flex flex-column gap-4 align-items-start">
@@ -58,13 +61,7 @@ function Band() {
5861
CodeBoxx Ventures puts the studio&rsquo;s delivery capacity behind products we believe in.
5962
Cash, equity, or both &mdash; the structure follows the stage you are at.
6063
</p>
61-
<Button
62-
onClick={() => {
63-
location.href = '/#contact';
64-
}}
65-
>
66-
Pitch Your Project
67-
</Button>
64+
<Button onClick={onPitch}>Pitch Your Project</Button>
6865
</div>
6966
</section>
7067
);
@@ -128,70 +125,86 @@ function Criteria() {
128125
);
129126
}
130127

131-
function Pitch() {
128+
function PitchDrawer({ open, onClose }) {
129+
const [form, setForm] = React.useState(PITCH_BLANK);
130+
const [sent, setSent] = React.useState(false);
131+
React.useEffect(() => {
132+
if (open) setSent(false);
133+
}, [open]);
134+
const set = (k) => (e) => setForm((f) => Object.assign({}, f, { [k]: e.target.value }));
135+
const invalid = form.email.length > 0 && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(form.email);
136+
const ready = form.first && form.last && form.email && !invalid && form.phone;
132137
return (
133-
<section className="sect">
134-
<div className="wrap grid2">
135-
<div className="d-flex flex-column gap-3">
136-
<p className="eyebrow">START THE CONVERSATION</p>
137-
<h2 className="h2">Have a project and looking for a venture-style partner?</h2>
138-
<p className="lede">
139-
Send the product, the stage you are at and what you need built. A delivery lead and a
140-
partner review it together and answer with a proposed structure.
141-
</p>
142-
<div className="d-flex gap-3 flex-wrap">
143-
<Button
144-
variant="outline-primary"
145-
onClick={() => {
146-
location.href = 'CodeBoxx.html#solutions';
147-
}}
148-
>
149-
See the Studio
150-
</Button>
151-
</div>
138+
<Offcanvas show={open} onHide={onClose} placement="end" className="pitch-offcanvas">
139+
<Offcanvas.Header className="site-header">
140+
<div className="d-flex flex-column gap-3 align-items-start">
141+
<span className="kicker">Ventures</span>
142+
<h3 className="ptitle">Pitch Your Project</h3>
152143
</div>
153-
<div className="panel">
154-
<h3 className="ptitle">Submit your project</h3>
155-
<Form.Group>
156-
<Form.Label>Full Name</Form.Label>
157-
<Form.Control id="v-name" placeholder="First Last" />
158-
</Form.Group>
159-
<Form.Group>
160-
<Form.Label>Email</Form.Label>
161-
<Form.Control id="v-email" placeholder="name@company.com" />
162-
</Form.Group>
163-
<Form.Group>
164-
<Form.Label>Company or Product</Form.Label>
165-
<Form.Control id="v-company" placeholder="codeboxx-enterprise-primary" />
166-
</Form.Group>
167-
<Form.Group>
168-
<Form.Label>Stage</Form.Label>
169-
<Form.Control id="v-stage" placeholder="Idea, prototype, or in market" />
170-
</Form.Group>
171-
<div className="rule" />
172-
<div className="form-actions">
173-
<span className="form-actions-note">Reviewed within one business day.</span>
174-
<Button size="lg">Send</Button>
175-
</div>
144+
<Button size="sm" variant="ghost" onClick={onClose}>
145+
Close
146+
</Button>
147+
</Offcanvas.Header>
148+
<Offcanvas.Body className="d-flex flex-column gap-4">
149+
<div className="form-row-2">
150+
<Form.Control placeholder="First Name" value={form.first} onChange={set('first')} />
151+
<Form.Control placeholder="Last Name" value={form.last} onChange={set('last')} />
176152
</div>
177-
</div>
178-
</section>
153+
<Form.Group>
154+
<Form.Control
155+
placeholder="Email"
156+
value={form.email}
157+
isInvalid={invalid}
158+
onChange={set('email')}
159+
/>
160+
<Form.Control.Feedback type="invalid">
161+
Invalid address. Missing domain.
162+
</Form.Control.Feedback>
163+
</Form.Group>
164+
<Form.Control placeholder="Phone" value={form.phone} onChange={set('phone')} />
165+
<Form.Group>
166+
<Form.Label>What kind of project</Form.Label>
167+
<Form.Select aria-label="What kind of project" value={form.kind} onChange={set('kind')}>
168+
<option value="">Select</option>
169+
{PROJECT_KINDS.map((k) => (
170+
<option key={k} value={k}>
171+
{k}
172+
</option>
173+
))}
174+
</Form.Select>
175+
</Form.Group>
176+
<Form.Group>
177+
<Form.Label>Describe your project in a few words</Form.Label>
178+
<Form.Control as="textarea" rows={4} value={form.details} onChange={set('details')} />
179+
</Form.Group>
180+
<div className="rule" />
181+
<div className="form-actions">
182+
<span className={'form-actions-note' + (sent ? ' sent' : '')}>
183+
{sent ? 'Pitch received.' : 'Reviewed within one business day.'}
184+
</span>
185+
<Button size="lg" disabled={!ready} onClick={() => setSent(true)}>
186+
Submit
187+
</Button>
188+
</div>
189+
</Offcanvas.Body>
190+
</Offcanvas>
179191
);
180192
}
181193

182194
function VenturesPage() {
195+
const [pitchOpen, setPitchOpen] = React.useState(false);
183196
return (
184197
<div id="top">
185198
<TopBar
186199
onCodi={() => {
187200
location.href = '/#contact';
188201
}}
189202
/>
190-
<Band />
203+
<Band onPitch={() => setPitchOpen(true)} />
191204
<Models />
192205
<Criteria />
193-
<Pitch />
194206
<Footer />
207+
<PitchDrawer open={pitchOpen} onClose={() => setPitchOpen(false)} />
195208
</div>
196209
);
197210
}

src/styles/_home.scss

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,9 @@
591591
}
592592

593593
.panel-link-card {
594-
justify-content: space-between;
594+
padding: 0;
595+
gap: 0;
596+
overflow: hidden;
595597
min-height: 260px;
596598
color: inherit;
597599
text-decoration: none;
@@ -600,6 +602,14 @@
600602
text-decoration: none;
601603
}
602604
}
605+
.panel-link-card-body {
606+
display: flex;
607+
flex-direction: column;
608+
justify-content: space-between;
609+
gap: 20px;
610+
padding: 24px;
611+
flex: 1;
612+
}
603613
.card-date {
604614
font-size: v.$text-micro;
605615
font-weight: v.$weight-medium;

src/styles/_static-pages.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,8 @@
3232
gap: 20px;
3333
max-width: 780px;
3434
}
35+
36+
// ---- Ventures "Pitch Your Project" drawer ----
37+
.pitch-offcanvas {
38+
--bs-offcanvas-width: 460px;
39+
}

0 commit comments

Comments
 (0)