npm create vite@latest npm i tailwindcss postcss autoprefixer -D npx tailwindcss init -p npm i phosphor-react npm i date-fns npm i @vime/core @vime/react --force (incompatibilidade com react 18) // Default theme. ~960B import '@vime/core/themes/default.css';
npm i react-router-dom npm i classname
npm install @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-operations @graphql-codegen/typescript-react-apollo -D
query = buscar dados mutation = alterar informações CMS = Content Management System Headless CMS- GraphCMS - Painel de admin (dados fornecidos através de uma API REST ou GraphQL) https://graphcms.com/ http://rseat.in/lab-graphcms
- CMS headless pra ecommerce?
- Shopify, Saleor ou Medura
query MyQuery {
lessons {
id
slug
title
teacher {
bio
avatarURL
name
}
}
}
npm i @apollo/client graphql
import { ApolloClient, InMemoryCache } from '@apollo/client';
export const client = new ApolloClient({ uri: 'https://api-ap-southeast-2.graphcms.com/ ...', cache: new InMemoryCache() })
const GET_LESSONS_QUERY = gql`
query {
lessons {
id
title
}
}
`;
useEffect(() => {
client
.query({
query: GET_LESSONS_QUERY,
})
.then((response) => {
console.log(response.data);
});
}, []);
import { gql, useQuery } from '@apollo/client';
const GET_LESSONS_QUERY = gql`
query {
lessons {
id
title
}
}
`;
const { data } = useQuery<{ lessons: Lesson[] }>(GET_LESSONS_QUERY);
import { gql, useQuery } from '@apollo/client';
const GET_LESSONS_BY_SLUG_QUERY = gql`
query GetLessonBySlug($slug: String) {
lesson(where: { slug: $slug }) {
description
title
videoId
teacher {
avatarURL
bio
name
}
}
}
`;
interface GetLessonBySlugResponse {
lesson: {
description: string;
title: string;
videoId: string;
teacher: {
avatarURL: string;
bio: string;
name: string;
};
};
}
interface VideoProps {
lessonSlug: string;
}
const { data } = useQuery<GetLessonBySlugResponse>(GET_LESSONS_BY_SLUG_QUERY, {
variables: {
slug: props.lessonSlug,
},
});
import { gql, useMutation } from '@apollo/client';
const CREATE_SUBSCRIBE_MUTATION = gql`
mutation CreateSubscriber($name: String!, $email: String!) {
createSubscriber(data: { name: $name, email: $email }) {
id
}
}
`;
export function Subscribe() {
const navigate = useNavigate();
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [createSubscriber, { loading }] = useMutation(
CREATE_SUBSCRIBE_MUTATION
);
const handleSubmit = async (event: FormEvent) => {
event.preventDefault();
await createSubscriber({
variables: {
name,
email,
},
});
navigate('/event');
};
- Cria pasta graphql/mutation e graphql/queries
- adiciona as queries e mutations em arquivos
- cria um arquivo codegen.yml
- adciona a URI
Agora é só chamar o hook import { useGetLessonBySlugQuery } from './../graphql/generated';
interface VideoProps { lessonSlug: string; }
export function Video(props: VideoProps) { const { data } = useGetLessonBySlugQuery({ variables: { slug: props.lessonSlug, }, });
schema: URI
documents: './src/graphql/**/*.graphql'
generates:
./src/graphql/generated.ts:
plugins:
- typescript
- typescript-operations
- typescript-react-apollo
config:
reactApolloVersion: 3
withHooks: true
withHOC: false
withComponents: false
Adciona no package.json e executa "codegen": "graphql-codegen"
Medidas são múltiplas de 4
@tailwind base;
@tailwind components;
@tailwind utilities;
body {
@apply bg-zinc-900 text-zinc-100;
}
theme: {
extend: {
fontFamily: {
sans: 'Roboto, san-serif',
},
colors: {
colors: {
green: {
300: '#00B37E',
500: '#00875F',
700: '#015F43',
}
},
},
}
}
.leading-relaxed {
line-height: 1.625;
}
Três valores: flex-grow | flex-shrink | flex-basis
.flex-1 {
flex: 1 1 0%;
}
Smooth the font on the level of the pixel, as opposed to the subpixel. Switching from subpixel rendering to antialiasing for light text on dark backgrounds makes it look lighter.
--webkit-font-smoothing: antialiased
The CSS property aspect-ratio lets you create boxes that maintain proportional dimensions where the height and width of a box are calculated automatically as a ratio. .aspect-video { aspect-ratio: 16 / 9; }
const isLessonAvailable = isPast(props.availableAt) const availableDateFormatted = format(props.availableAt, "EEEE' • 'd' de 'MMMM' • 'k'h'mm", {locale: ptBR})
theme: {
extend: {
backgroundImage: {
blur: 'url(/scr/assets/images/bg.png)'
}
}
}
<div className='min-h-screen bg-blur bg-cover bg-no-repeat'> </div>
Cadastra dados, alterar e deletar => Fazer no backend
className={classNames(
'border border-gray-500 p-4 rounded group-hover:border-green-500',
{
'bg-green-500': isActiveLesson,
}
)}
- Mudar as cores
Ideias:
- Criar componente de botão
- Login - Não permitir pessoas que não estão inscritas a entra na parte de evento: inscrição de github - token no localstorage
- implementar mais validações no form e feedback,
- adicionar um avatar do usuário logado, no header, trazendo do github a imagem dele
- ir para ultimo aula vista
- Admin criar aulas e professores, excluir aulas e professores