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
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
"preview": "vite preview"
},
"dependencies": {
"dompurify": "^3.2.6",
"marked": "^16.0.0",
"pinia": "^3.0.2",
"vue": "^3.5.13",
"vue-router": "^4.5.0"
Expand Down
Binary file modified public/favicon.ico
Binary file not shown.
Binary file added public/images/education/iut_valencia.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/education/uah_logo.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/recommendation/amrith-g.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/recommendation/bhupesh-pathak.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/recommendation/dawid-makowski.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/recommendation/jarek-tkaczyk.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/recommendation/kong-kw.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/recommendation/ross-riley.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/pages/AboutPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
<aside class="md:w-[240px] lg:w-[300px] shrink-0">
<div class="space-y-6">
<WidgetSocialPartial />
<WidgetNewsletterPartial />
<WidgetSkillsPartial />
</div>
</aside>
</div>
Expand All @@ -88,7 +88,7 @@ import FooterPartial from '@partials/FooterPartial.vue';
import HeaderPartial from '@partials/HeaderPartial.vue';
import SideNavPartial from '@partials/SideNavPartial.vue';
import WidgetSocialPartial from '@partials/WidgetSocialPartial.vue';
import WidgetNewsletterPartial from '@partials/WidgetNewsletterPartial.vue';
import WidgetSkillsPartial from '@partials/WidgetSkillsPartial.vue';

const userStore = useUserStore();
const user = ref<User | null>(null);
Expand Down
4 changes: 2 additions & 2 deletions src/pages/HomePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<!-- Right sidebar -->
<aside class="md:w-[240px] lg:w-[300px] shrink-0">
<div class="space-y-6">
<WidgetNewsletterPartial />
<WidgetSkillsPartial />
<WidgetSponsorPartial />
</div>
</aside>
Expand All @@ -47,7 +47,7 @@ import SideNavPartial from '@partials/SideNavPartial.vue';
import ArticlesListPartial from '@partials/ArticlesListPartial.vue';
import WidgetSponsorPartial from '@partials/WidgetSponsorPartial.vue';
import FeaturedProjectsPartial from '@partials/FeaturedProjectsPartial.vue';
import WidgetNewsletterPartial from '@partials/WidgetNewsletterPartial.vue';
import WidgetSkillsPartial from '@partials/WidgetSkillsPartial.vue';

import { useUserStore } from '@stores/users/user.ts';
import { onMounted } from 'vue';
Expand Down
4 changes: 2 additions & 2 deletions src/pages/PostPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@
<!-- Right sidebar -->
<aside class="md:w-[240px] lg:w-[300px] shrink-0">
<div class="space-y-6">
<WidgetNewsletterPartial />
<WidgetSkillsPartial />
<WidgetSponsorPartial />
<WidgetPostsPartial />
</div>
Expand All @@ -215,7 +215,7 @@
<script setup>
import SideNavPartial from '@partials/SideNavPartial.vue';
import HeaderPartial from '@partials/HeaderPartial.vue';
import WidgetNewsletterPartial from '@partials/WidgetNewsletterPartial.vue';
import WidgetSkillsPartial from '@partials/WidgetSkillsPartial.vue';
import WidgetSponsorPartial from '@partials/WidgetSponsorPartial.vue';
import WidgetPostsPartial from '@partials/WidgetPostsPartial.vue';
import FooterPartial from '@partials/FooterPartial.vue';
Expand Down
4 changes: 2 additions & 2 deletions src/pages/ProjectsPage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<!-- Right sidebar -->
<aside class="md:w-[240px] lg:w-[300px] shrink-0">
<div class="space-y-6">
<WidgetNewsletterPartial />
<WidgetSkillsPartial />
<WidgetSponsorPartial />
</div>
</aside>
Expand All @@ -66,7 +66,7 @@ import HeaderPartial from '@partials/HeaderPartial.vue';
import SideNavPartial from '@partials/SideNavPartial.vue';
import type { Project, User } from '@stores/users/userType.ts';
import ProjectCardPartial from '@partials/ProjectCardPartial.vue';
import WidgetNewsletterPartial from '@partials/WidgetNewsletterPartial.vue';
import WidgetSkillsPartial from '@partials/WidgetSkillsPartial.vue';
import WidgetSponsorPartial from '@partials/WidgetSponsorPartial.vue';

const userStore = useUserStore();
Expand Down
6 changes: 2 additions & 4 deletions src/pages/ResumePage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
<h1 class="h1 font-aspekta mb-12">My resume</h1>
<!-- Page content -->
<div class="text-slate-500 dark:text-slate-400 space-y-12">
<RecommendationPartial />
<AwardsPartial />
<EducationPartial />
<RecommendationPartial v-if="user" :recommendations="user.recommendations" />
<EducationPartial v-if="user" :education="user.education" />
<ExperiencePartial v-if="user" :experience="user.experience" />
</div>
</section>
Expand All @@ -46,7 +45,6 @@

<script setup lang="ts">
import HeaderPartial from '@partials/HeaderPartial.vue';
import AwardsPartial from '@partials/AwardsPartial.vue';
import FooterPartial from '@partials/FooterPartial.vue';
import SideNavPartial from '@partials/SideNavPartial.vue';
import EducationPartial from '@partials/EducationPartial.vue';
Expand Down
75 changes: 43 additions & 32 deletions src/partials/EducationPartial.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,62 @@
<h2 class="h3 font-aspekta text-slate-800 dark:text-slate-100">Education</h2>
<ul class="space-y-8">
<!-- Item -->
<li class="relative group">
<li class="relative group" v-for="item in processedEducation" :key="item.uuid">
<div
class="flex items-start before:absolute before:left-0 before:h-full before:w-px before:bg-slate-200 dark:before:bg-slate-800 before:self-start before:ml-[28px] before:-translate-x-1/2 before:translate-y-8 group-last-of-type:before:hidden"
>
<div
class="absolute left-0 h-14 w-14 flex items-center justify-center border border-slate-200 dark:border-slate-800 dark:bg-linear-to-t dark:from-slate-800 dark:to-slate-800/30 bg-white dark:bg-slate-900 rounded-full"
>
<img src="../images/education-icon-01.svg" width="24" height="24" alt="Purdue University" />
</div>
<div class="pl-20 space-y-1">
<div class="text-xs text-slate-500 uppercase">May 2017 <span class="text-slate-400 dark:text-slate-600">·</span> Apr 2020</div>
<div class="font-aspekta font-[650] text-slate-800 dark:text-slate-100">Master of Technology Science</div>
<div class="text-sm font-medium text-slate-800 dark:text-slate-100">Purdue University</div>
<div class="text-sm text-slate-500 dark:text-slate-400">
Throughout my years at Purdue, I immersed myself in a dynamic learning environment, surrounded by dedicated faculty and talented peers.
</div>
</div>
</div>
</li>
<!-- Item -->
<li class="relative group">
<div
class="flex items-start before:absolute before:left-0 before:h-full before:w-px before:bg-slate-200 dark:before:bg-slate-800 before:self-start before:ml-[28px] before:-translate-x-1/2 before:translate-y-8 group-last-of-type:before:hidden"
>
<div
class="absolute left-0 h-14 w-14 flex items-center justify-center border border-slate-200 dark:border-slate-800 dark:bg-linear-to-t dark:from-slate-800 dark:to-slate-800/30 bg-white dark:bg-slate-900 rounded-full"
>
<img src="../images/education-icon-02.svg" width="24" height="26" alt="San Jose State UniversitySan Jose State University" />


<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="opacity-30 size-8 dark:opacity-30 fill-none text-fuchsia-500 dark:text-white"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M4.26 10.147a60.438 60.438 0 0 0-.491 6.347A48.62 48.62 0 0 1 12 20.904a48.62 48.62 0 0 1 8.232-4.41 60.46 60.46 0 0 0-.491-6.347m-15.482 0a50.636 50.636 0 0 0-2.658-.813A59.906 59.906 0 0 1 12 3.493a59.903 59.903 0 0 1 10.399 5.84c-.896.248-1.783.52-2.658.814m-15.482 0A50.717 50.717 0 0 1 12 13.489a50.702 50.702 0 0 1 7.74-3.342M6.75 15a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Zm0 0v-3.675A55.378 55.378 0 0 1 12 8.443m-7.007 11.55A5.981 5.981 0 0 0 6.75 15.75v-1.5"
/>
</svg>

</div>
<div class="pl-20 space-y-1">
<div class="text-xs text-slate-500 uppercase">May 2013 <span class="text-slate-400 dark:text-slate-600">·</span> Apr 2017</div>
<div class="font-aspekta font-[650] text-slate-800 dark:text-slate-100">Bachelor of Technology</div>
<div class="text-sm font-medium text-slate-800 dark:text-slate-100">San Jose State UniversitySan Jose State University</div>
<div class="text-sm text-slate-500 dark:text-slate-400">
Throughout my years at SJSU, I immersed myself in a dynamic learning environment, surrounded by dedicated faculty and talented peers.
</div>
<div class="text-xs text-slate-500 uppercase">Year <span class="text-slate-400 dark:text-slate-600">·</span> {{ item.graduated_at }}</div>
<div class="font-aspekta font-[650] text-slate-800 dark:text-slate-100">{{ item.degree }}</div>
<div class="text-sm font-medium text-slate-800 dark:text-slate-100">{{ item.school }}</div>
<div class="text-sm text-slate-500 dark:text-slate-400" v-html="item.html"></div>
</div>
</div>
</li>
</ul>
</div>
</template>

<script>
export default {
name: 'EducationPartial',
};
<script setup lang="ts">
import { computed } from 'vue';
import { marked } from 'marked';
import DOMPurify from 'dompurify';
import type { Education } from '@stores/users/userType.ts';
const { education } = defineProps<{
education: Education[]
}>()
const processedEducation = computed(() => {
return education.map(item => {
const sanitisedHtml = DOMPurify.sanitize(marked.parse(item.description) as string);
return {
...item,
html: sanitisedHtml,
};
});
});
</script>
64 changes: 39 additions & 25 deletions src/partials/RecommendationPartial.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,55 @@
<h2 class="h3 font-aspekta text-slate-800 dark:text-slate-100">Recommendations</h2>
<ul class="space-y-8">
<!-- Item -->
<li class="relative group">
<li class="relative group" v-for="item in processedRecommendations" :key="item.uuid">
<div class="flex items-start">
<div
class="absolute left-0 h-14 w-14 flex items-center justify-center dark:border-slate-800 dark:bg-linear-to-t dark:from-slate-800 dark:to-slate-800/30 bg-white dark:bg-slate-900 rounded-full"
>
<img class="rounded-full" src="../images/testimonial-03.jpg" width="56" height="56" alt="Testimonial 03" />
<img class="rounded-full" :src="image(item.person.avatar)" width="56" height="56" :alt="item.person.full_name" />
</div>
<div class="pl-20 space-y-1">
<div class="font-aspekta font-[650] text-slate-800 dark:text-slate-100">Mary Christopher</div>
<div class="text-sm font-medium text-slate-800 dark:text-slate-100">Designer Lead at Inventa Inc.</div>
<div class="text-sm text-slate-500 dark:text-slate-400">
“ Working with James on projects is a breath of fresh air. He is an extremely talented dev, with an outstanding work ethic, eye for detail, and speed. James doesn't just
execute and deliver incredible codes but works with you to challenge the product or flow at hand to create the best possible solution. ”
</div>
</div>
</div>
</li>
<!-- Item -->
<li class="relative group">
<div class="flex items-start">
<div
class="absolute left-0 h-14 w-14 flex items-center justify-center dark:border-slate-800 dark:bg-linear-to-t dark:from-slate-800 dark:to-slate-800/30 bg-white dark:bg-slate-900 rounded-full"
>
<img class="rounded-full" src="../images/testimonial-04.jpg" width="56" height="56" alt="Testimonial 04" />
</div>
<div class="pl-20 space-y-1">
<div class="font-aspekta font-[650] text-slate-800 dark:text-slate-100">Harry Kastelli</div>
<div class="text-sm font-medium text-slate-800 dark:text-slate-100">CEO & Founder Mark Corp.</div>
<div class="text-sm text-slate-500 dark:text-slate-400">
“ James is an excellent developer. He is not just quick to evaluate and translate ideas into high-fidelity codes, but he's also well-versed in UX strategy. While working
together, James handled our external partnership with Design Agencies, and delivered weekly progress reports with fresh ideas. ”
<div class="font-aspekta font-[650] text-slate-800 dark:text-slate-100">{{ item.person.full_name }}</div>
<div class="text-sm font-medium text-slate-800 dark:text-slate-100">{{ item.person.company }}</div>
<div class="flex justify-between text-xs dark:text-teal-500 text-slate-400 pb-2 ">
<div>{{ item.relation }}</div>
<div>{{ item.formattedDate }}</div>
</div>
<div class="text-sm text-slate-500 dark:text-slate-400" v-html="item.html"></div>
</div>
</div>
</li>
</ul>
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue';
import { marked } from 'marked';
import DOMPurify from 'dompurify';
import { image, date } from '@/public.ts';
import type { Recommendation } from '@stores/users/userType.ts';


marked.use({
breaks: true,
gfm: true,
});

const { recommendations } = defineProps<{
recommendations: Recommendation[]
}>()

const processedRecommendations = computed(() => {
return recommendations.map(item => {
const sanitisedHtml = DOMPurify.sanitize(marked.parse(item.text) as string);

return {
...item,
html: sanitisedHtml,
formattedDate: date().format(new Date(item.created_at)),
};
});
});

</script>
13 changes: 0 additions & 13 deletions src/partials/SideNavPartial.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,6 @@
</a>
</router-link>
</li>

<!-- subscribe -->
<li class="py-2">
<router-link v-slot="{ href, navigate, isExactActive }" to="/subscribe" custom>
<a class="h6 blog-side-nav-router-link-a" :class="bindIconClassFor(isExactActive)" :href="href" @click="navigate">
<span class="sr-only">Subscribe</span>
<svg class="fill-current" xmlns="http://www.w3.org/2000/svg" width="21" height="21">
<path fill-opacity=".16" d="m13.4 18-3-7.4-7.4-3L19 2z" />
<path d="M13.331 15.169 17.37 3.63 5.831 7.669l5.337 2.163 2.163 5.337Zm-3.699-3.801L.17 7.53 20.63.37l-7.161 20.461-3.837-9.463Z" />
</svg>
</a>
</router-link>
</li>
</ul>
</nav>
</div>
Expand Down
12 changes: 12 additions & 0 deletions src/public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,15 @@ const IMAGES_DIR = 'images';
export function image(filename: string): string {
return `/${IMAGES_DIR}/${filename}`;
}

export function date(language?: string, options?: Intl.DateTimeFormatOptions): Intl.DateTimeFormat {
const lang = language || "en-US";

const ops = options || {
year: "numeric",
month: "long",
day: "numeric"
}

return new Intl.DateTimeFormat(lang, ops)
}
Loading