Create a Project Card web component

This commit is contained in:
Nettika 2026-01-25 14:35:44 -08:00
parent f33746a274
commit ac64fd8ebe
No known key found for this signature in database
2 changed files with 91 additions and 1 deletions

90
src/project-card.js Normal file
View file

@ -0,0 +1,90 @@
class ProjectCard extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
connectedCallback() {
this.render();
}
static get observedAttributes() {
return ['title', 'percentage', 'archived'];
}
attributeChangedCallback() {
this.render();
}
render() {
const title = this.getAttribute('title') || 'Untitled Project';
const percentage = parseInt(this.getAttribute('percentage')) || 0;
const archived = this.getAttribute('archived') === 'true';
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
}
.card {
border: 1px solid var(--color-bg-secondary, #e9e9e9);
border-radius: var(--border-radius, 5px);
box-shadow: var(--box-shadow, 2px 2px 10px) var(--color-shadow, #f4f4f4);
padding: 1.25rem;
margin: 1rem;
width: var(--width-card, 285px);
background: var(--color-bg, #fff);
}
.card:hover {
box-shadow: var(--box-shadow, 2px 2px 10px) var(--color-bg-secondary, #e9e9e9);
}
.card.archived {
opacity: 0.6;
}
.title {
font-weight: bold;
margin-bottom: 0.5rem;
color: var(--color-text, #000);
}
.progress-bar {
width: 100%;
height: 20px;
background-color: var(--color-bg-secondary, #e9e9e9);
border-radius: var(--border-radius, 5px);
overflow: hidden;
margin-bottom: 0.5rem;
}
.progress-fill {
height: 100%;
background-color: var(--color-link, #118bee);
transition: width 0.3s ease;
}
.percentage {
font-size: 0.9rem;
color: var(--color-text-secondary, #999);
}
.archived-badge {
display: inline-block;
background-color: var(--color-text-secondary, #999);
color: white;
padding: 0.2rem 0.5rem;
border-radius: var(--border-radius, 5px);
font-size: 0.8rem;
margin-left: 0.5rem;
}
</style>
<div class="card ${archived ? 'archived' : ''}">
<div class="title">
${title}
${archived ? '<span class="archived-badge">Archived</span>' : ''}
</div>
<div class="progress-bar">
<div class="progress-fill" style="width: ${percentage}%"></div>
</div>
<div class="percentage">${percentage}% complete</div>
</div>
`;
}
}
customElements.define('project-card', ProjectCard);

View file

@ -5,7 +5,7 @@
[x] Create a `Project` struct that corresponds to the schema definition.
[x] Create a module or struct at your discretion for interfacing with the database. Create functions for the following: create a project, update a project's progress, archive a project, unarchive a project, and list of all projects.
[x] Create a `main.css` file in src. Use mvp.css as a starting point.
[ ] Create a `project-card.js` file in src that creates a web component for displaying a project.
[x] Create a `project-card.js` file in src that creates a web component for displaying a project.
[ ] Using a Rouille router, create `GET /main.css` and `GET /project-card.js` endpoints that returns the relevant files. Use the include_bytes! macro.
[ ] Create a `GET /projects` endpoint. Using Maud for markup generation, have this endpoint return an HTML page that shows all projects. Each project should be a `project-card` web component. Keep the page simple: no title or any buttons currently.
[ ] Create a `POST /projects` endpoint that accepts URL encoded data and creates a new project.