Skip to content

Commit

Permalink
Merge pull request #77 from dzcode-io/65-projects-scene
Browse files Browse the repository at this point in the history
Added projects scene
  • Loading branch information
ZibanPirate authored Jul 16, 2020
2 parents 871923b + 0be3441 commit 5e79474
Show file tree
Hide file tree
Showing 14 changed files with 385 additions and 0 deletions.
4 changes: 4 additions & 0 deletions data/projects/list.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"items": ["Algerian_Users"],
"include": ["title"]
}
2 changes: 2 additions & 0 deletions frontend/src/apps/main/entry/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import "react-toastify/dist/ReactToastify.css";

const Landing = lazy(() => import("t9/apps/main/scenes/landing"));
const Articles = lazy(() => import("t9/apps/main/scenes/articles"));
const Projects = lazy(() => import("t9/apps/main/scenes/projects"));
const Learn = lazy(() => import("t9/apps/main/scenes/learn"));
const Contact = lazy(() => import("t9/apps/main/scenes/contact"));

Expand Down Expand Up @@ -86,6 +87,7 @@ export const App: React.SFC<{}> = () => {
<Route path="/" exact={true} component={Landing} />
<Route path="/Learn" component={Learn} />
<Route path="/Articles" component={Articles} />
<Route path="/Projects" component={Projects} />
<Route path="/Contact" component={Contact} />
<Route render={() => <Redirect to="/" />} />
</Switch>
Expand Down
64 changes: 64 additions & 0 deletions frontend/src/apps/main/redux/actions/projects-scene/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { actionType } from "../../constants";
import { Dispatch } from "react";
import { MainStoreStateInterface } from "t9/types/main";
import Axios from "axios";
import { hasInCollection } from "src/common/utils";
import { Project } from "t9/types/fullstack";
import { fullstackConfig } from "src/config";

const dataURL = fullstackConfig.data.url;

export const fetchProjectsList = () => async (
dispatch: Dispatch<any>,
getState: MainStoreStateInterface,
) => {
try {
const response = await Axios.get(dataURL + "/projects/list.c.json");
dispatch({
type: actionType.UPDATE_PROJECTS_SCENE,
payload: { projectsList: response.data },
});
} catch (error) {
console.error(error);
}
};

export const fetchCurrentProject = () => async (
dispatch: Dispatch<any>,
getState: MainStoreStateInterface,
) => {
const projectSlug = location.pathname.substring(
location.pathname.indexOf("/", 1) + 1,
);
const cashedProject = hasInCollection<Project>(
getState().projects,
"slug",
projectSlug,
[["content"]],
);
if (cashedProject) {
// update our scene state
dispatch({
type: actionType.UPDATE_PROJECTS_SCENE,
payload: { currentProject: cashedProject },
});
} else
try {
const response = await Axios.get(
dataURL + `/projects/${projectSlug}.json`,
);
const currentProject = response.data;
// update our scene state
dispatch({
type: actionType.UPDATE_PROJECTS_SCENE,
payload: { currentProject },
});
// update our cache state
dispatch({
type: actionType.UPDATE_PROJECTS,
payload: [currentProject],
});
} catch (error) {
console.error(error);
}
};
2 changes: 2 additions & 0 deletions frontend/src/apps/main/redux/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ export const actionType = {
UPDATE_LEARN_SCENE: "UPDATE_LEARN_SCENE",
UPDATE_ARTICLES: "UPDATE_ARTICLES",
UPDATE_ARTICLES_SCENE: "UPDATE_ARTICLES_SCENE",
UPDATE_PROJECTS: "UPDATE_PROJECTS",
UPDATE_PROJECTS_SCENE: "UPDATE_PROJECTS_SCENE",
};
4 changes: 4 additions & 0 deletions frontend/src/apps/main/redux/reducers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import { documentation } from "./documentation";
import { learnScene } from "./learn-scene";
import { articles } from "./articles";
import { articlesScene } from "./articles-scene";
import { projects } from "./projects";
import { projectsScene } from "./projects-scene";

export const mainReducer = combineReducers({
documentation,
learnScene,
articles,
articlesScene,
projects,
projectsScene,
});
20 changes: 20 additions & 0 deletions frontend/src/apps/main/redux/reducers/projects-scene/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ProjectsSceneProps } from "t9/apps/main/scenes/projects";
import { actionType } from "t9/apps/main/redux/constants";

export const projectsScene = (
state: ProjectsSceneProps = {
projectsList: null,
currentProject: null,
},
action: {
type: string;
payload: ProjectsSceneProps;
},
) => {
switch (action.type) {
case actionType.UPDATE_PROJECTS_SCENE:
return { ...state, ...action.payload };
default:
return state;
}
};
18 changes: 18 additions & 0 deletions frontend/src/apps/main/redux/reducers/projects/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { actionType } from "t9/apps/main/redux/constants";
import { Project } from "t9/types/fullstack";
import { updateCollection } from "src/common/utils";

export const projects = (
state: Project[] = [],
action: {
type: string;
payload: Project[];
},
) => {
switch (action.type) {
case actionType.UPDATE_PROJECTS:
return updateCollection<Project>(state, action.payload, "slug");
default:
return state;
}
};
23 changes: 23 additions & 0 deletions frontend/src/apps/main/scenes/projects/catalog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import "./style";
import { Project } from "t9/types/fullstack";
import { Link } from "react-router-dom";

export const Catalog = (props: { projectsList: Project[] | null }) => (
<div className="catalog">
{props.projectsList
? props.projectsList.map((project, index) => (
<Link
key={`project-${index}`}
style={{
paddingLeft: `${(project.slug.match(/\//g) || []).length + 1}rem`,
}}
className="item"
to={"/Projects/" + project.slug}
>
{project.title}
</Link>
))
: "Loading Projects List..."}
</div>
);
20 changes: 20 additions & 0 deletions frontend/src/apps/main/scenes/projects/catalog/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@import "../../../../../common/style/variables";

.projects {
.catalog {
padding: 1rem;
width: 100%;
display: inline-block;
.item {
display: block;
padding: 1rem;
cursor: pointer;
}
.item:hover {
background-color: wheat;
}
@media screen and (min-width: $regular) {
width: 20%;
}
}
}
80 changes: 80 additions & 0 deletions frontend/src/apps/main/scenes/projects/details/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import React, { useEffect } from "react";
import { Project } from "t9/types/fullstack";
import Markdown from "react-markdown";
import "./style";

import programer from "t9/apps/main/assets/png/programmer.png";
import contact from "t9/apps/main/assets/png/contact.png";
import github from "t9/apps/main/assets/png/github.png";
import support from "t9/apps/main/assets/png/support.png";

const socialMedia = [
{
id: 1,
name: "dzcode",
href: "https://github.com/dzcode-io/dzcode.io",
icon: github,
},
{ id: 2, name: "Learn", href: "/learn", icon: programer },
{ id: 3, name: "Contact", href: "/contact", icon: contact },
{ id: 4, name: "Support", href: "/support", icon: support },
];

export const Details = (props: DetailsInterface) => {
useEffect(() => {
props.fetchCurrentProject();
setTimeout(() => {
window.FB && window.FB.XFBML.parse();
}, 3000);
}, []);
const { currentProject } = props;
return (
<div className="details">
{currentProject ? (
<div>
{/* Image */}
{currentProject.image && (
<img
className="hero-image"
src={currentProject.image}
alt={currentProject.title}
/>
)}
{/* Title */}
<h2 className="title">{currentProject.title}</h2>
{/* Description */}
<small className="description">{currentProject.description}</small>
<hr className="break" />
{/* Details */}
<Markdown className="details" source={currentProject.content} />
<hr className="break" />
{/* Contact + Edit*/}
<div className="actions">
{socialMedia.map((item) => {
return (
<div key={item.id} className="item">
<img src={item.icon} alt={item.name} className="icon" />
<a href={item.href}>{item.name}</a>
</div>
);
})}
</div>
{/* Comments */}
<div
className="fb-comments"
data-href={location.origin + location.pathname}
data-width="100%"
data-numposts="5"
/>
</div>
) : (
"Loading Project..."
)}
</div>
);
};

export interface DetailsInterface {
fetchCurrentProject: () => void;
currentProject: Project | null;
}
76 changes: 76 additions & 0 deletions frontend/src/apps/main/scenes/projects/details/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
@import "../../../../../common/style/variables";

.projects {
.details {
display: inline-block;
vertical-align: top;
width: 100%;
align-self: center;

@media screen and (min-width: $regular) {
width: 80%;
}

.hero-image {
width: 100%;
max-height: 400px;
object-fit: cover;
}

.title {
font-size: 3rem;
margin: 1rem;
}

.description {
margin: 1rem;
}

.break {
margin: 1rem 1rem 0;
}

.details {
margin: 0 1rem;
width: 100%;
}

.actions {
width: 100%;
height: 100px;
display: flex;
width: 60vw;
flex-direction: row;
align-items: center;
justify-content: space-evenly;
.item {
font-size: 1.1rem;
font-weight: 600;
display: flex;
align-items: center;
padding: 1rem;
width: 120px;
z-index: 5;
cursor: pointer;

&:hover {
transform: scale(1.1);
}

a {
text-decoration: none;
color: $text-primary;
}
}

.icon {
width: calc(30px + 1vw);
height: calc(30px + 1vw);
margin-right: 20px;
}
}

.fb-comments {
}
}
}
Loading

0 comments on commit 5e79474

Please sign in to comment.