Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 13 additions & 23 deletions src/AppwriteService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ export const AppwriteService = {
}
},
countProjects: async (queries: string[]) => {
console.log("Counting projects...");
const hasIsPublished = queries.find((query) =>
query.startsWith('equal("isPublished')
);
Expand All @@ -90,17 +89,14 @@ export const AppwriteService = {
if (!hasCreatedAtSort) {
queries.push(Query.orderDesc("$createdAt"));
}
try {
const response = await databases.listDocuments<Project>(
"main",
"projects",
queries
);

return response.total;
} catch (error) {
console.error(`Error counting projects: ${error}`);
}
const response = await databases.listDocuments<Project>(
"main",
"projects",
queries
);

return response.total;
},
getProject: async (projectId: string) => {
const project = await databases.getDocument<Project>(
Expand All @@ -111,7 +107,6 @@ export const AppwriteService = {
return project;
},
listProjects: async (queries: string[]) => {
console.log("Listing projects...");
const hasIsPublished = queries.find((query) =>
query.startsWith('equal("isPublished')
);
Expand All @@ -129,18 +124,13 @@ export const AppwriteService = {
queries.push(Query.orderDesc("$createdAt"));
}

try {
const { documents: projects } = await databases.listDocuments<Project>(
"main",
"projects",
queries
);
const { documents: projects } = await databases.listDocuments<Project>(
"main",
"projects",
queries
);

return projects;
} catch (error) {
console.error("Listing projects failed: " + error);
return [];
}
return projects;
},
searchProjects: async (searchQuery: string) => {
const { documents: projects } = await databases.listDocuments<Project>(
Expand Down
21 changes: 21 additions & 0 deletions src/routes/404.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { component$ } from "@builder.io/qwik";
import { Link } from "@builder.io/qwik-city";

export default component$(() => {
return (
<ul class="u-flex u-gap-24 u-flex-vertical-mobile">
<div class="u-flex-vertical u-gap-24 u-flex-shrink-0 u-flex-basis-50-percent">
<Link href="/" style="padding: 0px;" class="button is-text">
<span class="icon-cheveron-left" aria-hidden="true"></span>
<span class="text">Back to Projects</span>
</Link>
<div>
<h2 class="heading-level-2">404</h2>
<p class="u-margin-block-start-16" style="font-size: 1rem;">
Page not found.
</p>
</div>
</div>
</ul>
);
});
148 changes: 93 additions & 55 deletions src/routes/projects/[projectId]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,87 @@ import { marked } from "marked";
import ProjectTags from "~/components/layout/ProjectTags";
import Upvote from "~/components/blocks/Upvote";
import Socials from "~/components/blocks/Socials";
import { AppwriteException } from "appwrite";

export const useProjectData = routeLoader$(async ({ params, status }) => {
try {
return {
project: await AppwriteService.getProject(params.projectId),
error: null,
};
} catch (error) {
if (error instanceof AppwriteException) {
status(error.code);
return { project: null, error };
}
}

export const useProjectData = routeLoader$(async ({ params }) => {
return {
project: await AppwriteService.getProject(params.projectId),
project: null,
error: {
code: 500,
message: "Internal Server Error",
},
};
});

export const head: DocumentHead = ({ resolveValue }) => {
const projectData = resolveValue(useProjectData);
const { project, error } = resolveValue(useProjectData);

if (error?.code === 500) {
return {
title: "Something went wrong | Built with Appwrite",
};
}

if (!project) {
return {
title: "Project not found | Built with Appwrite",
};
}

return {
title: `${projectData.project.name} | Built with Appwrite`,
title: `${project.name} | Built with Appwrite`,
meta: [
{
name: "description",
content: projectData.project.tagline,
content: project.tagline,
},
{
name: "og:title",
content: `${projectData.project.name} | Built with Appwrite`,
content: `${project.name} | Built with Appwrite`,
},
{
name: "og:description",
content: projectData.project.tagline,
content: project.tagline,
},
],
};
};

export default component$(() => {
const projectData = useProjectData();
const { project, error } = useProjectData().value;

const html = marked(projectData.value.project.description, {
if (error) {
return (
<ul class="u-flex u-gap-24 u-flex-vertical-mobile">
<div class="u-flex-vertical u-gap-24 u-flex-shrink-0 u-flex-basis-50-percent">
<Link href="/" style="padding: 0px;" class="button is-text">
<span class="icon-cheveron-left" aria-hidden="true"></span>
<span class="text">Back to Projects</span>
</Link>
<div>
<h2 class="heading-level-2">{error.code}</h2>
<p class="u-margin-block-start-16" style="font-size: 1rem;">
{error.message}
</p>
</div>
</div>
</ul>
);
}

const html = marked(project.description, {
mangle: false,
headerIds: false,
});
Expand All @@ -48,7 +96,7 @@ export default component$(() => {
localStorage.getItem("visitedProjects") ?? "[]"
) as string[];

visitedProjects.unshift(projectData.value.project.$id);
visitedProjects.unshift(project.$id);

const visitedProjectsUnique = [...new Set(visitedProjects)];

Expand All @@ -68,30 +116,24 @@ export default component$(() => {
</Link>

<div class="u-flex u-gap-16 u-cross-center">
<h2 class="heading-level-2">{projectData.value.project.name}</h2>
<Upvote
projectId={projectData.value.project.$id}
votes={projectData.value.project.upvotes}
inline
/>
<h2 class="heading-level-2">{project.name}</h2>
<Upvote projectId={project.$id} votes={project.upvotes} inline />
</div>

<p style="font-size: 1.2rem; margin-top: -1rem;">
{projectData.value.project.tagline}
</p>
<p style="font-size: 1.2rem; margin-top: -1rem;">{project.tagline}</p>

{(projectData.value.project.urlGooglePlay ||
projectData.value.project.urlAppStore ||
projectData.value.project.urlMacOs ||
projectData.value.project.urlWindows ||
projectData.value.project.urlLinux) && (
{(project.urlGooglePlay ||
project.urlAppStore ||
project.urlMacOs ||
project.urlWindows ||
project.urlLinux) && (
<div>
<h4 class="eyebrow-heading-3">Download the Application</h4>

<div class="u-flex u-flex-wrap u-cross-center u-gap-8 u-margin-block-start-12">
{projectData.value.project.urlGooglePlay && (
{project.urlGooglePlay && (
<a
href={projectData.value.project.urlGooglePlay}
href={project.urlGooglePlay}
target="_blank"
class="button is-secondary"
>
Expand All @@ -100,9 +142,9 @@ export default component$(() => {
</a>
)}

{projectData.value.project.urlWindows && (
{project.urlWindows && (
<a
href={projectData.value.project.urlWindows}
href={project.urlWindows}
target="_blank"
class="button is-secondary"
>
Expand All @@ -111,9 +153,9 @@ export default component$(() => {
</a>
)}

{projectData.value.project.urlLinux && (
{project.urlLinux && (
<a
href={projectData.value.project.urlLinux}
href={project.urlLinux}
target="_blank"
class="button is-secondary"
>
Expand All @@ -122,9 +164,9 @@ export default component$(() => {
</a>
)}

{projectData.value.project.urlAppStore && (
{project.urlAppStore && (
<a
href={projectData.value.project.urlAppStore}
href={project.urlAppStore}
target="_blank"
class="button is-secondary"
>
Expand All @@ -133,9 +175,9 @@ export default component$(() => {
</a>
)}

{projectData.value.project.urlMacOs && (
{project.urlMacOs && (
<a
href={projectData.value.project.urlMacOs}
href={project.urlMacOs}
target="_blank"
class="button is-secondary"
>
Expand All @@ -147,17 +189,17 @@ export default component$(() => {
</div>
)}

{(projectData.value.project.urlWebsite ||
projectData.value.project.urlGitHub ||
projectData.value.project.urlTwitter ||
projectData.value.project.urlArticle) && (
{(project.urlWebsite ||
project.urlGitHub ||
project.urlTwitter ||
project.urlArticle) && (
<div>
<h4 class="eyebrow-heading-3">Stay in Touch</h4>

<div class="u-flex u-flex-wrap u-cross-center u-gap-8 u-margin-block-start-12">
{projectData.value.project.urlWebsite && (
{project.urlWebsite && (
<a
href={projectData.value.project.urlWebsite}
href={project.urlWebsite}
target="_blank"
class="button is-secondary"
>
Expand All @@ -166,19 +208,19 @@ export default component$(() => {
</a>
)}

{projectData.value.project.urlGitHub && (
{project.urlGitHub && (
<a
href={projectData.value.project.urlGitHub}
href={project.urlGitHub}
target="_blank"
class="button is-secondary"
>
<span class="icon-github" aria-hidden="true"></span>
<p>View on GitHub</p>
</a>
)}
{projectData.value.project.urlTwitter && (
{project.urlTwitter && (
<a
href={projectData.value.project.urlTwitter}
href={project.urlTwitter}
target="_blank"
class="button is-secondary"
>
Expand All @@ -187,9 +229,9 @@ export default component$(() => {
</a>
)}

{projectData.value.project.urlArticle && (
{project.urlArticle && (
<a
href={projectData.value.project.urlArticle}
href={project.urlArticle}
target="_blank"
class="button is-secondary"
>
Expand All @@ -204,7 +246,7 @@ export default component$(() => {
<div>
<h4 class="eyebrow-heading-3">Tags</h4>
<div class="u-flex u-flex-wrap u-gap-8 u-margin-block-start-12">
<ProjectTags project={projectData.value.project} />
<ProjectTags project={project} />
</div>
</div>

Expand All @@ -214,20 +256,16 @@ export default component$(() => {
>
<h4 class="eyebrow-heading-3">Share</h4>
<Socials
url={`https://builtwith.appwrite.io/projects/${projectData.value.project.$id}`}
title={`Built with Appwrite: ${projectData.value.project.name}`}
body={projectData.value.project.tagline}
url={`https://builtwith.appwrite.io/projects/${project.$id}`}
title={`Built with Appwrite: ${project.name}`}
body={project.tagline}
/>
</div>
</div>

<div>
<div class="object-og object-og-rounded">
<img
src={AppwriteService.getProjectThumbnail(
projectData.value.project.imageId
)}
/>
<img src={AppwriteService.getProjectThumbnail(project.imageId)} />
</div>
</div>
</ul>
Expand Down